diff --git a/.gitignore b/.gitignore index 57cc6bdb7..559203ed9 100644 --- a/.gitignore +++ b/.gitignore @@ -138,3 +138,5 @@ gradle-app.setting build.gradle.deploy prison-spigot/lib/old/ +prison-spigot/lib/disabled/ +zip_snapshots/ diff --git a/PrisonSpigotMC/index.html b/PrisonSpigotMC/index.html new file mode 100644 index 000000000..c23eaf0a6 --- /dev/null +++ b/PrisonSpigotMC/index.html @@ -0,0 +1,79 @@ + + + + + + + Prison - Test Document Titles + + + + + +
+ + + + + PRISON + + + +
+ +
+ +
+
+ +
+ + \ No newline at end of file diff --git a/build.gradle b/build.gradle index eca3fcf16..187e2a62f 100644 --- a/build.gradle +++ b/build.gradle @@ -22,15 +22,15 @@ import java.util.Date buildscript { - repositories { - mavenCentral() - gradlePluginPortal() - - } + repositories { + mavenCentral() + gradlePluginPortal() + + } - dependencies { - classpath 'com.github.johnrengelman:shadow:8.1.1' - } + dependencies { + classpath 'com.github.johnrengelman:shadow:8.1.1' + } } @@ -39,7 +39,7 @@ plugins { id 'java' id 'base' -// alias(libs.plugins.shadow) +// alias(libs.plugins.shadow) id 'com.github.johnrengelman.shadow' version '8.1.1' } @@ -48,6 +48,11 @@ base { archivesName = 'Prison' } +// Ensure all Java compilation across the entire project uses UTF-8 natively +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = "UTF-8" @@ -65,8 +70,8 @@ ext.targetArchiveClassifier = 'Java1.8' java { toolchain { - languageVersion.set(JavaLanguageVersion.of(8)) -// languageVersion.set(JavaLanguageVersion.of(16)) + languageVersion.set(JavaLanguageVersion.of(8)) +// languageVersion.set(JavaLanguageVersion.of(16)) } } @@ -74,20 +79,20 @@ java { /* task('Build-Java8', type: JavaCompile ) { - javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(8) - } - - ext.targetArchiveClassifier = 'java1.8' + javaCompiler = javaToolchains.compilerFor { + languageVersion = JavaLanguageVersion.of(8) + } + + ext.targetArchiveClassifier = 'java1.8' } task('Build-Java16', type: JavaCompile ) { - javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(16) - } - - ext.targetArchiveClassifier = 'java16' + javaCompiler = javaToolchains.compilerFor { + languageVersion = JavaLanguageVersion.of(16) + } + + ext.targetArchiveClassifier = 'java16' } */ @@ -104,14 +109,14 @@ println """ ========================================================================== You are building the Prison plugin Prison Version: ${project.version} - Build time: ${getCurrentTimestamp()} - Java version: - Test value: ${targetArchiveClassifier} + Build time: ${getCurrentTimestamp()} + Java version: + Test value: ${targetArchiveClassifier} Output files are located in [subproject]/build/libs. The runnable JAR is usually named Prison-.jar. Example: The spigot build artifact is: - prison-spigot/build/libs/Prison-${project.version}.jar + prison-spigot/build/libs/Prison-${project.version}.jar ========================================================================== """ @@ -119,54 +124,244 @@ Example: The spigot build artifact is: subprojects { - apply plugin: 'java' - apply plugin: 'com.github.johnrengelman.shadow' -// apply plugin: 'maven' -// apply plugin: 'maven-publish' + apply plugin: 'java' + apply plugin: 'com.github.johnrengelman.shadow' +// apply plugin: 'maven' +// apply plugin: 'maven-publish' -// archivesBaseName = 'Prison' - - - group = 'tech.mcprison.prison' - -// sourceCompatibility = 16 -// targetCompatibility = 16 -// sourceCompatibility = 1.8 -// targetCompatibility = 1.8 - - repositories { - mavenCentral() - // maven { url "https://maven.sk89q.com/repo/" } +// archivesBaseName = 'Prison' + + group = 'tech.mcprison.prison' + + java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + } + } - maven { - url "https://mvnrepository.com/artifact" - } - } - - configurations { - deployerJars - } + configurations { + deployerJars + } - dependencies { - - implementation( libs.commons.lang3 ) + dependencies { + + implementation( libs.commons.lang3 ) implementation( libs.gson ) implementation( libs.guava ) - testImplementation( libs.junit ) - - } + testImplementation( libs.junit ) + + } } wrapper { - distributionType = Wrapper.DistributionType.ALL + distributionType = Wrapper.DistributionType.ALL +} + +tasks.register('zipSource', Zip) { + group = 'prison' + description = 'Creates a versioned ZIP of source, resources, and all Gradle/AI metadata.' + + archiveBaseName = "Prison-Context" + archiveVersion = project.version + destinationDirectory = file("$rootDir/zip_snapshots") + + // 1. Root Orchestration Files + from(rootDir) { + include 'build.gradle' + include 'settings.gradle' + include 'gradle.properties' + include 'gradle/libs.versions.toml' + } + + // 2. The "Brain" Folder (Your AI metadata) + from("$rootDir/zipDocs") { + into('metadata') + } + + // 3. Sub-project Source, Resources, and their specific build.gradle + subprojects.each { sub -> + from(sub.projectDir) { + include 'src/main/java/**' + include 'src/main/resources/**' + include 'build.gradle' // Each module's specific build file + + into(sub.name) + } + } + + // Exclusions to keep the "Millionaire" tokens focused + exclude '**/build/**' + exclude '**/.gradle/**' + exclude '**/.settings/**' + exclude '**/bin/**' + exclude '**/out/**' } + +tasks.register('concatSource') { + group = 'prison' + description = 'Concatenates source, resources, and metadata into a single AI-friendly text file.' + + // Set the output directory and filename + def outputDir = file("$rootDir/zip_snapshots") + def outputFile = new File(outputDir, "Prison-Context-${project.version}.txt") + + // The actual work must happen in the execution phase (doLast) + doLast { + outputDir.mkdirs() + + // Clear the file if it already exists from a previous run + if (outputFile.exists()) { + outputFile.text = '' + } else { + outputFile.createNewFile() + } + + println "Generating AI context file at: ${outputFile.absolutePath}" + + // Helper closure to process a file tree and append to the text file + def processTree = { FileTree tree -> + tree.matching { + // Your standard exclusions + exclude '**/build/**' + exclude '**/.gradle/**' + exclude '**/.settings/**' + exclude '**/bin/**' + exclude '**/out/**' + // Added safeguards: prevent sneaky binary files in resources from turning to gibberish + exclude '**/*.png', '**/*.jpg', '**/*.jpeg', '**/*.gif', '**/*.ico', '**/*.jar', '**/*.zip' + }.each { File f -> + if (f.isFile()) { + // Calculate the relative path from the root directory + def relativePath = rootDir.toPath().relativize(f.toPath()).toString() + + // Normalize separators so Windows backslashes become standard forward slashes + relativePath = relativePath.replace('\\', '/') + + // Append the header and file contents + outputFile.append("================================================================\n") + outputFile.append("File: ${relativePath}\n") + outputFile.append("================================================================\n") + outputFile.append(f.text + "\n\n") + } + } + } + + // 0. The Prime Directives (Force these to the absolute top) + // The "Brain" Folder + def brainFilesSI = fileTree(dir: "$rootDir/zipDocs", + includes: ['SYSTEM_INSTRUCTIONS.md']) + processTree(brainFilesSI) + + def brainFiles = fileTree(dir: "$rootDir/zipDocs", + excludes: ['SYSTEM_INSTRUCTIONS.md']) + processTree(brainFiles) + + + // 1. Root Orchestration Files + def rootFiles = fileTree(dir: rootDir, includes: [ + 'build.gradle', + 'settings.gradle', + 'gradle.properties', + 'gradle/libs.versions.toml' + ]) + processTree(rootFiles) + + // 2. Sub-project Source, Resources, and specific build scripts + // Define the sub-projects you want to skip + def excludedProjects = ['prison-spigot-alt', 'prison-worldguard7'] + + subprojects.each { sub -> + // Only process the sub-project if its name is NOT in the excluded list + if (!excludedProjects.contains(sub.name)) { + def subFiles = fileTree(dir: sub.projectDir, includes: [ + 'src/main/java/**', + 'src/main/resources/**', + 'build.gradle' + ]) + processTree(subFiles) + } + } + + println "Successfully concatenated Millionaire tokens into ${outputFile.name}" + } +} + +tasks.register('exportGradleConfigs') { + group = 'help' + description = 'Exports all Gradle configuration files into a single timestamped text file for review.' + + doLast { + // Create the timestamped filename + def df = new SimpleDateFormat("yyyy-MM-dd_HH-mm") + def timestamp = df.format(new Date()) + def outputFile = file("gradle_project_settings_${timestamp}.txt") + + // Initialize/clear the file + outputFile.text = "" + + // Define the explicit order of core files to pull from the root + def coreFiles = [ + "this_file_does_not_exist.txt", + "gradle/libs.versions.toml", + "gradle/wrapper/gradle-wrapper.properties", + "gradle.properties", + "settings.gradle", + "build.gradle" + ] + + // Helper closure to write a file's content with the requested formatting + def appendFile = { String relativePath -> + def targetFile = file(relativePath) + outputFile.append("=====================================================\n") + outputFile.append("-- File: ${relativePath}\n") + + if (targetFile.exists()) { + // Grab and format the file metadata + def sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm") + def numFormat = new java.text.DecimalFormat("#,###") + + def lastModDate = sdf.format(new Date(targetFile.lastModified())) + def fileSize = numFormat.format(targetFile.length()) + + outputFile.append("-- Modified: ${lastModDate}\n") + outputFile.append("-- Size: ${fileSize} bytes\n") + outputFile.append("--\n\n") + outputFile.append(targetFile.text + "\n\n") + } else { + outputFile.append("-- (File not found or empty)\n\n") + } + } + + // 1. Process the explicitly ordered core files + coreFiles.each { appendFile(it) } + + // 2. Iterate through all subprojects and grab their build.gradle files + subprojects.each { sub -> + def subBuildFile = sub.buildFile + if (subBuildFile.exists()) { + // Get the path relative to the root project (e.g., "aers-web/build.gradle") + def relativePath = rootProject.relativePath(subBuildFile) + // Normalize slashes for consistency in the text file + relativePath = relativePath.replace('\\', '/') + appendFile(relativePath) + } + } + + println "===================================================" + println " SUCCESS: Configuration files consolidated!" + println " File saved to: ${outputFile.absolutePath}" + println "===================================================" + } +} + + def getCurrentTimestamp() { SimpleDateFormat df = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss") diff --git a/docs/changelog_v3.3.x.md b/docs/changelog_v3.3.x.md index 060a66256..3b23de62e 100644 --- a/docs/changelog_v3.3.x.md +++ b/docs/changelog_v3.3.x.md @@ -1,10 +1,10 @@ [Prison Documents - Table of Contents](prison_docs_000_toc.md) -## Prison Build Logs for v3.3.x +## Prison Build Logs for v3.3.1 ## Change logs - - **[v3.3.0-alpha - Current](changelog_v3.3.x.md)** - - [v3.2.0 through v3.3.0-alpha.17](prison_changelogs.md) + - **[v3.3.1 - Current](changelog_v3.3.x.md)** + - [v3.2.0 through v3.3.0-alpha.19](prison_changelogs.md) * [Known Issues - Open](knownissues_v3.2.x.md) * [Known Issues - Resolved](knownissues_v3.2.x_resolved.md) @@ -13,2477 +13,84 @@ These change logs represent the work that has been going on within prison. +# 3.3.1 2026-06-15 -# 3.3.0-alpha.18a 2024-05-21 - - -**v3.3.0-alpha.18a 2024-05-21** -Releasing this alpha.18a because the fix of the of the new player bug was crippling servers. - - -* **Bug Fix: When a new player was joining prison, and there were placeholders being used in the rank commands for either the default ladder, or the first rank, the resolution of the placeholders was triggering a new player on-join processing within prison.** -This happed because the new RankPlayer object was not being added to the PlayerManager before ranking the player... now the player's object will be there when the rank commands are processed. -Honestly have no idea why this has not been an issue in the past.... - - -* **Docs... added curseForge.com to the list of locations where prison can be downloaded from.** - - - -* **Fix to the docs... for some reason, eclispse, or one of it's plugins failed and corrupted the markdown.** -I did not realize it was corrupted since it was still showing the correct content, but when restarting the IDE and loading the files, they were missing the first characters. - - -**Prison v3.3.0-alpha.18 2024-05-20** - -This version has been tested and confirmed to be working with Spigot v1.20.6 and Paper v1.20.6. - - - -* **Player Ranks GUI: Fixed an issue with the code not using the correct defaults for NoRankAccess when no value is provided in the configs.** - - -* **Obsolete blocks: Marked an enum as @Deprecated to suppress a compile warning.** This has not real impact on anything. - - -* **Gradle updates:** -Upgraded XSeries from v9.10.0 to v10.0.0 -Upgraded nbtApi from v2.12.2 to v2.12.4 -Upgraded luckperms-v5 from v5.0 to v5.4 - - -* **Economy: Added a feature to check if a player has an economy account.** -Currently this is not being used outside of the economy integrations, but it can be used to help suppress initial startup messages where players do not have an account, which will help prevent flooding a lot of messages to the console for some servers. - - -* **Player Cache: There was a report of a concurrent modification exception.** -This is very rare and generally should not happen. -The keySet is part of the original TreeMap collection, so the fix here is to take all keys and put them in a new collection so they are then disconnected from the original TreeSet. -This will prevent a concurrent modification exception if there is an action to add or remove users from the user cache, since the user cache remains active and cannot be locked with a synchronization for any amount of time, other than then smallest possible. -The standard solution with dealing with this TreeSet collection would be to synchronize the whole activity of saving the dirty elements of the player cache. Unfortunately, that will cause blocking transactions when player events try to access the player cache. Therefore it's a balance game of trying to protect the player cache with the minimal amount of synchronizations, but allow the least amount of I/O blocking for all other processes that are trying to use it. -Hopefully this is sufficient to allow it all to work without conflict, and to be able to provide enough protection. - - -* **Gradle: Removed a lot of the older commented out settings.** -See prior commits to better understand how things were setup before, or for references. - - -* **Gradle: A few more adjustments to add a few more items to the libs.versions.toml.** - - - -* **Placeholders: The placeholder api call from PlaceholderAPI is passing a null OfflinePlayer object.** -Not sure why this has never been an issue before, but added support for null OfflnePlayers. - - - -* **Spiget: Updated the way prison handles spiget by now submitting a task with a 5 second delay.** -The messages are more helpful now. -This also moves it out of the SpigotPrison class. - - -* **Upgraded John Rengelman's shadow, a gradle plugin, from v6.1.0 to v8.1.1** - - - -* **Upgrade gradle from v7.6.4 to v8.7** - Upgraded from: v7.6.4 -> v8.0 -> v8.0.2 -> v8.1 -> v8.1.1 - -> v8.2 -> v8.3 -> v8.4 -> v8.5 -> v8.6 -> v8.7 - v8.3 required a configuration change due to `org.gradle.api.plugins.BasePluginConvention` type has been deprecated and will be removed in gradle v9.x. This is impacting the use of the `build.gradle`'s `archivesBaseNamme`. This is being replaced by the new `base{}` configuration block. - v8.3 also required other config changes. - - - -* **Upgrade spiget from v1.4.2 to v1.4.6** - Was using a jar with v1.4.2 due to their repo going down frequently. - Switched back to pulling through maven and got rid of jar. - - -* **Upgrade gradle from v7.3.3 to v7.6.4** - Upgraded from: v7.3.3 -> v7.4 -> v7.4.1 -> v7.4.2 - -> v7.5 -> v7.5.1 -> v7.6 -> v7.6.1 -> v7.6.2 -> v7.6.3 -> v7.6.4 - Preparing for Gradle v8.x - Around v7.5.1 required a change to auto provisioning - - -**v3.3.0-alpha.17a 2024-04-29** - - -* **GUI settings: Update them to remove unused stuff.** - - -* **GUI Tools messages: refined the messages and hooked them up.** - - -* **Initial setup of the GUI tools messages that are at the bottom of a page.** -Setup the handling of the messages and added the messages to all of the language files. -Support for prior, current, and next page. Also c -* **Update the plugin.yml and removed the permissions configs since they were generating errors (lack of a schema) and the perms and handled through the prison command handler.** - - - -* **CustomItems: Fixed an issue when CustomItems is a plugin on the server, but the plugin fails to load.** -Therefore the problem was fixed to allow a failed CustomItems loading to bypass being setup and loaded for prison. -`CustomItems.isEnabled()` must exist and return a value of true before the integration is enabled. - - -* **XSeries XMaterials: Update to XSeries v9.10.0 from v9.9.0.** -Had issues with case sensitivity when using `valueOf()`, which was changed to `matchXMaterial().orElse(null)` which resolves a few issues. -XMaterials v9.10.0 sets up support for spigot 1.20.5. There may be more changes as spigot stabilizes. -The issue with using `valueOf("green_wool")` would not find any matches since the enum case must match the string value exactly. So `valueOf("GREEN_WOOL")` would have worked. This was fixed to help eliminate possible issues with configuring the server. - - -* **Auto features: normal drop processing: Added a new feature to check inventory for being full, and if it is, then display the messages.** - - - -* **Auto features: Inventory full chat notification: bug fix. This fixes using the wrong player object.** -It now use prison's player object so the color codes are properly translated. - - -* **Placeholders: bug fix: When using a search from the console which included a player name, it was generating an invalid cast to a SpigotPlayer object when it wasn't related to that class due to the player being offline.** - - -* **GUI: ranks and mines: setup and enable a new default access block type that can be used if that rank or mine has not been specifically specified.** - - -* **GUI: tool bar's prior page and next page: Suppress the page buttons if there is only one page worth of gui content. ** - - -* **GUI: Player ranks: Fixed a bug where clicking on a rank in the player's gui was trying to run an empty command, which was generating an invalid command error.** -Ignores the command running if the command is either null or blank. - - - -* **Update to plugin.yml since some soft dependencies were missing.** - - -* **Economies: fixed the display of too many economy related messages, including eliminating logging of messages for offline players.** -The vault economy check for offline players, will now only show one informational message if a player is not setup in the economy. - - -* **GUI Player ranks: The setting for Options.Ranks.MaterialType.NoRankAccess was not hooked up properly so it was not really working.** -The config creation was wrong. Also fixed the code that was generating the gui. - - -* **RankPlayer and topn ranking: This may not have an impact overall, but for both the default and prestiges ladders, they are defaulting to a value of -1 when performing a comparison between players.** - - -* **Update privatebin-java-api to a newer release that now does a better job with a failure to use the correct protocol.** -It identifies what TLS version is being used, and if TLSv1.3 is missing, then it will indicate that the java version needs to be updated. -As a fallback, if the privatebin cannot be used, it is now using the older paste.helpch.at service. But if it does, the resulting documents are not purged and not encrypted. - - -* **Economy: EdPrison's economy. Added support for use of EdPrison's economy and custom currencies.** -This will allow prison to use EdPrison's economy does not also use another established economy that is accessible through vault, or multi-currency. - - - -# 3.3.0-alpha.17 2024-04-20 - -**v3.3.0-alpha.17** 2024-04-20 - - - -* **Mines messages: Secondary placeholders. Added support for mines' messages to be able to support secondary placeholders within the language files. NOTE: Not usable at this time.** -But... this is basically useless. Within the mines language files, the vast majority of all messages are related to admin messages and are not viewable by the players. -Therefore the admin-only messages will not support the secondary placeholders since the players will never see them. -At this time, there are no messages that supports the use of these secondary placeholders, although the feature has been enabled for mines. -If a need is required, then please reach out and request such features should be enabled. At this time, effort and work will not be performed blindly upon items that will never be used, so if you see a need for this, I'd be happy to add them since you would have a need. - - - -* **Placeholder bug: The placeholder 'prison_rankup_cost_percent' uses the calculated value of a percentage, but when used with the placeholder attribute, it was found to use the price instead.** As such, the actual value returned for the placeholder was incorrect. - - -* **Player Manager: Secondary Placeholders: Setup the secondary placeholder support on the PlayerManager, but it has not been enabled yet** since secondary placeholders on placeholders do not make a lot of sense because each placeholder is only one value and they cannot contain alternative text. At least not yet. - - -* **Localizable: Secondary placeholders: Rewrote the whole support of secondary placeholders related to players.*** -Expanded the support by making them generic so other data sources can also have their own custom set of placeholders too. Such as mines. -This now supports a new interface that will provide the generic support. -Player's commands have been modified to pass a RankPlayer object, which supports the new interface. Non-player commands have not been converted since players will never see those messages (such as admin commands). - - -* **Added a comment in the ranks message files indicating that there is now some support for player based placeholders to farther customize messages.** -This also fixes an issue with the broadcast messages to use the intended player instead of the target player who is being sent the message. - - - -* **Localization: If admin adds extra parameters, or other parsing failures, happens on a message, the error will now be trapped and logged to the console without formatting.** - - - -* **Economy: For economies that prison supports that has a method to check if the player has an account, prison now tries to check if there is an account for the player before trying to use the economy.** -This could potentially prevent issues or run time failures. - - -* **Prison API: Added a few new functions to work with ItemStacks.** - - - -* **Players: Shift the function of getting a player object to the Player classes, such as CommandSender.** -This is to simplify the code and to put the functionality in one location. - - - -* **Sellall: New command: '/sellall items inspect'** -This new command will inspect what the player is holding, and dump the details so the admin can see exactly how an item/block is created, including lore and enchantments. -Eventually this information can be used to enhance the ability to sell and buy non-standard items by allowing the admins to filter on lore, enchantments, and/or NBTs. - - - -* **SpigotPlayer: Fixed a potential issue if trying to use getRankPlayer() if the ranks module is not enabled.** -Added a check to ensure it's active. -We have not seen any reports of issues related to this. - - - -* **Prison Player: Added a new sendMessage function using Lists of Strings. ** -Added a new function getPlatformPlayer() which gets a bukkit player object if the player is online. This will consolidate a lot of other duplicate code. - - -* **Mine Bombs: wrapped up the changes to enable the placement of a mine bomb when using the BlockPlaceEvent which is used when using a block for the bomb's item.** - - -* **Prison ItemStack: remove enchantments from the core ItemStack since prison cannot properly represent it in versions lower than 1.13.x**, plus it was wrong for all spigot versions greater than 1.12.x. -Added the proper enchantment functions to the SpigotItemStack object. - - -* **Initial setup of sellall lore filtering** -A little clean up. - - -**3.3.0-alpha.16c 2024-03-11** - - -* **PlaceholderAPI: Upgrade from v2.11.2 to v2.11.5** - - -* **XSeries: Upgrade from v9.8.0 to v9.9.0** - - -* **Mine bombs: add support for BlockPlacementEvent so if someone is using a Block they can use it as the mine bomb's item.** - - -* **Prison's NBT: Add support for using NBTs with bukkit's Block.** - - -* **Add support for getting the "hand" from the BlockPlaceEvent.** - - -* **Prison support listeners: added support for listening to and providing dumps for PlayerDropItemEvent, PlayerPickupItemEvent, and BlockPlaceEvent.** - - -* **Promote & Demote: Improved upon reporting issues with the command.** -There were few situations where the command would exit without reporting why, which was leading to difficulties with using the command effectively. - - -* **New feature: TopN customization now possible. The messages and placeholders that you can use are located in the core multi-language files.** -See the bottom of the files for instructions on usage. -TopN data is set to delay load so it does not lengthen the startup process. As such, it now reports that the data is being loaded so it is now clear why there are no entries in the list initially. - - -* **Mines: eliminate a field no longer used: includeInLayerCalculations.** -This was obsoleted with better use of logic. - - -* **Mine resets: Reworked how prison is selecting random blocks per layer, to properly include constraints.** -The addition of various new features in the past made a mess of the logic, so it's been cleaned up greatly so it now makes sense and should work properly now. -There is a slight risk, that as blocks are removed from a layer due to reaching it's max constraint value, that future random selections were missing blocks selections and was then inserting AIR. This fixed code now will insert a filler block which has been selected with no constraints, and the largest chance value. - - -* **mines block layerStats: rewrote to improve and get rid of the collection manipulations.** -Found potential problem with air being inserted in to mines. -Renamed a lot of uses of Location objects to include the name "location" in their variable names instead of "block". - - -* **Mines block layer: Added colors for same IDs so it's easier to read.** Added a check that sees what block actually exists. If counts of what should have spawned match whats in the mine for that layer, then it shows only one number. It shows two numbers if a block's intended spawn does not match what's in the mine. - - -* **Mine reset: added a force to the reset so it will ignore an existing mine reset and allow a new one to begin.*** -When a mine is being reset, there is no way to actually cancel it. So this allows a large mine to undergo multiple concurrent resets. Use at your own risk. - - - -* **Bug fix: the check for the time the reset has been going on was incorrect and was fixed.** -Also all the code for submitting the reset task was moved in to the mutext. Now, if the reset got hung up, this will properly terminate it and resubmit it. - - -* **File format: Eliminate the check for file types since there is only one.** -Currently there isn't a setting to specify what it should be. - - -* **Mines block layerStats: Added a new command that shows which blocks are in each layer in the mine.** -There are a lot of future enhancements that can be added to this command, such as checking the actual blocks to see if they are still there, or if there was a problem with the spawning of the blocks. - - -* **Block lists: Added the total chance percentage to be displayed with the blocks.** - - -* **File output technique: Changes to how the "replace" existing files works.** -If the file does not exist, then it opens it to create it, otherwise it truncates it. - - -* **Mine bombs: Ability to prevent a bomb's blocks from count towards the player's block totals.** - - -* **Sellall and autosell: Refinements were made to the handling of the sellall settings to better stabilize the use of the commands.** Setting status for the players were moved to the player objects and is now used in all of the related calculations so there is better stability and consistency. - - -* **Mines import: prevent the processing of an importing of a mine if there are problems with the mine's name, or locations.** - - -* **AutoSell: Bug fix: When autosell and sell on inventory is full was all turned off, it would still sell.** -This fixes some of the logic to simplify the code, and to fix those issues. - - -* **Mine skip reset messaging: Did not have it hooked up in the correct location, so the skip messages were not happening.** - - -* **Mine reset: Under heavy load when performing a mine import, there were seen occasionally errors with concurrent modification errors.** -Code was changed to minimize that possibility. - - -* **Sellall and GUI message failures: a number of messages that would indicate the player does not have access to that command were changed to remove the permission from the message.** -This was requested by a couple of admins because they did not want the players to see the internal workings that would otherwise control how the software would behave. - - - -* **Mine imports: Fix some minor issues to get this to work even better.** - - -* **Mine skip reset: If a mine is reset, send a message to players, but only if the message is defined and not empty: 'skip_reset_message='** - - - -* **Player sellall Multipliers: Fixed the ranks multiplier to include all ranks that are defined within the sellall multipliers.** -Added a new function that will gather and list all multipliers that go in to the calculation of the player's total multipliers, which includes the rank multipliers (the sellall multipliers) and also permission based multipliers. -This detailed list of the individual multipliers, is viewable for each player that is online with the command `/ranks player ` and reveals the actual details of how it's calculated. - - - -**3.3.0-alpha.16b 2024-02-24** - - -* **Import Mines: Added the ability to import mines from JetPrisonMines config files.** -`/mines import jetprisonmines help` - - -* **Prison Command Handler: using config.yml you can now change all of prison's root commands with 'prisonCommandHandler.command-roots'.** -Can now map 'prison', 'mines', 'ranks', 'gui', 'sellall' to all new command that you want. - - -* **File saving: alternative technique for saving files. Do not use!** -This is a more dangerous technique that could possibly result in lost configurations. This is being provided as a degraded service if the fail-safe technique is not working ideally on a degraded server. -This should never be used, unless directed by a prison support admin. - - - -* **Prison startup bug: There was an issue with the prison startup when there was an error and prison tried to log the error**, only to find that resources that were needed for logging were not yet loaded nor were their dependencies. This fixes some of the entanglements to allow the error messages to be properly logged. - - -* **Bug fix: GUI configuration: Found a problem that when configuring the gui initial settings, that there were problems when trying to access mines and ranks when they don't yet exist.** - - -* **Add prison debug option to filter on blockConstraints when regenerating the blocks within the mines.** - - -* **Bug fix: prison support submit: if the bukkit system cannot extract a file from the jar**, such as plugin.yml, this will prevent the failure of the command. This will allow the command to continue being processed, but may just skip the extraction. - - - -* **Placeholders: Top player rank was using the wrong ladder, which was incorrectly the prestiges rank and not the default rank.** -Correcting the rank fixed the problem. This only was an issue if the player did not have a prestige rank. - - - -* **Mines set resetTime: fix typo in the description where it shows '*all' instead of '*all*'.** - - -* **ranks ladder: applyRanksCostMultiplier command was changed to allow the value of 'true' to be used along with the value of 'apply'.** This helps to eliminate some confusion on how the command works. - - -* **Bug fix: Prison command handler. When players are de-op'd, and they do the commands such as `/ranks help` or `/mines help` it was incorrectly showing other sub commands they did not have access to.** -This now shows the correct sub commands that they have access to. - - -* **Placeholders: topn players - bug fix. If a player did not have a prestige rank, then it would cause a NPE when using the `prison_top_player_rank_prestiges_nnn_tp` placeholder.** -Just check to ensure its not null... if it is, then return an empty string. - - -* **Bug fix: Player manager startup: fixed a problem where all players were being updated** even though they did not have a name change. Only when name changes are detected are the files updated or when a new player is found. - - -* **Add debug statements to identify how each block was calculated during a mine reset.** - - -* **Bug fix: block constraints: fix an issue with the selection of lower limits.** - - -* **updated the help on the `/mines block constraint` to indicate that the layer count is originating from the top, not the bottom.** - - -* **alpha.16a - 2023-12-28** - NOTE: I just noticed that alpha.16a was never committed. So this is not the correct location of when it was set with the local builds. - - -* **Mines: Fixes an issue for when mines are disabled and they are being checked in other processes to see if they are active.** -If the instance of PrisonMines is null, then it will create a temp instance just to prevent an NPE. - - -* **Mines unit tests: Setup a new constructor for mines that is only to be used with unit tests which allows the mines to be created,** but it does not initialize them since such tasks and processes are not needed in the unit tests. -As a side effect, these two unit test run much faster since it's not trying to setup tasks. - - -* **Prison Block change: Add support for display name, which is optional.** -Setup sellall so it can use the display name now, so renamed items will not be mistaken for vanilla minecraft items. -More work needs to be done to hook up displayName to other features, such as sellall and add prison block to mines. - - -* **Bug fix: Fixed the command `/mines set accessPermission` where it was apply the given perm to all mines.** - Likewise, all mines parameter was failing to do anything. - - -* **NOTE: This alpha version "should" support spigot 20.0.4.** -After a few days, if no other issues surface pertaining to 20.0.4, or other related plugins, this will be released as a public release. - - -* **Fix issue with BlockEvent's SellAll when isAutoSellIfInventoryIsFullForBLOCKEVENTSPriority feature is enabled.** -This was not using the correct new functions that checks to see if a player can use autsell, or if they have it temporarily toggled off. This also checks to see if the player has the correct perms, if perms are enabled for the sellall event. - - -* **Breaking change in XSeries: GRASS has been changed to SHORT_GRASS for v20.0.4!** It's disappointing to say the least that after all of these damn years, XSeries screwed up and pushed a breaking change to their repo. They should have kept GRASS so they would have remained compatible will all past code and configs that had to refer to GRASS directly, but nope... they opted for causing problems. Very disappointing. -Setup a converter to automatically convert all GRASS to SHORT_GRASS as the mines are loaded. - - - -* **Upgrade XSeries from v9.7.0 to v9.8.0.** -* **Upgrade nbt-api from v2.12.0 to v2.12.2.** - - -* **config.yml - changed the default values for remapping aliases and restricting players from using commands.** -The default, which used `/mines tp` was actually causing conflict with normal usage. - - -* **AutoFeatures auto permissions: enable the ability to 'disable' the perms.** Any op'd player, if perms are enabled, will have these auto features enabled. There is no other way around this, since this is the correct behavior of OP'd players. - - -* **Mine resets: If a mine reset takes longer than 4 minutes, then that is probably a failure and the mine reset did not complete.** Therefore, reset the mine reset mutex and try again. This allows a "crashed" mine reset to auto fix itself if it can. The 4 minute wait time is LONG, but it will prevent a normal reset from being canceled and restarted in the middle of a restart. - - -* **Performance: Changed the defaults for the mine reset settings to help improve the performance on larger servers.** -The older settings would allow other commands to backup and it would appear as if there was lag happening, TPS would rarely drop below 20. This helps to keep performance a little more responsive. -The side effect is that there will need to be more "chunks" submitted which could possibly result in longer wall-time for mine resets. - - -* **Mine resets: If a suggested block is null, then set it to air. This was causing an NPE under some conditions.** - - -* **BlockEvents: Added the ability to update block events** -instead of deleting them and re-adding them. Follow directions when using '/mines blockevent update help', or whenever a block event listing is shown in game, you can now click on the commands to auto populate the block event update command... then just edit the needed changes and submit. - - -* **Upgrade XSeries to v9.7.0 from v9.4.0.** - - -* **Bug Fix: Mine resets and block constraints.** -This fixes a few issues with block constrains using min and max, along with exclude from top and bottom too. - - -* **Bug Fix: GUI ranks, mines, and prestiges were not using the default item name correctly.** It was using the template correctly, but was not translating the use of placeholders. Only name and tag are supported. -Mines: `{mineName}` and `{mineTag}` -Ranks and prestiges: `{rankName}` and `{rankTag}` - - -* **Mines: Added support for '*all*' for mine names for the following mine commands: resetDelay, resetThreshhold, notificationPerm, and accessPermission** - - -* **Localizable: Bug fix. Blanks were being removed by the use of trim() so the spaces were being ignored.** - - -**v3.3.0-alpha.16 2023-11-18** - -* Update change logs for v3.3.0-alpha.16 - - -* **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** - - - -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) - - - ---------------------------- - - - -**3.3.0-alpha.13 2022-08-25** - -Highlights of some of the changes included in this alpha.13 release. Please see the change logs for all details. - - -* Added a new tool: `mines tp list` which will show a player all of the mines they have access to. They can also click on a listed mine to generate the TP command. This command can also be ran from the console to inspect what players have access to. -* Fixed a recently introduced bug where if the server starts up, but someone has no ranks, it was not able to properly assign them their first default rank. It was leading to circular references. -* Fixed an issue with color codes not being translated correctly with placeholderAPI. -* Prison has a rank cost multiplier where ranks on different ladders can increase, or decrease, the cost of all ranks the player buys. So when they prestige, it makes ranks A-Z cost more each time. What's new is that now you can control which ladders these rank cost multipliers are applied to, such as not on prestiges, but only on default. -* Fixed calculations of the placeholder `prison_rank__player_cost_rankname`. It was not fully working with every possible rank on every possible ladder. Now it works correctly if trying to get the player's cost for even many prestige ranks out (it includes cals for all A-Z mines at multiple passes). -* Mine bombs: Changed to only allow mine bombs to be setoff withn mines the player has access to. Fixed an issue with color codes within the mine bomb's tags. -* Fixes issues with NBT, color codes with prison broadcast commands. -* Rewrote topN for better performance: `/topn`. Older players are archived within topN and can be queried: `/topn archive`. -* Update ladder details on a few commands. -* Update XSeries from v8.8.0 to v9.0.0 so prison now supports 1.19.x blocks. -* Bug fixes with first join events. Bug fix with a few guis. -* CMI update: If CMI is detected at startup, and delayed startup is not enabled, prison will go in a simple delayed startup mode to allow CMI a chance to enable it's economy through vault. This reduces the learning curve with CMI users. -* New feature: Prison will now make an auto backup of all files in it's directory when it detects a change in version. Can manually backup too. The backup stores temp files then removes them from the server, this helps keep the server clean. -* Update bstats: Gained control of the account and started to add useful custom reports to help zero in on what we need to help support. -* More work on block converts. Will be added in the next alpha releases. -* Bug fixes: mines gui fixes for virtual mines. Sellall bug fixes. Placeholders fixes. - - - - -* **Minor addition to bstats.** - - -* **Player Mine GUI had the wrong calculation for volume which also threw off blocks remaining and percent remaining.** -The calculation for volume was using the surface area and not the total number of blocks. - - -**v3.3.0-alpha.12L 2022-08-25** - - -* **Updates to the bstats....** - - -* **New placeholders: `prison_rank__linked_mine_tag_rankname` and alias `prison_r_lmt_rankname`.** -Similar to `prison_rank__linked_mine_rankname` but uses the mine's tag instead of the mine's name. - - -* **Mine TP list: use mine tags and clickable mines to teleport to them.** - - -* **Mines TP list. Added a new options to mines tp command to list all mines that the player actually has access to.** -Not finished with it... will add clickable links to them when in game. - - -* **There was an unused updated tool in prison. It's against my policy to auto update this plugin, which would need to be consented to anyway, but I feel that admins need to be in full control of updates and know what is included in the updates. There was identified a potential exploit called zip-slip-vulnerability that could hijack a server if malicious zip is extracted. Prison never used this tool, so it's been fully disabled with no intention of reenabling. It may be deleted in the near future.** - - -* **TopN bug fix: If a player was in an archived state, they were not being moved to active when they would login.** - - -* **If the player is holding the mine bomb in their off hand, then remove the inventory from their off hand.** - - -* **v3.3.0-alpha.12k** - - -* **Fixed an issue when starting the server an no ranks exist. Also fixes an issue when starting the server an a player has no rank.** -Was using a mix of really old code, and the latest code, which caused a conflict since neither was doing what it was really supposed to. - - -* **Added the custom bstats report for Prison Vault Plugins.** -This reports all plugins that have been integrated through Vault. This report does not impact any other plugins report. This is segmented by integration type. - - -* **Fixed bug when server starts up when no player ranks exist.** -It will now bypass the player validation until ranks have been configured. - - -* **v3.3.0-alpha.12j 2022-08-21** - - -* **Update bstats to remove old custom reports that are not wanted/needed anymore.** -Added 6 new placeholder reports that classifies placeholders ini various categories related to how they are used within prison. Any placeholder that appears in these lists, will not be included in the generic 4-category placeholder lists. -Added a few more simple pie charts to cover a lot of the details on ranks, ladders, and players. Simple is better so you can just glance at all of them, without having to drill down on each one. - - -* **v3.3.0-alpha.12i 2022-09-19** - - -* **TopN players - fixed an issue where topN was being processed before the offline players were validated and fixed.** -There was an issue with processing an invalid player that did not have a default rank. - - -* **v3.3.0-alpha.12h 2022-08-19** - - -* **Rankup costs: Minor clean up of existing code. Using the calculateTargetPlayerRank function within the RankPlayer object.** - - -* **PAPI Placeholders: Force color code translations on all resulting placeholders.** -There were a few issues where placeholder color codes were not being properly translated. This was not consistent with everyone. Not sure why it was working for most. -These changes are more in line with how chat handlers and MVdW placeholders works. - - -* **Ladder: apply rank cost multiplier to a ladder or not.** -This new feature enables you to disable all rank cost multipliers for a specific ladder. Normally that rank cost multiplier applies to all ladders, but now you can suppress it. It's for the whole ladder, and not on a per rank basis. - - -* **Fixed an issue with calculating the player's rank cost when they already on the presetiges ladder and calculating the higher prestige ranks.** -Appears as if this becomes an issue when at the last rank on the default ladder. - - -* **v3.3.0-alpha12g 2022-08-14** - - -* **Fxing of the calculations of the placeholder prison_rank__player_cost_rankname and related placeholders.** -The original implementation did not take in to consideration the prestige ranks in relation to the default rank. -The improvements in this calculation now generates a list of all ranks between the current rank and the target rank. So if a few prestige ranks out from the player's current prestige rank will result in calculating every rank in between including multiple passes through all default ranks. So if there are 26 default ranks, and the player is at rank A with no prestiges, then to calculate rank P4 would include the following ranks: -b --> z + p1 + a --> z + p2 + a --> z + p3 + a --> z + p4. -This results in a total of 107 ranks that must be collected, then the player's cost for each rank will have to be calculated. Then all of these must be added together to get the player's cost on rank P4. -This calculation has to be performed for each rank in it's entirety -Warning: this calculation on high prestige ranks will be a performance issue. If this becomes a problem on any particular server, then the only recommendation that can be provided is not to use any of the prison_rank__player_cost placeholders. - - -* **TopN : a few more adjustments to fix a few issues with duplicates and also with using values from within the topN to include in the report to help minimize the need to recalculate everything especially with archived entries.** - - -* **Mine bombs: Fixed an issue with the mine bomb names not always working with color codes.** -Honestly the wrong function was being used so how it even worked I don't know. lol - - -* **New topN functionality: far better performance, with regular updates.** -TopN now is a singleton and is self contained. When the singleton is instantiated, it then loads and setup the prisonTopN.json file on the first run. 30 seconds after the initial load, it then hits all players to load their balances in an async thread. -The command /ranks topn, or just /topn has new parameter: "archived". Any player who has not been online for more than 90 days will be marked as archived. The archived option will show just the archived players. -Setup new parameters within config.yml to control the topn behavior with the async task. - - -* **v3.3.0-alpha.12f 2022-08-08 ** (forgot to commit when made this version) - - -* **Mine Bombs: Only allow bombs to be placed when within a mine that the player has access to.** -This will help prevent wasted bombs. - - -* **Fixed an issue with nbt items not having a value for toString().** - - -* **Encode color codes for the prison utils broadcast command.** - - -* **Added an "invalid player name" message to the rankup commands.** -Also added missing messages to the zh_TW.properties file. - - -* **BlockEvents were changed to auto display the existing rows so it's easier for the end user to know which row to select.** -All they need to do is to enter the mine's name, then press enter to submit the command, and then the existing rows details will be shown. Then the user can select the row and complete the command. -Updated docs on block events. - - -* **BlockEvents were changed to auto display the existing rows so it's easier for the end user to know which row to select.** -All they need to do is to enter the mine's name, then press enter to submit the command, and then the existing rows details will be shown. Then the user can select the row and complete the command. - - -* **minor updates for disabled mine reset times. No functional changes were made.** - - -* **Fixed a potential NPE with giving the players overflow blocks, but not sure what the exact cause was, but looked like there was an issue with mapping to a spigot item stack.** - - - **CMI delayed startup: Added new feature to try to auto enable Prison's delayed startup if CMI is detected as an active plugin, and if the delayed startup is disabled within the config.yml.** -This is to help get more CMI users up and running without more effort, but yet still provide the ability to customize how it is triggered. -If CMI is active, there is NO WAY to disable a delayed startup check.* - -* **Added the the option for playerName to the `/rankup` command so the command can be scripted and ran from the console.** - - -* **There was another issue with using `/gui` related to no ladders being loaded.** -This fixes that problem, and it appears like the issue was caused by plugman messing things up. This does not "solve" the problem with ladders not being loaded, but prevents the NPE from happening. - - -* **There was an issue with `/prison reload gui` causing a NPE.** - - -* **Fixed the `/ranks topn` command (`/topn`) to sort the list of players before printing the list.** -The list was being set a server startup time, and if someone would rankup or prestige, it was not reflecting their new position. The list is also now sorted after each rankup. Sorting should be a low cost operation since the list used never is regenerated so the changes made during sorting is minimal at best. - - -* **Added the ability to control the prefix spaces on the unit names.** -NOTE: may need to enable the use of the `core_text__time_units_short` since the long units are not being used. May need to create another placeholder for short/long. It used to be short, so may need to use long with the new placeholder and convert the calcs to the short as the default. -This was requested by PassBL. - - -* **v3.3.0-alpha.12e** - - -* **Fixed issue rank null issues when showing ladder details.** - - -* **Prison backups: Fixed an issue with folders not existing when running the backups the first time.** - - -* **v3.3.0-alpha.12d 2022-07-25** - - -* **Added more information on ladder listing to show name, number of ranks, and rank cost multiplier.** - - -* **bStats update: Added a new bstats custom chart for auto features.** - - -* **Update some docs. Added docs for Prison Backups** -[Prison Backup Document](prison_docs_050_Prison_backups.md) - - -* **Upgrade XSeries from v8.8.0 to v9.0.0** - - -* **Fixed issue with prison version check triggering a backup upon startup.** -It was always bypassing the previous version check, so it was always creating another backup. - - -* **Update bstats by moving to its own class in its own package.** -Added 4 new custom charts to split the plugins in to 4 parts. - - -* **Fixed a few issues with the ranks gui where they were using the wrong message key (placeholder).** - - -* **Prison v3.3.0-alpha.12c** - - - -* **Prison bstats: setup 4 new bstats charts for prison. May change a few charts or add new ones in the near future.** -Got control over the prison bstats so can now add custom stats. - - -* **Prison backups: Created a Prison/backups/versions.log file which gets logs when a new prison version is detected on startup, which also performs a backup.** -All backups are also logged in the versions.log file too. - - -* **v3.3.0-alpha.12b** -- Added the fix for the placeholders. See next note. - - -* **Fixed an issue with placeholders not be properly evaluated; there were 3 sections and they were combined in to one so it would not bypass any.** - - -* **Possible bug fix with first join: it appears like it was inconsistant with running the rank commands. Fixed by rewriting how the first join event is handled.** - - - -* **Prison backups: Added new features where it is generating a stats file in the root of the zip file which contains all of the "prison support submit" items.** -This is just about ready, but lacking support for auto backups when prison versions change, or job submission to run auto backups at regular intervals. - - -* **Setup a prison backup command that will backup all files within the prison plugin folder.** -When finished, it will delete all temp files since they have been included in the backup. -The new command is `/prison support backup help`. - - -* **v3.3.0-alpha.12a** - - -* **Added a new set of intelligent placeholders: these show the tags for the default ladder and prestige ladder, for the "next" rank but are linked together.** -They only apply to the default ladder and the prestige ladders. The tags are only shown if the player has that rank, or if that will become their next rank. -These ONLY show the tags that will be appropriate when the next rank up. So if the can still rankup on the default ladder, then only the default rank shows the next ranks tag. If they are at the end of the default rank, then it will show the next rank on the prestiges ladder; if they do not have a rank there currently, then it will show the next prestige rank with the default rank showing the first rank on that ladder. - - -* **When the command handler starts up, it now logs the pluigin's root command and the command prefix which is used if there are duplicate commands found during bukkit command registration.** - - -* **Bug fix: Placeholders search was missing the assignment of the placeholderKey, which is what would like the search results on the raw placeholders, with the actual data that is tied back to the player.** -In otherwords, without the PlaceholderKey it was not possible to extract the player's data to be displayed within the command: /prison placeholders search. - - -* **Added constants for the default and prestiges ladder name so it does not have to be duplicated all over the place, which can lead to bugs with typos.** - - -* **Sellall bug fix: There wasn't a common point of refernce to check if sellall is enabled. Many locations were directly checking config.yml, but the new setting has been moved to the modules.yml file. ** -If config.yml has sellall enabled in there, it will be used as a secondary setting if the sellall setting in modules.yml is not defined or set to false. Eventually the config.yml setting will be removed. - - -* **Found that bStats was erroring out with the servers hitting the rate limit so this makes a few adjustments to try to get prison to work with bstats.** -Basically plugins that load last will be unable to report their stats since every single plugin that is using bstats submits on it's own, and therefore it quickly reaches the limits. - - -* **BlockConverters: More changes to block converters.** -Added defaults for auto blocking, and for auto features with support for *all* blocks. - - -* **Bug fix: mines gui was not able to handle virtual mines with the internal placeholders. -This bug fix was included with the deployment of alpha.12 to spigotmc.org. - - - -* **Pull Request from release.branch.v3.3.0-alpha.12 to Master - 2022-06-25** - - -This represents about six months of a lot of work with many bug fixes, performance improvements, and new features that have been introduced. The last two alphas were not pulled back to main, but they were released, This PR will preserve the released alpha as it has been published. - -Also, this helps to ensure that this work will not be lost in the event the bleeding branch is lost/removed. Hopefully it won't be, but a lot of work has gone in to it and it will be impossible to recreate the current state of the alpha release. - -This version, v3.3.0-alpha.12, has 300 commits and 323 changed files. The list of actual changes since v3.2.11 is substantial and the change log should be referenced. - -Highlights of some of the changes include (a sparse list): - -* new block model - full support for CustomItems custom blocks - updated XSeries which mean prison supports Spigot 1.19. -* major improvements to auto features - streamlined and new code - higher performance - many bugs eliminated - now supports drop canceling to make prison more compatible with other plugins -* better multi-language support - supports UTF-8 -* Improved rankup - rankup commands are now ran in batch and will not lag the server if players spam it -* rewrite of the async mine resets - next to impossible for mine resets to cause lag - Uses a new intelligence design that will throttle placing blocks as the server load increases, which makes it next to impossible for it to cause lag. -* Enhanced debugging tools - if a server owner is having issues, prison has more useful tools and logging to better identify where the issues are - new areas are not able to log details when in debug mode - debug mode now has a "count down timer" where if debug mode is 8enabled like /prison debug 10 then it will only allow 10 debug messages to print, then it will turn off debug mode automatically. This is very useful on very heavy servers when a lot of players are active... it prevents massive flooding of the console. -* Major rewrite of the placeholder code that identifies which placeholder raw text is tied to, so it can then retrieve and process the data. - Pre-cache that provides mapping to raw text, so once it is mapped, it can prevent the expensive costs of finding the correct placeholder - Added the beginning of tracking stats (through the pre-cache0 and will be adding an actual placeholder cache in the near future. -* Mine Bombs - fixes and enhancements -* Starting to create a new sellall module that will support multiple shops and custom blocks (not just XMaterial names) -* Block Converters - Will allow full customization on all block specific things within auto features - will eliminate all hard coded block -* Started to add NBT support. - Used in mine bombs - Starting to use in GUI's to simplify the complexity of hooking actions up with the menu items. -* Added rank scores and top-n players - Rank score is a fair way to score players within a rank. It's currently the percentage of money they have to rank up (0 to 100 percent), but once they cross the 100% threshold, then 10% of the excess subtracts from their rank score. This prevents camping at levels. -* There is more stuff, some major, a bunch of minor, and many bug fixes along the way. - - - - - -* **v3.3.0-alpha.12 2022-06-25** - - - -* **v3.3.0-alpha.11k 2022-06-20** -Plus luckperms doc update. - - -* **Mine resets: Fixed an issue when dealing with zero-block resets on a very small mine, such as a one block mine in that the 5 second delay was preventing from rapid resets.** -Bypass both 5 second cooldown on resets and blockmatching when 25 blocks or less for the mine size. -With running resets in async mode, with rapid resets for a one-block mine, the handling of the block breaks can occur out of order, which will trigger the block mismatch. - - -* **Fix issue: On the creation of a new mine, it would reset the mine a number of times. This fixes the problem by only allowing one reset every 5 seconds at the soonest.** - - - -* **Placeholder fix: The PAPI placeholder integrations should not be prefixing raw text with "prison_"; that is the task for PlaceholderIdentifier.** - - -* **minor items changed with the GUIs... no functional changes.** - - -* **Update a number of docs...** - - -* **Fixed an issue where if you try to use a % on a number it's causing String format errors.** -This now strips off % and $ if they are used. - - -* **Update Docs: LuckPerms groups and tracks... added images and fixes a few minor things too.** - - -* **Update some of the docs on setting up luckperms and tracks.** - - -* **v3.3.0-alpha.11j** - - -* **Since the chat event is handled within the spigot module, and since ranks and mines would just duplicate the processing since they both will hit the SpigotPlaceholder class, it made sense to handle the chat event directly within the spigot module.** - - -* **Updates to the prison placeholder handler. This fixes a bug with chat messages return a null value.** -These changes also allows the pre-cache to track invalid placeholders now, so it can fast-fail them so it does not have to waste CPU time trying to look up which placeholder key they are tied to. - - -* **v3.3.0-alpha.11i** -Getting ready to release alpha.12. - - -* **Placeholder stats: A new feature that is tracking usage counts with placeholders.** -This is not a placeholder cache that caches the results, but it caches the placeholder that is associated with text placeholder. The stats currently only tracks the total number of hits, and the average run time to calculate the placeholder. -The pre-cache will reduce some overhead costs. This also provides the framework to hooking up a formal placeholder cache. - - -* **Placeholders: changed the two top_player line placeholders that are the headings** - since they originally had _nnn_ pattern that is getting messed up in some settings. So removal of the nnn helped to getting it working. - - -* **GUI MInes: Update support for custom lore support within the gui configs.** - - -* **Update XSeries from v8.7.1 to v8.8.0 to better support the newest blocks.** - - -* **Updated item-nbt-api-plugin from v2.9.2 to v2.10.0.** - - -* **v3.3.0-alpha.11h 2022-06-14** - - -* **Prison Placeholders: General clean up of obsolete code.** -Since the new placeholder system is working well with the new class PlaceholderIdentifier, obsolete code that was commented out has been removed. -The obsolete class that used to be the key component to identifying placeholders was PlaceholderResults and is no longer used anywhere. It's core components were moved to PlaceholderIdentifier and therefore all references to this obsolete class has been eliminated. -At this time, PlaceholderResults has not been deleted, but will be at some future time. - - -* **Prison Placeholders: Major rewrite the handling of placeholders.** -Prison's placeholder handling was completely rewritten to better handle the matching of a placeholder text with the actual placeholder objects. Over the last few years, many new features were added to prison's placeholders, but the way they were implemented were through patching existing code. This rewrite starts from scratch on how placeholder are decoded. Placeholders are now only decoded once instead of being decoded when attempting to match each internal placeholder. The results are significant performance improvements and eliminates a lot of redundant code. Some new features were add, such as supporting more than one placeholder attribute at a time. Also it streamlines how parameters and data is passed from the outer most layers of prison to where the placeholders are calculated. - -Another major benefit of this rewrite, beside reduction of code complexity and performance improvements, is that it opens the door to being able to implement an internal placeholder cache. Some plugins request placeholder data once per tick, or 20 times per second. Multiply that by 50 online players, and you got prison performing the same calculation 1000 times per second. Caching could help reduce that to only one calculation per second (assuming a cache time to live value of 1 second. Caching will not always be so simple, or possible, or every placeholder. Player-based placeholders can't be cached like static mine placeholders (mine names and mine tags as an example). - - -* **Add support for Portuguese.** - - -* **BlockConverters: fix issue when block converters are not active.** - - -**v3.3.0-alpha.11g - 2022-06-11** - - -* **Disable the gui for autofeatures configs. They are so out of date, they were causing problems.** -Autofeatures should be manually edited. - - -* **Fix a problem when BlockConverters are disabled, and doing a reload on auto features, it's not able to find that config file so its throwing an exception.** - - -* **The build was failing intermittently on the continual integration (CI)** -pertaining to the item-nbt-api-plugin, so an entry to added to "lock it in" to the correct path within the mavenrepository.com repo. -This should prevent the resource from being paired with the wrong repo. - - -* **There is a situation when checking for new updates to the language files, that it needs to write the new file, but the old one has not been archived.** -This now checks to make sure the old one has been renamed, and if it hasn't, then it will rename it. - - -* **Added an entry for the sellall module in the modules.yml file.** -Code has been setup to check, with a default fall-back on to the sellall settings within config.yml file. The entry in config.yml has been commented out. -Either will work, but the setting within modules.yml will take priority. - - -* **Update XSeries to v8.7.1 from v8.6.2.** -Note that this does not add any of the newer 1.19 blocks or items. - - -* **GUI: Fixed some issues with the gui and admin perms. Added some admin perms to a few gui commands to lock them down.** -Found a serious issue with non-admins being able to edit rank costs and sellall item costs. The GUIs were not locked down and if the players knew the commands, they could edit the costs. - - -* **v3.3.0-alpha.11f 2022-06-06** - - -* **BlockConverters: minor changes.** - - -* **Bug fix: Backpacks were not working properly with just ".save()" but had to add ".setChanged()" too, otherwise minepacks will not actually save the status of the backpacks.** - - -* **BlockConverters: rename targets to outputs.** - - -* **BlockConversions: hooked up the code to not only filter and return the blockConversions for the player and the block, but to also return the item stacks from the results.** -This is just about ready to be used in the code. - - -* **Romanian Locale language files were placed in the wrong location.** -Oreoezi provide two new language files for the Romanian Locale, but they were placed in the wrong location. -They were added to "prison-core/out/production/resources/lang/core/" and ".../mines/". For them to actually -work correctly, without being deleted, need to be placed within the following path: -"prison-core/src/main/resources/lang/core/" and "prison-core/src/main/resources/lang/mines". -These should now be usable. Also the LocaleManager now has alternatives setup to default to en_US; future -alternative languages can be added in the future. - - -* **BlockConverters: add some validators to the BlockConverters.** -Reports various issues, fixes non-lowercase source block names, and also disables invalid settings. - - -* **BlockConverters: Adjusting around how they are setup, and how they are generated.** -BlockConverters are now in their own config file: blockConvertersConfig.json. -They are no longer being stacked/placed in the autoFeaturesConfig.yml file, so all the conversion code is no longer required. With it being json, it now can reflect the java classes without any special considerations on the conversion process. - - -* **BlockConverters: More work on these settings.** -Setting up to work with AutoFeaturesConfig.yml, but having second thoughts about adding these configs to that file since it will complicate the config details. - - -* **Fixed a bug on the smelting of coal_ore which was yielding 10 times too much, but this was never seen since a silk touch pickaxe would have to been used.** - - -* **Placeholder fix for `prison_mines_blocks_mined_minename` since it was not being incremented after the fixing of the autopickup=false and handle normal drops = true.** -Also found that the calculated field for the mine's total blocks mined was not being recalculated after load the mines from their save files. This now is working properly. - - -* **Major exploit fix: sellall was not indicating that the inventory was changed within the Minepacks backpacks,** -and therefore players were able to sellall of their inventory, logoff, and then when they log back on, it will be restored. -Now, all inventory changes are forcing a save for the backpacks. - - -* **Fixed an incorrect mapping to a message: auto features tool is worn out.** - - -* **v3.3.0-alpha.11e 2022-05-23** - - -* **Bug fix: Fixed an issue with sellall when the module sellall is not defined but sellall is enabled in the config.yml file.** - - -* **Bug fix: Minepacks has a new function in their API to force backpack changes to be saved.** -Before it could only be marked as changed, which was not enough to get it to save in all situations. Prison is now calling "save()" to ensure its behaving better now. -NOTE: releasing this fix with alpha.11d even though it has been added after being set to 11d. - - -* **Prison v3.3.0-alpha.11d 2022-05-22** - - -* **GUI messages: a few more updates and corrections** - - -* **GUI: More fixes to the gui messages... including moving all of the new gui specific messages out of prison-sellall module to the prison-core module so they will still be accessible if the prison-sellall module is disabled.** - - -* **GUI cleaned up by eliminating so many excessive uses of translating amp color codes to the native color codes.** -Found some locations where there were at least 7 layers of function calls, with each layer trying to translate the color codes, which of course was excessive. - - -* **Change the name of the SpigotSellallUtilMessages class to SpigotVariousGuiMessages due to the fact these messages are used in more than just sellall.** -It should be noted that eventually the non-sellall messages may have to be removed from the sellall module. - - -* **Spigot GUI Messages: Hook up more messages to prison's messaging system.** - - -* **Sellall messages: Start to setup the correct usage of the multi-language message handling through the new prison-sellall module.** -This fixes the messaging within the SellAllUtil class. - - -* **Move auto feature messages to the spigot message file so they can be customized.** -Removed the inventory full messages from the AutoFeaturesConifg.yml file. - - -* **The normalDrops processing was not hooked up to the newest way auto pickup is disabled, which was skipping normalDrops if auto pickup was disabled.** -The number of blocks in the normalDrops is now being passed back through the code so it can identify that it was successful and finalize the processing. - - -* **3.3.0-alpha.11c 2022-05-14** - - -* **GUI Menus enable NBT support.** -This is a major change. The details for the menus options and commands are now stored in NBT data so they do not have to rely on the item name, lore, or other tricks. -This is a first phase, and more work needs to be done to remove hooks with the item names for other menu options. Main set of changes has been done to the menu tools. - - -* **Changed placeholder attributes to print the raw value and placeholder.** -Changes to the logging to allow & to be encoded to the unicode string of -`U+0026` so it can bypass the color code conversions, then it is converted back -to an & before sending to bukkit. This works far better than trying to -use Java regEx quotes. - - -* **Fixed signs for sellall to enable them to work with any wood variant.** - - -* **3.3.0-alpha.11b 2022-05-02** - - -* **Placeholder fix for formatted time segments to use the values setup in the language files within core.** -This allows the placeholders to use the proper notations for singular and plural units of times as configured for each language. - - -* **Placeholder fix for rankup_cost and rankup_cost_remaining on both the formating of the percents and the bar.** -The percents were being displayed as an integer, so with rounding, they were very misleading since they would show 100% when they were really hitting 99.5% and higher. Also the bar is not working better, and if the percentage is less than 100%, then it will always show a RED segment at the end of the bar; it will ONLY show GREEN when it's 100% or higher. - - -* **Mine Bombs fix to allow color codes within the bomb's name.** -The color codes are removed for the sake of matching and selecting when giving to players so you don't have to use them in the commands. - - -* **Placeholder issues when not prefixed with "prison_" is being addressed by prefixing the identifier with "prison_" right away.** -This "is" addressed, but it's deep in the code and for some reason certain parts of the code is not making the connection to the correct placeholder without that prefix. So this really is not the desired way to address this, but it eliminates the problem. The reason why it's not the desired way, is because it's exposing buisness rules of how to handle the placeholders, outside of the placeholder core code. - - -* **Bug fix... with placeholder prison_rank__player_cost_remaining_rankname, and its variants,** - eliminate the calculation of including the current rank since that has already been paid for. Prior to this fix, it was only excluding prior ranks. - - -* **3.3.0-alpha.11a 2022-04-25** - - -* **Mine Bombs and NBT settings: this fixes mine bombs to work with NBT tags, which are being used to identify which items are actually mine bombs.** - - -* **Fixes the mine bomb usage of lore where the lore that is defined in the settings is no longer altered so it's now used verbatim.** -Also the check for mine bomb is removed from using the name, or first line of lore, and now tries to use NBT data. -But note, that the NBT data is not working correctly yet. - - -* **Fixed the usage of setting up the NBT library within the gradle config file.** -Fixed issue with unknown, or incompatible items were unable to be parsed by XMaterial which was resulting in failures. This fixes the problem by preventing the use of a partial created SpigotItemStack. - - -* **Hook up the NBT library to the SpigotItemStack class.** -This has not been tested yet to see how it works, especially between server resets. - - -* **Added NBT support to prison. This loads a NBT library to be used only with the spigot sub-project.** -This has not been hooked up to anything yet. - - -* **Placeholder fix: Problem with the placeholder getting a prestige rank that was one too high.** -The following placeholders were fixed: prison_rrt, prison_rankup_rank_tag, prison_rrt_laddername, prison_rankup_rank_tag_laddername - - -* **Hooked up the BlockConvertersNode to the yaml file IO code so it will save and load changes to the auto features configs for anything with the BlockConverters data type.** -Removed unused functions. - - -* **Mine reset potential bug fix: Some rare conditions was causing problems, so using another collection to pass the blocks, and getting the size prior to calling the function to prevent the problems from happening.** -This appeared to be happening when a mine was being reset multiple times, at the same time. The mine should never be resetting multiple times, at the same time. May need to add more controls to prevent it from happening. - - -* **Bug Fix: The IGNORE block type was not marked as a block, therefore could not be used within a mine.** - - -* **New feature: Block Converters. Setup the initial core settings for block converters within the auto features.** -The core internal structure is in place and so is the ability to write the data to the file system. -This has not been hooked up to anything yet. - - -* **Setup placeholder formatted time values to use the language config file.** -This set of values will "NOT" reload when the command `/prison reload locales` is ran. The server must be restarted to reload these values. - - -* **CustomItems getDrops() debug mode will list the results of the get drops.** -This will help track what's going on with the getDrops function since it's a complicated process. - - -* **Placeholders: prison_rankup_rank_tag (and the ladder variants) now shows the prestiges next rank when at the top rank in the default ladder.** -This only applies to the default ladder and only if the prestiges ladder is activated. - - -* **Pull out the setBlock and blockAt functions from the SpigotWorld class so that way it would properly track within Timings.** - - - -** v3.3.0-alpha.10 2022-04-02** - -** Release notes for the v3.3.0-alpha.10 release as posted to spigotmc.org and polymart.org: - -v3.3.0-alpha.10 - -This alpha.10 release includes many significant performance improvements and bug fixes. Although this is an alpha release, it is proving to be stable enough to use on a production server. Please make backups and test prior to using. This v3.3.0-alpha.10 release is "still" backwards compatible with v3.2.11 so you should be able to down-grade back to v3.2.11 without major issues. The breaking changes that will be in the final v3.3.0 release have not been applied yet to these alpha releases. - -Please see our discord server for the full listing of all bug fixes and improvements, there have been more than 70 updates since the alpha.9 release. The following is just a simple short list. - -- Many bug fixes. Some that even predates the v3.2.11 release. - -- Performance improvements: startup validations moved to an async thread. Slight delay between mine validations to allow other tasks to run (needed for less powerful servers). Improvements with sellall performance. - -- Added more support for Custom Items (custom blocks) - -- Added support for top-n players and added over 30 new placeholders. Top-n support for blocks mined and tokens earned will be added shortly too. - -- Upgraded internal libraries: bstats, XSeries, gradle, custom items, and a couple others. - -- Many fixes: Mine bombs, sellall, autosell, auto features, block even listening and handling. - - -* **Ran in to an issue with spigot versions < 1.13 where a data value outside of the normal range prevents XMaterial from mapping to a bukkit block.** -This change provides a better fallback which ignores the data value, which is the varient. The drawback of ignoring the varient type, which is outside the valid ranges anyway, is that it may not accurately reflect the intended block types. But at least this will prevent errors and being unable to map to any blocks. - - -* **Change to prison startup details reporting to elminate duplication.** -Near the end of the prison startup process, prison would run the `/prison version` command to provide additional information in the logs. This was duplicating some of the information that was already printed during the actual startup process. -Changes were made to only add the information that was missing so the whole command does not need to re reran. Overall this is a small impact, but a useful one. It does shift where these functions live and ran from. - - -* **ChatDisplay: An internal change that controls if a chat display object (multi-lined content, such as command output) displays the title.** -This will be useful when integrating in to other commands and workflows, such as redesigning how the startup reporting is handled. - - -* **v3.3.0-alpha.9g 2022-03-29** - - -* **auto features: Enable player toggle on sellall for auto feature's autosell.** - - -* **sellall reload - fixed issue where the reload was not chaning any online valus or settings.** - - -* **Mine bombs cooldown - ran in to a null value in the cooldown timers. Handles this situation now. ** - - -* **Sellall - added debug logging on the calculation of sell prices.** - - -* **Sellall bug fix on calculation boolean config values; it was not returning the correct value.** -This was found by a report that `/sellall hand` was not working. - - -* **Auto features bug fix: was paying the player, instead of just reporting the value when in debug mode.** - - -* **Update debug info in auto features to properly show it's within the BLOCKEVENTS priority processing.** - - -* **Topn calculations: handle a null being returned for the prestige ladder.** - - -* **Enabled a sellall feature to enable the old functionality where sellall ignores the Display Name or is not a valid prison block type.** - - -* **Fixed an NPE issue with checking to see if a block exists within a mine.** -This issue was impacting spigot versions less than 1.13. The problem is with data values being abnormal and out of the standard range. - - -* **Fixed a NPE on the topn calculations.** - - -* **auto features autosell when inventory is full when using the priority BLOCKEVENTS.** - - -* **topn fix: If next rank is null, then try to use the next prestige rank for the cost.** - - -* **v3.3.0-alpha.9f 2022-03-25** - - -* **Placeholders top player: added new placeholders based upon the _nnn_ pattern to identify the player.** - - -* **Top-n players listing: added an alternative line.** - - -* **Placeholder Bar Attributes: Now supports a non-positional keyword "reverse" which will take any bar graph and reverse it.** - - -* **AutoFeatures debugging: Some color change in the logging details for failures so they are easier to see.** - - -* **Prepare for the handling of STATSPLAYERS placeholders, which will be the ones that provides the placeholders for the top-n players.** -This handles the workflow on handling the placeholders. - - -* **Slight update on how the top-n players are printed... simplifies and also cleans it up the formatting.** - - -* **Updated the rankup accuracy to be greater than or equal to 1.0.** -And conditionally only report the accuracy_out_of_range if >= 1.0. - - -* **When validating the success of a rankup transaction's abiliity for the rankup cost to be applied, the validation is now checking to see if it's within a plus/minus of 1.0 from the target final balance of the player.** -This covers the inability of floats and doubles not being able to accurately repesent base 10 numbers all of the time, which the accuracy may be off by a small value such as 0.000001, but that will prevent an equality check from passing. -By checking that it's within a range of plus/minus one will help prevent false failures. - - -* **Fixed issue where ranking does not which rank is associated with each rank.** -Now the ranks will properly track the players at their ranks. - - -* **3.3.0-alpha.9e 2022-03-14** - - -* **Top-n: More work to enable. Now supports /ranks topn, with alias /topn.** -The rank-score and penalty is not yet enabled. Placeholders will be enabled after the command is fully functional. - - -* **Prison startup performance fix: On large servers with many players, the process of getting the player's balance from the economy plugin can cause significant delays if that plugin is not able to handle the load...** -so the validation of the players and the sorting of the top-n list is now ran in an async thread so it will not cause lag or delays on startup. - - -* **Prison version: including more information on ranks and add the ladder rank listing to the prison version command.** - - -* **Removed some old code from block event processing...** - - -* **Mine bombs getting a replacement blocks from the player's location.** - - -* **CustomItems drops: If custom items do not produce a drop, then default to dropping the block itself.** - - -* **Sellall: prevent selling with custom name items.** - - -* **PlayerCache earningsPerMinute: Sychronize to prevent an issue with concurrent mods.** - - -* **Mine bombs: Fix an issue with the generated mine bomb tool not being enchanted with the specified fortune, which also was effecting the durability and dig_speed too.** - - -* **Reworked how some of the registered event listeners are setup, which is needed for expanding to supporting other plugin's enchanments.** - - -* **Update the bstats configs for v3.0.0.** -Although it compiled without the bstats-base, it failed to run. I suspect my local cache for gradle was incorrectly providing objects when it shouldn't have. - - -* **Upgrade bstats to v3.0.0, was at v2.2.1.** -Hoping this will better report the proper usage. -Added more custom details on the graphs: player count, defaultRankCount, prestigesRankCount, otherRankCounts. -Set api version to v3.3. - - -* **BugFix: Prevent a possible NPE when blocks are null when calculating gravity effected blocks, and ensuring there is a location when trying to place blocks.** -Both of these should never be an issue, but based upon different conditions, they can become an issue. - - -* **Added an autoFeatures to enable/disable the use of CustomItems' getDrops().** - - -* **CustomItems integration: Adding support for getDrops() from CUI.** -This integrates custom blocks in to getting the SpigotBlock (an internal prison block). -It's not yet functional due to issues within CUI, but this is the initial setup. - - -* **Report that bedrock users are not getting their tokens.** -When in debug mode, if their balance is not correctly updated it will report it in the console. - - -* **v3.3.0-alpha.9d 2022-03-10** - - -* **Within the SpigotBlock, now has hooks to load CustomItems blocks when trying to convert an org.bukkit.Block to a SpigotBlock.** - - -* **For unbreakable blocks, reinforce that the location, which is the key, will not be null.** -The block sometimes can be null, so by having the seperate location will not cause a failure if the block is null. - - -* **Fixed an issue when checking if a block is unbreakable... it should not have been null, so this is a temp fix to prevent an error.** - - -* **CustomItems custom blocks: Hook up the new drops for CustomItems plugin.** - - -* **Update some of the gradle settings and fix the new custom items api.** - - -* **Upgrade XSeries from v8.5.0.1 to v8.6.2.** - - -* **Update CustomItems API from v4.1.3 to v4.1.15.** -This update adds support for prison to get the drops from the CustomItem blocks. - - -* **Changed the development environment and updated the java 1.8 to the latest release.** - - -* **v3.3.0-alpha.9c 2022-03-06** - - -* **Enable the ability to split messages in to multiple lines by using the placeholder `{br}`.** - - -* **Small adjustments to the MineReset handing of the targetBlock collections.** -Prevent their instantiation in the constructor since they are being lazy loaded. Also synchronizing on the adding of target block, since there was one report on an issue with that not being synchronized. - - -* **Added more validation checks and reporting on rankups and demotes.** -So if something goes wrong, it can hopefully identified and tracked. -If rank change failed, or if a refund failed, it will now better report these conditions. - - -* **Setup a return of success, or failure, on custom currency functions.** -GemsEconomy does not indicate if it was successful, but added code to check to see if it was successfully manually/indirectly. - - -* **Sync set blocks fixes. Isolate the targetBlocks and add a null check to ensure thre are no problems.** - - -* **RankLadder: removed obsolete code that was never used.** - - -* **Some initial setup for a rankScore.** -This is not hooked up yet, but the the core basics are there and should work soon. - - -* **Bug fix: Fixed an issue were a block would be added, or changed, and it would change all similar blocks in all mines to have the same percentage.** -This issue was intermittent and was caused by directly getting the block from the master list, without cloning it. The correction to this issue was to use a search function that would clone the block, but it also would compensate for custom blocks if the block's namespace was not initially provided. - - -* **Bug fix: Risk of a null on the blockHit, so add checks to ensure it's not before trying to process.** - - -* **Bug fix: The clickable delete code is that is generated is off by 1 on the inserted row.** -The row number needed to be reduced by one since the row number was incremented right before this final injection. - - -* **v3.3.0-alpha.9b 2022-02-28** - - -* **Fixed the command '/ranks ladder command remove' when specifying a row value that was too large.** -The message was only providing one value when it should have had two, and the first parameter was '%d' instead of '%1'. - - -* **PlayerCache: Unloading Players... when a player is being unloaded, and they are not in the cache, the unloading process is now able to indicate that the player should not be loaded.** -Also when trying to load a player, it will not attempt the load if the file does not exist. - - -* **Sellall bug fix... was using the wrapper to map it to an XMaterial which was causing NPEs.** -Using the prison's compatibility functions to perform the mapping, which will now provide a safer mapping that will not cause NPEs. - - -* **Module prison-sellall cleaned up gradle config to remove a few configs that are not needed.** - - -* **Fixed a bug with the blockEvent block filter for adding blocks, it was using the blockEvents collection instead of the prison blocks collection.** - - -* **Fix placeholder for prison_player_tool_lore to provide the actual tool's lore.** -The placeholder was not hooked up. - - -* **Mine manager when enabling mines after the delayed loading from multiverse-core delayed loading...** -put a slight delay on each submission of the startup air counts for each mine... spacing them out by one tick so they are not all trying to run at the same time. - - -* **v3.3.0-alpha.9 2022-02-27** - - -* **Bug fix: Sellall error: Resolve an issue with the off-hand not being removed when selling.** -Turned out that you can read all inventory slots, which includes the off-and slot, but when removing ItemStacks, the remove(ItemStack) function then ignores the off-hand slot. Has to directly remove from the off-hand slot. - - -* **Mine bombs: fixed issue with lore not being added.** -Was adding the wrong source; was adding the destination to the destination. - - -* **Mine Bombs: Add some basic validations when loading the mine bombs from the config files** - - -* **Mine Bombs: add a reload function for mine bombs.** -/prison reload bombs or /prison utils bomb reload - - -* **Removed warnings from the Vault economy wrapper since NPCs can actually initiate commands and NPC will always return nulls for OfflinePlayers....** therefore just return a value of zero. - - -* **New command added to '/prison support runCmd' to allow an OP process, such as a NPC in Citizens, to run a command as a player.** -For example this is handy for having an NPC open the player's GUIs such as mines or ranks. - - -* **v3.3.0-alpha.8h 2022-02-26** - - -* **Bug fix: Synchronized some of the collections that are needing it within the PlayerCache.** - - -* **Bug fix: Fixed an inventory glitch that was preventing items from being added to the inventory.** -Basically the inventory had items, but it was not updating the contents of the inventory on the client side. This was fixed by updating inventory when finished processing the adds. -If autosell on full inventory is enabled, and there are extra drops, then sell them all before they make it to the inventory. This works most of the time, but sometimes the inventory still fills up. This is now more of a characteristic than a bug. - - -* **3.3.0-alpha.8g 2022-02-25** - - -* **More adjustments to the block events so the config setting can be shown in the header of the /prison support listeners blockevent command.** - - -* **Setting up support for the BLOCKEVENTS on all block break event listeners.** -Changed around how the listeners are created to simplify and be more accurate in the event states. - - -* **Extracted the BlockBreakPriority enum to be an object on its own.** -Added BLOCKEVENT and added information on what the various priorities should do. This is in preparation to refactoring how events are processed. - - -* **Prison tokens: externalize the messages related to the admin tokens commands.** - - -* **For the admin commands for tokens, added an option to be able to suppress the messages.** - - -* **v3.3.0-alpha.8f 2022-02-23** - - -* **The creation of a new sellall module which will eventually contain the code to manage multiple shops that will be based upon ranks.** - - -* **Adjustments to the configuration of the mutex to better ensure that only one job is submitted for the reset, and to ensure other tasks are not locked up, or locked out.** -There was a report that the prior way was causing the mines to lockup. - - -* **v3.3.0-alpha.8e 2022-02-20** - - -* **Mine reset mutex is conditionally enabled to ensure the locks remain balanced.** -To ensure the mutex is enabled ASAP, its engaged outside of the normal location... it may only be a few nano-seconds savings, but with OP pickaxes mining with many players within one mine, the mutex must be enabled rapidly. - - -* **Bug Fix: Mine reset changes: Eliminate paged resets, some code that is not being use anymore, disabled the RESET_ASYNC type to be similar to RESET_SYNC since they are now the same, locked out checkZeroBlockResets so mines cannot reset multiple times at the same time using the MineStateMutex.** -The major issue here was that mines were being reset in the middle of a reset action. Used a preexisting MineStateMutex to secure the checkZeroBlockResets() function to prevent it from kicking off many resets. These multiple resets were happening because many players were triggering the resets... as a side effect, there were many situations of collections failing due to concurrent modification exceptions. - - -* **Getting the collection size was an issue by the time it was done processing the blocks, so getting them first may help prevent errors.** - - -* **Made many changes to the default configurations of the autoFeatures.** -This is to try to make it easier to use prison by using more of the settings that are most useful. -Added more comments to make it easier to understand these settings too.f - - -* **Release v3.3.0-alpha.8d 2022-02-20** - - -- **Fixed issues with vault economy and withdrawing from a player's balance.** -It now also reports any errors that may be returned. - - -* **To prevent NPEs, isBlockAMatch has been changed to use the MineTargetPrisonBlock as a parameter and then internally, checking for nulls, it will extract the status data block.** -This was causing errors when processes were trying to access target blocks before they had a chance to initialize. - - -* **Address a rare condition where the mineTargetPrisonBlocks is being "accessed" before the system is done initializing the mine.** -This creates an empty collection, but it will prevent errors in the long run. - - -* **Add equals and hashCode to the MineTargetBlockKey so it can be better used in structures like HashMaps.** - - -* **Mine bombs: Added a {countdown} placeholder for use with the MineBomb's tagName field.** -A few other adjustments such as adding more "color" to the default bomb tagNames. - - -* **Added validation check to make sure the player's balance was decreased, or increased, successfully before actually applying the rank change.** -If the balance does not reflect the change, then the rank change will be prevented. - - -* **Slight adjustment to addBalance so as to help reduce out of synch possibilities.** -The access to economy hooks, has been moved in to the sychronized block. - - -* **v3.3.0-alpha.8c 2022-02-16** - - -* **Fixed a start up issue with multiverse-core in that it now runs the air-count processes so the mines can have their targetBlocks defined.** -Many issues were resulting from failure to get the target blocks. Not sure how it was working before, other than targetBlocks were not being used as much as they are now. - - -* **Fixed a potential error if targetBlocks are not loaded yet, or loaded at all for a given mine.** -Was causing NPEs.... - - -* **Added logging for when a delayed world comes online and list all mines that are activated.** - - -* **v3.3.0-alpha.8b** - - -* **Clean up the way the command tasks were being called.** -Added mine name to the blockEvent logging. - - -* **Fixed a reversal of some calculations when converting nano seconds to milliseconds.** - - -* **New feature: debug count down timer.** -Able to now set a debug count down timer where debugging is turned off after logging that number of entries. - - -* **Potential bug fix in better managing if sellall should be enabled by directly checking the configuration parameter that enables it.** -Better logging of sellall when inventory is full. - - -* **Commit some SellAllUtil comments that are useful for debugging timing issues.** -These are now disabled, but can be manually reenabled when needed. - - -* **Some changes to Sellall to provide more flexibility and to fix some potential bugs** -The isEnabled now uses the proper boolean settings to indicate if the sellall utility is enabled or not. Before it was trying to treat strings as boolean. - - -* **Add prison command descriptions that goes along with the placeholders.** -They are not yet hooked up, but they will provide more information to the admins on what the placeholders will provide, and also how they can use them since some of these will include examples of the formats. - - -* **Bug fix: The cancellation of the event was not being returned in the correct locations**, -so it was bypassing all of the before mine reset commands. The before mine commands will now run correctly. - - -* **Prison commands: reorganize some of the structures used for the prison commands.** -Hook up some of the logging to track run times for each command. - - -* **Prison commands: reorganize some of the structures used for the prison commands.** -Hook up some of the logging to track run times for each command. - - -* **Prevent the autosell happening just because someone is op.** -To make this work, and to prevent odd behaviors where OPs suddenly are not able to mine correctly, OP can no longer use the autosell based upon perms. - - -* **Setup the time durations on reporting of mine resets to use external settings.** -Enables the use of singular and plural unit names. - - -* **Rework how rankup commands are ran: in progress.** -This new way of dealing with rankup commands is to collect all commands that need to be ran, from all rankups, then run them in one group when the player is done being ranked up. -For most changes in rank, this will have zero effect on anything (mostly), but it has a huge impact with the **rankupmax** command. -When hooked up (which is is not), this will take all commands and run them in a sync task. So "every" command will run in a sync task. But each command will be monitored for run time, and if the runtime for one command exceeds a threshold, then the sync task will resubmit itself to run again after on tick. This will slow down the process of running all of the commands, but it will help prevent them from causing lag. -With tracking run times on each command, if prison is in debug-mode, then it will generate console logs identify how long it take to run each command. So if any given command is causing lag, then it would be possible to identify what the offending command is. - - -* **Fixed a problem before releasing... was not using the correct variable so the generated File object was not getting used.** - - -* **Bug fix: If a player cache file does not exist, it now prevents it from loading.** - - -* **Fixed an issue with the GUI, such that if the player does not have a rank on the ladder**, -that it will now force the creation of a PlayerRank object so it does not cause a NPE. - - -* **Mine bombs: Enable the use of color codes on the armor stands when setting off the bombs...** - - -* **Mine bombs: Added durability and digspeed enchantments to the mine bomb data.** -This will allow for greater flexibility in how the tool in hand behaves. - - -* **If using a mine bomb, then do not allow durability calculations to be used**, -since if the pseudo tool breaks, then what ever the player is holding will be removed, which is usually an item stack of mine bombs. - - -* **Mine Bombs: The mine bomb give command now is case insensitive.** - - -* **Mine Bombs: Add ability to set the Y offset.** -It defaults to a value of -1. This allows fine tuning of bombs to better position them to sink deeper in the mine to increase the number of blocks that are included. - - -* **Fix issue with mine bombs not dropping blocks.** -The underlying block changed and therefore so did the behavior of the equals() function. - - -* **Added various token functions to the prison spigot API class.** - - -***3.3.0-alpha.8 2022-02-12** - - -* **Enable debug mode from within the config.yml file.** -It was not hooked up before. This is useful for initial logging of the mine air-counts. - - -* **Redesigned the initial mine air-counts which not only identifies which blocks are within a mine upon startup, but it also establishes the number of air blocks in a mine to help ensure it's able to properly reset when the mine is empty.** - - -* **Bug fix: cleaned up the way PlayerCache files are managed.** -Eliminated a lot of old code and simplifed the logic to ensure the liklihood of preventing corruption of the player caches. There has been some reports that the files were not being properly tracked and stats were being replaced with new entries. This also fixes some performance issues by caching the files in the directories. So once loaded, the loaders no longer need to read the file listings, which could take a while with a lot of files. - - -* **Provide information on locale settings within the `/prison version` command.** -Falls back to the en_US properties file if the selected language file does not exist. -If the non en_US properties files are found to be missing a property, then the english property is used as a fallback. These fallbacks are not written back to the save files. - - -* **v3.3.0-alpha.7 2022-02-09** -Set this back on an alpha release schedule. The betas appear to have been pretty stable. - - -* **Disable the player's nms attempts to get their locale... spigot 1.17 and higher no longer can get that value.** -Just use the server's default value. - - -* **For the /prison support commands, the output is now sent to the player instead of just the console.** - - -* **Some minor changes to /prison debug to give it an alias of /prison support debug.** -Format a few of the messages to make it easier to understand. - - -* **Removed the backpack's object from the player's cache.** - Backpacks are too massive for the player's cache and needs thier own cache system. - - -* **On the command /ranks set tag, added the note that if a tag is removed from a rank, then the rank name will be used instead.** -Fixed the placeholder for rank tags so if it is null, it no longer show a null, but now it show the rank's name. - - -* **Fixed the generation of the player mined block count placeholders.** -Was missing one _ after generating the specific block related placeholder. - - -* **Upgrade gradle from v7.3 to v7.3.1 to v7.3.2 to v7.3.3** -This is at the latest release. - - -* **Upgrade gradle from v7.2 to v7.3** - - Changes to provide better security when runnign gradle to prevent injection attacks. - - -* **Upgrade gradle from v7.1 to v7.1.1 to v7.2.** - - -* **Upgrade gradle from v7.0.2 to v7.1.** -NOTE: There are a number of updates to apply for gradle. Will commit on the minor versions and final version. - - -* **Added a few new placeholders and a new placeholder type of PLAYERBLOCKS.** -Added raws to the player_block_total per mine. Added player_blocks_total and its raw counts, which is a PLAYERBLOCKS. - - -* **Added a few new placeholders and a new placeholder type of PLAYERBLOCKS.** -Added raws to the player_block_total per mine. Added player_blocks_total and its raw counts, which is a PLAYERBLOCKS. - - -* **Changed around the logging of messages related to the use of autofeatures autosell.** -Added permissions to enable autosell on a per block. - - -* **Update CustomItems api from v3.7.17 to v4.1.3.** -This newer version of the API still does not have a getDrops() function. - - -* **Add more support for CustomItems plugin.** -It appears like this is working really well with auto pickup. It should be noted that the CustomItems' API does not have a getDrops() so it's impossible to get the correctly configured drops for the block, so for now, it will only return the block itself and not any configured drops. -Sellall may need to be fixed and there could be some other areas that needs some fine tuning, but so far all is working well. - - -* **For CustomBlockIntegrations added getDrops().** -This has to be used instead of bukkit's getDrops() since that will return only the base item drops, which are the wrong items. -For CustomItems plugin, there currently isn't a getDrops() function in the CustomItems API so instead, the integration's getDrops() returns the block. - - -* **If cancelAllBlockEventBlockDrops is enabled when it's not valid on the server version, then it will print the error to console, then turn off this features** - - -* **CustomItems: Hook up on server startup the ability to check for custom blocks when scanning the mines to set the air counts and block counts.** - - -* **Clean up the formatting on `/mines block list` so it's easier to read and looks better.** - - -* **If fail on /mines reset, then needed a missing return so the mine reset success message won't follow the error message.** - - -* **Bug Fix: When mine reset time is disabled, set to -1, and then all mines are reset with '/mines reset `*all*` details' it would terminate the reset chain on that mine.** -This change allows the next mine to be reset by not trying to set this mine's next action... which is none because reset time is -1. - - -* **v3.3.0-beta.2 2022-02-03** - - -* **Added an error message when failed to add a prestige multiplier.** - - -* **New feature: cached adding of earnings for the default currency.** -This was causing a significant amount of lag/slow down when performing autosell, or spamming of sellall. The lag was in the economy plugin not being able to accept additions of money fast enough. -Now this simple cache, will wait 3 seconds before adding the player's earnings to the economy plugin. When it does, it will do so in an async thread so as to not impact any performance in bukkit's main thread. Also prison's getBalance() functions, which includes the use of all prison placeholders, will include the cached amount, which means the player's balances appear as if they are not being cached. -Still need to cache the custom currencies. - - -* **Update /ranks autoConfigure to set notifications to a radius of 25 blocks, and enabled skip resets at a limit of 90% with 24 skips.** -Also moved DARK_PRISMARINE down a few levels since it's not as valuable as the other blocks. - - -* **Bug fix: Correct the comparison of a prison ItemStack by using compareTo.** -The old code was using enums, so the check for equality of enums resulted in comparing pointers, which will never work. -Updated a few other parts of the code to use the compareTo function instead of the equals function since that may not work correctly all the time. - - -* **For command /mines set notification added *all* for mine name so all mines can be changed at the same time.** - - -* **Change notification alerts from runnign every 5 minutes to every hour.** -Got a few complaints within the last fewa days that the notifications are too frequent. - - -* **Modified SpigotPlayer to add getRankPlayer() and modified RankPlayer to add getRankLadder, with short cuts for default and prestige so you don't have to always refer to their names (reduce errors).** -This is to remove the "mess" from other functions that need to get these player objects, of which sometimes they are not going about it the correct way. - - -* **sellall multiplier add - Now reports if a multiplier cannot be added. Also now adds the multiplier based upon the actual rank name**, -of which it was what the user entered with the command, which may not match the actual rank name. - - -* **RankLadders - Added a boolean function to check if the ladder is the default ladder or prestiges ladder.** - - -* **sellall multiplier - Now able to list all multipliers.** -It lists them in a 5 column listing. - - -* **Add debug logging when calling the external events.** -Will have to revisit this when hooked up to multi-block events, otherwise it could overwhelm the logging. - - -* **Ladder rank cost multiplier has 100 percent limits removed.** -Value can be any positive or negative number now. - - -* **Update some documentation related to CMI Economy.** - - -* **Broadcast the prison welcome message to all online players when prison is loaded with no mines or ranks defined.** -The messag is loggd to console 8 sconds after prison loads. The broadcast messags are sent 16 seconds after logging the welcome message. -The intention is to help bring awareness to new mods/admins that there is an easy way to get started with prison. - - -* **Broadcast the failed ranks loading to all online players.** -Its important that they know ranks failed to load. - - -* **Release v3.3.0-beta.1 !! Hooray!!** 2022-01-29 2:11 PM EST - - -* **Added nano-second timing autosell to confirm if there is a performance issue.** -My initial testings are showing that sellall has significant chance of performance problems in that selling items takes way too long. Will address in the future. - - -* **Disable all ranks related commands within the GUI menus.** -GUI was bypassing safeguards that were in place when the ranks module failed to load. - - -* **Update the placeholderAPI docs to correct the formatting of the docs to match what they should be.** -Had to indent by two spaces. - - -* **Created updated documents for the placeholderAPI wiki.** -These are local copies of the content since the prior content was removed/vandelized. - - - -* **New Feature: Added support for Quests so that block breakage within mines can now be tracked and be applied towards quests.** - - -* **Bug fix: Lapis_ore appently does not drop lapis_laluzi when using the bukkit's getDrops() function, it instead drops blue_dye, then when it gets to the player's inventory, it is then converted to lapis_lazuli.** -Therefore, auto sell cannot sell lapis_ore drops unles blue_dye is within the shop. I added blue_dye with the same value of lapis_lazuli to the sellall shop. This allows it to be sold now through auto pickup and auto sell. - - - -* **Bug Fix: Damage was being applied all the time.** -Found a field being initialized with a value of 1 when it should have been 0. - - -* **Prevent sellall from loading if ranks does not load. Sellall uses too many rank functions to stand alone.** +** v3.3.1 2026-06-15** + Prison-3.3.1.jar <-- Support for spigot 1.8 through spigot 1.20.x + Prison26-3.3.1.jar <-- Support for spigot 1.21.x and spigot 26 (manual build) + + NOTE: the latest release of paper will be fully supported in v3.4.0. -* **Bug Fix: The new Ranks error message handler which intercepts all ranks messags was failing to load properly when prison startup was not set for a delayed startup,** - which was because the ranks gui command (/ranks) was always being set even when ranks module failed to load. Now /ranks gui loads only if ranks was successful in being started. +** v3.3.1 2026-06-15** -* **Initially setup to use the actionBar for the messages, but that is not working correctly with such high volume of messages.** -So disabled them for now, but will switch them over shortly... +* **Updated gradle config files && bumped to version 3.3.1** -* **Format the earnings amount properly, so it will have a consistant format.** -Once in a while, instead of showing a value like 165.00 it shows 165.000000000000001. This is caused by the fact that doubles are binary, not base-10 so it canot always show the correct values. +* See change log: **[v3.3.0-alpha - v3.3.0](prison_changelog_v3.3.0.md)** +* See change log: **[v3.3.0-alpha - v3.3.0 Part B](prison_changelog_v3.3.0_b.md)** -* **Deprecated the MessagesConfig class since it is not implemented correctly.** -The messages should have been handled through Prison's multi-language tool, of which this does not use. +# 3.3.0-alpha.19j 2026-06-13 -* **Try to use a different way to identify the item stack, especially if the bukkit item stack does not exist.** -This was a random error when using gravel, sand, and dirt on spigot/paper 1.12.2. -* **Clean up some of the refrences to the new/old block models.** -* **Added the new command: '/sellall list' that will list all blocks and their prices.** +
-* **Added comments that usage of auto features cancel drops will not work from spigot v1.8 through 1.12.x.** -Should work with v1.13.x and newer. -* **Fix some block issues, mostly getting the correct block bukkit block and limit it to only one location and function that ultimately provides these hooks.** -This release appears to be more functional, but it still should not be used since it's not fully tested. +- **v3.3.0-alpha.17** 2024-04-20 and older -* **First pass at removing the old block model. Do not use this release!!** -This compiles and runs on the server. Most commands appear to work, including mine resets, but no visual confirmation has been performed in game yet. Since so much has been changed and it has not yet been tested in-game, this release should not be used until such rudementary testing can be performed. + +
+# Older change logs: -* **3.3.0-alpha.7 2022-01-22** +## 3.3.0-alpha.7 2022-01-22* A return to the v3.3.0 release track. The alpha.7 release represents a continuation of where we left off before. Once we got to alpha.6, it became apparent that it was critical to release before v3.3.0 was ready, so we returned to the v3.2.x track, including everything up to and including the v3.3.0-alpha.6. - - - - - - - # 3.2.11 2022-01-22 - # v3.2.10 2021-08-22 - # v3.2.9 2021-07-03 -- release v3.2.9 - # v3.2.8.1 2021-06-18 -* **Note: Bug fixes for 3.2.8.** - -* **Fixed a failure on startup for new installations of prison.** -Basically it was unable to deploy the language files due to try-with-resources closing the initial zip connection. - # v3.2.8 2021-06-17 -Prison V3.2.8 Release! Prison now fully support Spigot 1.17 and Java 16! **NOTE:** Since the start of the development on v3.3.0, Prison has had a few other releases under v3.2.7 and v3.2.8. The reason for these releases is that the major structures (and code) that would make prison v3.4.x, are not complete. Therefore, to get out new updates sooner than later, v3.2.7 and v3.2.8 have been release. -* **Released v3.2.8!** - * **v3.2.8-alpha.3 2021-06-16** * **v3.2.8-alpha.2 2021-06-12** -* **Spigot 1.17 release - v3.2.8-alpha.1 - 2021-06-11** -Only known issues: - * Unable to use nms to get the player's preferred language + +* **Spigot 1.17 2021-06-11** + * **v3.2.8-alpha.1 2021-06-07** Internally set the version, but will not release it until a few other things are finished. @@ -2497,9 +104,6 @@ NOTE: v3.2.8-alpha.1 is identical to v3.3.0-alpha.6. V3.3.0 is far from being r * **v3.3.0-alpha.6 2021-06-07** -Setting the version. The v3.3.0 release will be put on hold since focus will be to get v3.2.8 out which will support Java 16. It is unknown how many of the spigot 1.17 blocks will be initially supported. - -* **v3.3.0-alpha.5c - 2021-06-06** * **v3.3.0-alpha.5 2021-06-01** @@ -2526,7 +130,6 @@ v3.2.6, v3.3.0-alpha.1, v3.3.0-alpha.2, v3.2.7, v3.3.0-alpha.3 * **v3.3.0-alpha.0 2021-04-11** - Start on the alpha.1 release. diff --git a/docs/prison_changelog_v3.3.0-alpha.18.md b/docs/prison_changelog_v3.3.0-alpha.18.md index 03c8b4480..b00927a39 100644 --- a/docs/prison_changelog_v3.3.0-alpha.18.md +++ b/docs/prison_changelog_v3.3.0-alpha.18.md @@ -15,6 +15,18 @@ These build logs represent the work that has been going on within prison. # 3.3.0-alpha.18 2024-05-20 + +Prison 3.3.0-alpha.18a 2024-05-21 + +Bug fix: There was a bug that surfaced that was being triggered by new player joins to the prison server. +The symptom was the spamming of new player join messages. +This was actually happening only if there were rank commands that would be ran for the initial rank assignment if it used rank related placeholder. The resolution of the placeholders were triggering another new player cycle. +This was a classic chicken or the egg situation. +It is unknown when this problem was first "setup", but it's only recently that it's been reported. It may have been there in the code for a few years, so not sure how many times this was encountered without being reported. + + + + **Prison-3.3.0-alpha.18.jar** This version of prison works with Spigot v1.20.6 and Paper v1.20.6. diff --git a/docs/prison_changelog_v3.3.0.md b/docs/prison_changelog_v3.3.0.md new file mode 100644 index 000000000..715e12acc --- /dev/null +++ b/docs/prison_changelog_v3.3.0.md @@ -0,0 +1,1673 @@ +[Prison Documents - Table of Contents](prison_docs_000_toc.md) + +## Prison Build Logs for v3.3.0 + +## Change logs + - **[v3.3.0-alpha - v3.3.1](prison_changelog_v3.3.0.md)** + - **[v3.3.0-alpha - v3.3.1 - Part 2](prison_changelog_v3.3.0_b.md)** + - [v3.2.0 through v3.3.0-alpha.17](prison_changelogs.md) + +* [Known Issues - Open](knownissues_v3.2.x.md) +* [Known Issues - Resolved](knownissues_v3.2.x_resolved.md) + + +These change logs represents the final changes to v3.3.0. + + +There were numerous changes that were made, here are some of the highlights: + +* Support Spigot 26 - Preliminary, but functional +* Support Spigot 1.21.11 +* Updated libraries that Prison relies on: + * XSeries + * NBT-api + +* Preparing for the v3.4.0 v4.0.0 releases + * Cleaning up a lot of old code + * Removal of a lot of commented out code + * Started with about 188,580 lines of code + * Ended with about 170,148 lines of code + * Removed about 18,432 lines + +* Added support for Spigot 1.21.10 and 1.21.11, including handling for new unknown blocks. + +* Initiated an architecture split into legacy (Java 1.8) and modern (Java 21) builds to maintain broad compatibility. + +* Upgraded core libraries, including item-nbt-api to v2.15.5 and XSeries up to v13.8.0, to support modern Spigot releases. + +* Massively improved performance for large servers (tested with 46,000+ players) by disabling pre-adding players on startup and removing bulk Bukkit offline player lookups. + +* Fixed multiple placeholder bugs, including NullPointerExceptions for offline players and incorrect player objects preventing mineplayer placeholders from working. + +* Added Premium Vanish support to reject block break events from vanished players and admins. + +* Fixed bugs related to selling inventory items held in the off-hand. + +* Fixed mine bomb item stack duplication issues that were causing lore and NBT data loss. + +* Introduced the ability to throw mine bombs with configurable throw velocities. + +* Added full Bukkit Entity support for mine bombs to enable complex armor stand animations like starburst, orbital, and bounce. + +* Added an option to bypass block validation, allowing the mining of falling sand and player-placed objects within mines. + +* Introduced a new BackpackEvent API to allow external plugins to hook into Prison's backpack auto-pickup and auto-sell processes. + +* Added an InventoryFullEvent to signal when a player's inventory becomes full. + +* Added a {range: } placeholder to generate random integer values within commands. + +* Added new global command placeholders {ifPerm:} and {ifNotPerm:} to conditionally control command execution. + +* Implemented support for highly customizable complex placeholders using the prison__ prefix. + +* Significantly enhanced sellall compatibility for handling custom blocks and blocks with custom names. + +* Added the /mines debugBlockBreak tool to test and troubleshoot block breakage events using external tools. + +* Completely rewrote the startup air block counting sequence to process one mine at a time, eliminating massive TPS lag. + +* Enabled the use of enchantments to trigger auto features like auto pickup, auto smelt, and auto block. + +* Created a /mines block preventDrops feature to stop specific blocks from dropping items. + +* Updated player file name formats to include player names and safely support Bedrock player UUIDs. + +* Introduced a /ranks reload players command to safely reload player files without requiring a server restart. + +* Added support for hex color codes in mine bombs and text formatting. + +* Integrated new economy support for EdPrison's economy and The New Economy. + +* Added zEssentials and zMenu as soft dependencies to ensure proper plugin loading order. + +* Fixed block selection rounding errors by using floor integer comparisons to prevent selecting the wrong adjacent block. + + + +--------------------------- + + +These change logs represent the work that has been going on within prison. + +# 3.3.1 2026-06-15 + +** v3.3.1 2026-06-15** + + Prison-3.3.1.jar <-- Support for spigot 1.8 through spigot 1.20.x + Prison26-3.3.1.jar <-- Support for spigot 1.21.x and spigot 26 (manual build) + + NOTE: the latest release of paper will be fully supported in v3.4.0. + +* **Updated gradle config files && bumped to version 3.3.1** + + +# 3.3.0-alpha.19j 2026-06-13 + + +* **Update the version of XSeries x11.3.0 to support 1.8 through 1.21.x and the newer version v13.8.0 supports spigot 2026.** +Update the goals for future development projects. + + +* **Prison Cleanup: prison-spigot: Removed obsolete and unneeded comments and fix indentation where needed.** Fifth and final part. All basic clean ups has been completed with this set. + + +* **Prison Cleanup: prison-spigot: Removed obsolete and unneeded comments and fix indentation where needed.** Fourth part. + + + +* **Prison Cleanup: prison-spigot: Removed obsolete and unneeded comments and fix indentation where needed.** Third part. + + +* **Placeholders: Bug fix. The wrong player object was being used with the placeholder processing**, so it was not able to identify the player's location, which was preventing mineplayer placeholders from working. + + +* **Prison Cleanup: prison-spigot: Removed obsolete and unneeded comments and fix indentation where needed.** Second part. + + +* **Prison Cleanup: prison-spigot: Removed obsolete and unneeded comments and fix indentation where needed.** First part. + + +* **Bug fix in the ChatTest Junit test. When I was cleaning up that source I accidentally introduced a stray '.'.** + + +* **Prison Cleanup: prison-core: Removed obsolete and unneeded comments and fix indentation where needed.** Fifth part. + + +* **Prison Cleanup: prison-core: Removed obsolete and unneeded comments and fix indentation where needed.** Fourth part. + + +* **Prison Cleanup: prison-core: Removed obsolete and unneeded comments and fix indentation where needed.** Third part. + + +* **Prison Cleanup: prison-core: Removed obsolete and unneeded comments and fix indentation where needed.** Second part. + + +* **config.yml: change the default setting on adding new players on startup. This is a major problem on large servers.** + + +* **Design documents: Starting to create some of the design and planning documents that will be needed in the next few phrases of Prison.** + + +* **Prison Cleanup: prison-core: Removed obsolete and unneeded comments and fix indentation where needed.** First part. + + +* **Removed some uses of the old block model. Breaking change: This removal should not actually break anything, but if upgrading from a version using the old block models, upgrade to an earlier release first to take advantage of the automatic conversion.** + +* **Removed a few other unused source related to the old non-functional troubleshooting.** + + +* **Renamed an enum to BlockEventCustomPlaceholders since it was not clear it was related to block events and that this has nothing to do with the standard placeholders.** + + +* **Prison Cleanup: prison-ranks: Removed obsolete and unneeded comments and fix indentation where needed.** + +* **Prison Cleanup: prison-mines: Removed obsolete and unneeded comments and fix indentation where needed.** + + +* **General cleanup: these are works in progress (wip) that have not been finalized.** If it's source, its been moved to a package with .wip.in the name. These may be deleted in the future or they could be used. + + + +** v3.3.0-alpha.19j 2025-12-10** + + + + +* **Bug fixes: There were some issues with a mine existing in the world that has not been reset, and as such, it had block types that XSeries did not recognize when running spigot 1.21.11.** These fixes prevents prison from crashing and is able to perform a mine reset so they can be replaced with known blocks. + + +* **Better logging messages when something goes wrong with the air-counts.** Also, prevent an error in one mine from being displayed for all remaining mines. + + +* **2026-02-24 Major cross roads: Spigot 1.21.11 requires XSeries v13.6.0, but prison is stuck at v11.3.0 due to support for spigot 1.8.** + - To move forward, I'm going to split prison in to a legacy build and a modern build. So the build will create two artifacts. The source code will remain the same for both, but it will be different java versions it will be compiled with, and different versions of libraries. Java 1.8's builds will be locked in to some plugin versions that cannot change, such as XSeries v11.3.0. Others will be able to be upgraded and use the latest. + - XSeries (block control within prison) will have to be spit... Spigot 1.8 cannot use any version newer than v11.3.0. + - Java: The legacy build will continue to be built with java 1.8. But the modern build may use java 21. I will have to figure out what is ideal, and what other libraries are using. + - Since the source will be identical, legacy builds should still get bug fixes and new enhancements. + - Along with this change, I'm wanting to retire the v3.x.x and release v4.0.0. There are a few core things that will change with the v4.0.0 release. + + + +* **2026-02-23 Upgrade item-nbt-api to v2.15.5 so it can support spigot 1.21.11.** + + + +**Spigot 1.21.10 support added. The addition of this new version has resulted in new blocks that are not recognized by the version of XSeries that prison is using.** +Could not upgrade Xseries about 6+ months ago due to breaking changes that were causing failures with spigot 1.8 and a few other old releases. These changes just ignores the unknown blocks, since prison would not be able to use them anyway. +Not sure how to deal with XSeries, but may have to split the builds. +There were also issues with building the sub-project prison-misc so that sub project was disabled since it's not directly being used. The issue is that there is a resource in that project that is depending upon a specific library which is part of the bukkit 1.13.2 build, but it's using the repo from spigotmc. Will address this later, when needed. + + + +** 2025-04-13 ** **Placeholders: Bug fix. When trying to access information through placeholders for an offline player**, it was throwing an NPE because prison was not able to get that player object from bukkit. +This bug was from a major change to try to get away from using so many calls to bukkit for a specific offline player since it's a very expensive operation because bukkit reads every player setting file until it finds the correct one. So on servers with over a few thousand players, it can contribute to a lot of lag with a few player requests. + + + +** 2025-07-26 ** **Mine bombs: Identify the name of the mine bomb in chat.** +I don't recall the significance of this addition, but there was an issue with not knowing what mine bomb was active? + + +** 2025-09-14 ** **Premium Vanish: If a player is using Premium Vanish and they are vanished**, then prison will reject all activity from that player and will cancel the block break event. +This is to prevent a vanished player (admin) from accidentally breaking blocks in mines while vanished. + +** 2025-07-26 ** **Bug fix: Prevent an NPE when a sellallItem is null.** Generally this should not happen, but there was another bug that caused that object to be null, so this fix is just an extra insurance. + + +** 2025-07-28 ** **Fix a bug with inventory items being held in the off-hand.** If I recall, this was a potential exploit under some circumstances. Added support for selling through the off-hand, and provided fallbacks for older versions of spigot, such as 1.9. + + +** 2025-07-26 ** + +* **Players: Bug fix. If unable to get a player's default rank, then return a null from the function.** + It was recording that an error happened, but it was returning a null, but continuing on with the processing as if it has a valid rank. This was not a commonly occurring bug, but was happening with edge case testing. + + + +* **Mine bombs: Fixed an issue with the item stack not correctly duplicating itself when transitioning from an item in hand to being placed or thrown.** +As such, lore and NBTs were being lost or removed, which resulted in the mine bombs not being recognized when going through the explosion processing. + + +* **Mine bombs: Added a mine bombStatus so it's better documented if a mine bomb was successful or not.** +Toned down the status message after a mine bomb is submitted since it sounded like it may always be a possible failure when it really isn't. The bombStatus will now be a clearer indication on success or not. + + +* **Mines: Startup air block counts: Changed slightly to start this task later, and to put a slightly longer delay between mine counts so it puts less load on the server.** + + + +* **Mine Bombs: Fixed some issues with mine bombs, such as prison is now check all "throw" events, even if another plugin cancels it.** +Eliminated a few NPEs since some of them are now being triggered since validation can be turned off. + + + +* **Mines: Support falling sand and player placed objects.** +Prison normally does not support mining blocks that it did not place in the mine. The reason is to prevent players from getting credit and money for mining invalid blocks, of which, could lead to other problems. But this also prevents mining sand blocks when they fall because their supporting blocks were removed. +This change now turns off prisons validation of the blocks that are being mine, which will allow mining of fallen sand. As a side effect, it will allow mining of any block found in the mine, for better or for worse. +To enable this, start prison so prison can modify the autoFeaturesConfig.yml file. Then edit it and set the following setting to false: +'validateBlocksWerePlacedByPrison: false' + + +* **3.3.0-alpha.19i 2025-06-26** + + +* **Mine Bombs: Bug fixes. There are a few bug fixes in these changes which were resulting in mine bombs not working at all, or causing some odd behaviors.** +One internal change was to pass the mine in to more functions so some of the processes can be more mine aware, and to prevent trying to find the mine a second time. Benefit is reduced processing and slightly faster speeds. +One issue was that the initial block being processed for the explosion was not actually in the mine when it was on the surface, so prison would ignore that event. Fix was to shift the block down in to the mine so it would be usable. This was primarily when the Y-offset was set to ZERO. If it was any negative value, then the bombs would work well, but zero was the default value. +Some messages sent to the console have been enhanced to provide better clues with what's happening when in debug mode. So if it is a config setting that is preventing the bomb from being tied to the mine, it will be more obvious. + + +* **Locations: Fixed a potential problem with getting the wrong block, or processing the wrong block.** +Found the older code was rounding doubles within the block, so instead of being able to confirm that the given block was the same as another, if the position was greater than or equal to x.5 then it would round up to a different block next to it. +Fixed by using floor and comparing integer values so the selected block will always be the same block. +I am not aware of any specific reported bug related to this problem, but it would have occurred around selecting blocks (like when laying out a mine) or be an issue one the edge of mines where if a block is hit near the edge the rounding could have checked the block outside of the mine instead. I suspect occurrences of this bug were not too frequent, and appeared intermittent. +Note that in the prior commit, BoundsTest class was also benefiting from this fix and should have been included in this commit. + + +* **Bounds: Fixed an obscure bug where changing the World was not updating existing instances of a world.** This would mostly be impacting unit tests, so this would never have been an issue with actual running of prison. +Cleaned up the equals since something was not looking correct with some of the logic. Nothing really changed, but slightly altered to simplify the logic to ensure there are not problems. + + + +* **Mines: Last block break bug fix. Fixes an issue where the task to break the last few blocks is getting canceled on some servers because the mine reset is running before the blocks can be removed.** +The mine reset was canceling all tasks, when it should not be. The idea of canceling the tasks was if there was another reset being submitted, but that cannot happen due to the mutex. + + +* **Blocks: added an isPassable() function to the compatibility functions since this function does not exist in bukkit versions less than 1.14.** +This is used when throwing bombs. + + + +* **Change logs: Restructured the change logs so the primary file is not quite as large. It was starting to run in to some lag issues when editing.** + + + +* **Prison was hard coding the teleport message.** Not sure why it was not hooked in to the language files, or if it was, why it was removed. +Rehooked it up. + + +* **Added zEssentials and zMenu to Prison's soft depends so prison will load after those plugins.** +There was an issue with prison trying to access vault's economy before zEssentials could properly hook in to it. This should allow zEss to fully enabled the economy now. + + +* **3.3.0-alpha.19h 2025-04-07** +The build for alpha.19g did not reflect the correct version. So incrementing the version so it is clear if someone is using the correct version or not. + + + +* **3.3.0-alpha.19g 2025-03-31* + +* **These was a problem with hex color codes being used in lore (or elsewhere probably) where they are not being translated unless there is another color**, such as &7 anywhere else in the String. +The problem was that the hex conversion was working perfectly well. But since the "dirty" variable was not getting modified, since the hex colors were applied before that point in processing, it would always revert back to the original unchanged String value because it thought there was nothing that changed. +To fix the problem, I eliminated the dirty variable and am always converting the byte array back to a String value. So no need to check if dirty anymore, since it always converts. + + +* **MineBombs: Fix the way players are used to resolve a few issues with the player objects.** + + +* **Ranks: Change the way ranks player get the player objects, especially when the player is offline. +This fixes a few issues.** + + +* **Prison Utils: Changed the way the platform players are used to resolve some issues when the players are offline.** + + +* **PlayerCache Timer Task: Redo the submission of the task to be self contained and will not initiate the task if the Ranks are disabled.** + + +* **Player: Change the way to get a platform player. Tie it to the Platform, and to use a new way to construct the SpigotPlayer and the SpigotOfflinePlayer** by creating a static function that can take a RankPlayer object. +This fixes some of the issues with getting the wrong bukkit player object, or none, even when the player is online. +By putting the bukkit code directly in the SpigotPlayer and SpigotOfflinePlayer objects, it's able to bypass some of the abstraction that was found in the platform class. + + + +* **Placeholders: added a comment to better explain the hex colors.** + + +* **Ranks: Fixed a few issues with '/ranks player' be issued by the player.** +Added last seen date to the player objects. + + +* **MineBombs: Added the new cooldown message that is in the MineBombCooldownException to the core messages.** + + +* **Sellall: Ran in to a situation where an ItemStack that was being processed did not have a bukkit ItemStack internally, so it was causing an NPE. ** +This fixes the issue by checking to ensure the bukkit ItemStack exists first. + + + +* **BackpackEvent: New api using a backpack event to allow other plugins to hook in to the prison backpack processing which will behave as a new Backpack Integration.** +This will allow anyone to easily hook in to Prison's generic backpack behavior for auto pickup and autosell. +This new event is tied to the new IntegrationBackpackAPI. Basically, to perform a backpack operation on an unknown backpack source, the BackpackEvent collects a list of Inventory objects from the backpack, which allows prison to operate on the generic Inventory, and then it offers the use of a CallBack that will allow the backpack plugin to process the results of the actions against the inventories. + + + +* **MineBombs: Players: Ranks disabled: Made some changes to how players are being loaded in the 'bomb give' command to allow it to work when ranks have been disabled.** + + +* **MineBombs: Eliminated cooldowns from the 'utils bomb give' command and from prison checking to see if an items is a mine bomb to determine if the event should be handled.** +This should get rid of the bug where using bomb give too frequently would result in error messages and lost bombs (if a player is paying for a bomb). + + +* **MineBombs: Added a cooldown exception so cooldowns can now be handled and reported correctly. Before the "bomb not found" message would be used, which was confusing.** + + +* **MineBombs: Improvements to the command '/prison utils bomb list' command to better format the information and include some missing details.** + + +* **Bug fix: CommandSender: Was causing a type cast exception when trying to TP a player from the console.** +The CommandSender was assuming the sender was always a player object, when it shouldn't have been doing that. + + +* **Bug fix: CommandSender: Was causing a type cast exception when trying to TP a player from the console.** +The CommandSender was assuming the sender was always a player object, when it shouldn't have been doing that. + + + +* **Players: CommandSender: Added a new transient field miscText that can now be used to return a message to the caller.** +For the command '/mines tp' if a player tries to tp to their current rank's mines, and if that rank does not have any mines connected to it, it will now step back through all prior ranks until it finds a mine to TP the player to. +This returns a message that can be used, indicating the current rank, but indicates the next highest rank that had a mine. +This message is not yet externalized. Including a TP message indicating where they player has been TP'd to. + + + +* **CommandHandler: Expand the tracking of command stats to track the usage of aliases.** +The command '/prison support cmdStats' has been updated to include alias usage counts. +Usage of aliases would not be tracked at all, even the primary command. + + + +* **AutoManager: PEExplosionEvent - remove a debug statement that was showing up in the console when not in debug mode.** + + +* **InventoryFullEvent: Start to setup a prison based event that will fire when prison detects that the inventory object is full.** +This is useful for when other plugins, or customization to prison needs to perform an action when the inventory is full, such as handling a custom sell all action. +This new event offers cancel, but there is nothing to cancel within prison since canceling the event will not alter the inventory. It can be used to signal to other plugins that the event was handled by another plugin. + + +* **Mines block preventDrops: Improve the help documentation so it's clearer on what it actually does and how to use the command.** + + +* **PrisonRanks: A couple of other changes to help ensure there are no issues if Ranks are disabled.** + + +* **Ranks: Setup the PrisonRanks so getInstance() will not return a null and to ensure that isEnabled() returns false if Ranks is not enabled through module configs.** + + +* **RankupMax: Fix a bug where after successfully ranking up a few ranks, it always shows an error message related to the last attempt because the player cannot afford the next rank.** + + +* **Rankupmax broadcast bug: Sending the console log message to all players and the player too.** +Now sends the broadcast message that is associated with the normal rankup command. + + + +* **Prison debug: Add a 'commandHandler' to the debugger activeTargets so that way you can selectively enable a commandHandler log message outside of if debug is enabled or not.** +This is to troubleshoot if bukkit is actually passing commands to prison correctly. + + + +## 3.3.0-alpha.19f 2025-02-15 + +* Support for spigot/paper v1.21.4 +* Bug fix: NBT-lib. If NBT-lib fails, prison no longer allows the stacktrace to fill the console/logs. This library needs to be updated with each release of paper/spigot and when it is out of date it can throw a lot of errors. +* New prison command placeholder: `{range: }`. Can be used in rank commands, mine commands, ladder commands, and even Block event commands. This can help insert a random number in your commands, such as a random number of items that you may give a player. +* Bug fix: Players when reloading players, or on server startup, player's ranks could have been reset. This fixes that issue. +* Bug fix: Rankups. Changes to how internal references to players caused some problems on some commands by not returning the correct player objects. See next item. +* Bug fix and enhancement: There was an issue with how prison would get player objects from bukkit. It generally wasn't a problem, unless you had over a few thousand players. The problem was that prison would get OfflinePLayers from bukkit, and that would cause bukkit to lag the server badly since it would consume a lot of resources and time trying to find player files within the bukkit world folders. Prison no longer asks for OfflinePlayers. Prison was tested with 35,000 + players and the issue is now resolved. +* Sellall and Blocks: Updated some of the internals in sellall to be able to better support custom blocks that have been added to sellall, but are not within prison. Prison cannot spawn these blocks, but it can sell them now. +* + + + +* **Placeholders: Updated the docs to include the new command placeholder: '{range: }'** + + + +* **Players: On reloading players, and also sometimes on server restarts, player's ranks were being reset back to the default ranks on each ladder.** +This was caused by a bug where the rankId was trying to be used instead of the rank name. RankId is obsolete, but is still in the code so older player files can be loaded and converted to the new format. +The code that handles this conversion, and the basic loading, was rewritten to properly handle the rank name and rankId if it is still required. + + +* **Sellall: Removed use of ConfigurationSection since it works fine until a new value is being added.** +It was easier to roll back to how it was than to add a bunch of other code to add it if it does not exist. + + +* **Prison Commands: Added a new prison command placeholder '{range: }` that can be inserted in commands used in ranks, mines, or block events.** +This inserts a random integer value in the specified range. +This is good to provide some variation when issuing commands like give or other type of events. + + +* **Prison versions: Updated the internal references to java versions up to java 29.** +25 is the highest official value, but extended it by four extra versions just in case this is not revised between now and then. + + +* **Rankup: Found that a parameter that should not be null was being passed null in a few places.** +This was a problem in a few places for 'rankupmax'. +The RankPlayer object that was expected was available so it was a simple fix. + + +* **NBT & MineBombs: addresses an issue with NBT-Lib caused stack traces when used on a newer platform that the NBT lib has not been updated for.** +This also fixes the issue (my fault) where the exception that was being thrown was NoClassDefFoundError extends from Error, not Exception, which is what the try-catch was trying to intercept. +This now will prevent the exception and it will fail silently. + + +* **Rankup: Fixed a problem with rankup commands not using the correct player objects.** +Simplified how some of the player objects are used to eliminate this issue. + + +* **Startup block checks: Had to make changes to the handling of XMaterial since the latest versions are more brittle since they tend to be conflictive with itself.** +There are now a few block types that actually cause problems if used or accessed. +It appears as if 1.21.4 made major changes in how some blocks are identified, and XMaterial has not yet fully caught up with those changes? +This change captures exceptions caused byXMaterial, when in the past, it would only return a null value instead of throwing an exception. + + +* **Sellall: Major changes to better support custom blocks. Not perfect overall, since some aspects are not fully handled, such as enchantments or filters on specific nbt values.** +These changes fixes most of the issues with identifying custom blocks and allows them to be sold. This also fixes a lot of the internals on sellall, which is forcing a lot of movement away from XMaterial and relying more on PrisonBlocks. +Added better error messages to many functions, instead of just a generic stack trace. Need to do many more. + + +* **NBT-Lib: Upgrade from v2.14.0 to v2.14.1 so as to better support v1.21.4.** + + +* **Ranks: Some rank commands were failing to work properly because they were not getting the correct player.** +Instead of getting the play by name, it was using the sender, which would have been the player issuing the command. +This was an issue with '/ranks promote' and '/ranks demote' when issued in game. +This was fixed by only allowing the named player to be resolved, without giving the sender an option to be used. This was changed in a number of areas to help protect form possible errors. + + +* **PrisonBlock: Add isSellallOnly to prevent blocks added through sellall from being used in mines.** + + + +* **Sellall: Much better support for blocks with custom names.** Both for rejecting the wrong blocks, but also for now being able to sell them. +These changes are not perfect and does not support some conditions. +Prison currently does not support multiple custom blocks with the same material types and the same display name. +These blocks that are added through sellall should never be used within mines because prison cannot create those blocks to place in the mines. +New command: '/sellall addHand'. Improved a few other commands too such as '/sellall list' and '/sellall items inspect'. + + +* **PrisonBlock: Significant modifications to support non-prison blocks for sellall.** +The alters many behaviors to allow for almost any dynamic custom block name, outside of the supported custom items. +Created constants for the selection wand, both for the PrisonBlock and the item stack. +These changes will support sellall's use of more dynamic block names that are not within prison. If it is a custom block name, then it will be added to prison's list of blocks. These should not be used in mines since prison cannot generate them faithfully. + + + +### Version 3.3.0-alpha.19e 2024-12-14 + + +* **Updated nbtApi from v2.13.2 to v2.14.0. This should provide better support for spigot 1.21.4.** + +Tried to update XSeries to v12.0.0 but it failed. It does not appear to work with spigot v1.13.2, which is the version which prison uses for building it's jars. Will have to figure this out later, maybe their release v12.1.0 will address these issues. + + + +* **Doc updates: Provide more information on '/mines set resetThreshold' and the new command '/mines debugBlockBreak'.** + + +* **Mines: Debug block breakage. Created a new command '/mines debugBlockBreak` that will now be able to use tools from other plugins.** +Realized there was a problem with using the mine wand when testing block breakage in that you could not test with any other tool, which would prevent other plugins from handling the events like they should. +So now, by holding any tool in your hand, and issuing the command '/mines debugBlockBreak' it will test the block breakage with whatever they are holding. + + +* **Players: Fixed a problem with getting the vector for where the player is looking. The actual vector was getting lost so the result was that nothing was able to be properly calculated.** +This was fixed by creating an internal prison vector which could be used instead. + + +2024-12-14 + +* **Prison was gifted over 46,000 players!!!** +Someone who was running in to performance issues with prison on a large server, gifted me over 46,000 players in both prison and in bukkit. Now I can perform various testing with larger player bases to help fix and prevent performance issues. + + +* **Major Prison performance cleanup:** When there are a few thousand players on the server and in prison, prison was running in to major performance issues that was basically killing the performance of the server. +One major cause was with the startup routine of trying to add players that are on the server, but not in prison. This could run for literally days and consume tons of processing resources. So prison no longer tries to pre-add any player. They have to join the server to be added. +The other major problem, was that if prison was trying to lookup a player that was not online, it would hit bukkit's offline players, and it would get a full list of all offline players. This was horrible! Bukkit would have to read all player files to generate the offline players listing, which could take a long time. For example, with 46,000 players, it could take a few minutes for bukkit to fully load all players, and during that time, paper starts generating tons of warnings stating the server is not responding correctly. It does not kill the server, but it generates mega bytes of errors in the log files. +So to fix this problem, prison no longer uses the bukkit offline player's functions unless trying to access ONE offline player using strictly their UUID. A name search would require almost all files to be searched too. +As a result, prison is far more stable for very large player bases on servers!! This is a major improvement. In the past there has been complaints about prison when there were a lot of players, but I was never able to zero in on the problem since no one was really willing to work with me on figuring this out. What helped a lot was being gifted over 46,000 players. :) So now I can do some serious testing with many players. + + +* **Rankup: would not work for ladders other than default and prestiges. Fixed.** + + +* **Update xseries to v11.3.0 from v11.2.1.** + + +* **Mines: checking access. This change breaks down the access checks to see if a player has access to a given mine so it can be properly logged when in debug mode.** +It's been a problem trying to figure out why some events would work or wouldn't, now this will help identify access related conditions. Example is the use of mine bombs. + + +* **Mines: Hooking up a test dump to the mines commands so I can more easily test what JSON is generated with the current settings and configurations.** + + +* **Mines: Hook up the reconnectObjects() function so it will be able to hook up the dependencies.** +This is not hooked up yet, but will be used with the new ORM json manager. + + +* **Mines: adding transient to Mine data so it will not try to save the temporary and transient data when using ORM is generating json data from it.** + + +* **Ranks: a user reported a null pointer issue so made some changes to prevent it.*** +Was not able to reproduce it. + + +* **Mines: relocate a few objects to pull them out of MineData since they are constants.** + + +* **Mines: reconnectObjects() is a way to re-hooked up objects that could not be saved/stored when loading these objects from the database/files.** +These currently are not enabled or tested yet, but they are the foundation of getting the new process working to support a new way of storing and loading data. + + +* **Auto Features: clear bukkit clearDrops.** +An issue using an older version of prison resulted in the targetBlock being null. This has not been reproduceable with the current version of prison, so it's probably been fixed at it's root levels. But this change was made just to ensure it does not become an issue in the future. + + +* **PrisonBlock: Fix an issue with PrisonBlock setting a class variable that is also set within it's parent class.** +Overall, at a rough level, this does not cause a problem with the current prison environment. It's wrong. But it works. +Where it is failing is when prison is trying to setup ORM on the Mine object to simplify and expand the capability of future enhancements.. + + +* **Mine Bombs: Improve the debugging information on when mine bombs are selected, or rejected based upon the player having access to the mine or if a cooldown has rejected the mine bomb.** +SpigotPlayer: Using bukkit's block.isPassable() on getLineOfSight(), but may need to be extended to getLineOfsightExactLocation(). +It was not clear why mine bombs were not working. + + +### 3.3.0-alpha.19d 2024-09-26** + + +* **Prison blocks: It was realized that due to a recent expansion of the items that are included in the default for sellall, that the first 27 or so entries, were the blocks that were used in the auto generated mines when running the command '/ranks autoConfigure'.** +These first few blocks, were returned to their proper place so the mines are properly populated again. +Also, since blocks from multiple versions of spigot have been added, new code has been added to prevent adding any block that is not support by the version of spigot that the server is running. + + +* **Sellall startup messages: Fixed some formatting issues that were causing a misrepresentation of the sellall configurations within the startup logs.** + + +* **Prison Backpacks: Found that the startup messages for backpacks was using references to sellall configs, which was incorrect.** +The messages are now corrected. This error appeared as if sellall was being setup and configured twice, which it was not. + + +* **Sellall: The sellall initialization function was being called twice by error.** +As such, this prevents a duplicate message from appearing in the startup log. No problems were caused by calling initialize twice, but it was unneeded. + + +* **Mines: Startup air block counts. Bypass processing if no mines exist.*** +This prevents an error when starting prison for the first time before any mines can be defined. + + +* **Mine Bombs: When loading the default bombs, this change now prevents the display of "warnings" which are actually normal because the settings for the wrong spigot platform must be removed.** +This now uses the check to see if the mine module has been enabled, and if it has mines, if not, then it will not purge any of the mine constraints since the server is probably under construction and they should not be purged until the mines have been setup. + + +* ***Prison modules: Added an element count which reflects how many elements are loaded for each module.** + Examples would be ranks and mines, or number of prison utilities that were enabled. + + +* **File storage: Prison was changed a few weeks ago to precheck some of the critical folder structures to ensure they are there.** +That change was causing problems when creating a new instance of prison since the old code would fail if the directories were already there, which made no sense. + + +* **WorldGuard Regions: Enable the commands to be able to be ran from the console and through online players.** +Disabled the Mine-Area commands related to the WorldGuard regions because mine areas are not yet implemented. + + +* **Player: the code that gets a player object based upon a name has been altered to address a few issues.** + + +* **WorldGuard Regions: Updated the configs to include placeholders for the world, and updated the code to support it too.** + + +* **Custom placeholders: Fix an issue with the custom placeholders changes being able to correctly count the aliases in the command `/prison commands list`.** + + +* **Custom Placeholders: Added support for a more complex custom placeholder where the default is an abbreviated placeholder (simple) and a more complex expanded placeholder where you can set various options such as enable PAPI expansions and adding descriptions.** +Added custom placeholders to be included in the `/prison placeholders list`. +To view all custom placeholders, as translated, search for the custom placeholder prefix: +`/prison placeholder search prison__` + + + +* **Added a new function to the platform to check to see if there is a specific configuration section.** + + +* **Custom Placeholders: A custom placeholder is identified with the prefix of 'prison__' but one of the functions that cleans the placeholder fragments sent to prison, was removing one of those underscore characters.** +This preserves the needed underscore and allows for proper matching and identification. + + +** 3.3.0-alpha.19c 2024-09-20 ** + + +* **Build automation: github has deprecated and disabled version 1 and 2 of the actions, and v3 is slated to be disabled in Nov/Dec of this year too.** +So moving on to v4 to allow for better future use. +This prison build script is very simple and therefore the newer issues related to v4 when upgrading from older versions, should not impact prison. Basically the largest change is that these artifacts are now immutable. + + +* **Mine bombs: Not a significant change. Allowed the mine bomb data to be part of the event that is being passed along so it can be used in later updates and future features.** + + +* **Placeholders: Realized that the "uppercase" integration hook for placeholder API is not used.** +Realized that placeholder registration is done without sensitivity to the case used. + + +* **Custom Placeholders: Created support for custom placeholders that are defined in the config.yml file, and one simple short custom placeholder will be replaced by any combination of text and other placeholders.** +This way you can define complex placeholders within prison, and then use the short custom placeholders in other config files, which will help a lot if you are limited by characters. + + +* **Auto features: PrisonEnchant's listener: minor changes to only display the registration notice once.** + + +* **Removed various comments that were auto generated.** + + +**v3.3.0-alpha.19b 2024-09-09** + + + +* **Block Break Listeners: If in debug mode, and there is a fast fail, or an ignore on the blocks being broken, log the reasons why.** + + +* **Minor: variable not being used, so commented out to eliminate a compile warning.** + + +* **Mines: Air Block Counts: A few more fixes. Found that 'position' was not being reset on each mine, which was causing partial, or no resets for most mines.** + + +* **Mines: Air block counts: Minor change to the completed message to be more consistent with the other similar messages.** +Changed "-" to "of". + + +* **Ranks and Ladders: Minor changes to prevent new ranks and ladders from getting assigned a non -1 id.** +All new ranks and ladders will have an id of -1. All existing ranks and ladders will keep their ids. + + +* **Ranks and Ladders: Changed the way the ladder and rank file names are saved. Instead of using their IDs, it is now using their names.** +The file names are converted upon loading. Once loaded, and converted, the prison config setup cannot be reverted, but the old settings and files will be saved in the saved directories and can be restored if needed. +Rank IDs and Ladder IDs are no longer used internally. They are being kept for now, but will be removed in the future. + + +* **Mines: Air Block Counts: Improvement. Rewrote the way prison is handling the air block counts because they were causing the servers to fall behind on TPS by a significant amount.** +The server, depending upon how many mines, and how large they were, the system (spigot, paper, etc) would warn that it was running behind by 50 ticks to a few hundred ticks. The primary reason was that all the mines would be submitted to run almost at the same time, in different threads, so it would starve all available TPS. +These changes were a complete rewrite on how the jobs are submitted and the mines are processed. Now it's just one initial job submission, instead of each mine submitting it's own task. And that one new job steps through each mine, one at time, counting the blocks, and then moving on to the next mine. As such, we are not ensuring only one task is trying to run at the same time, thus allowing other services to get sufficient access to the processing that they need. Where a mine-heavy test server was reporting falling behind by 600+ ticks, after these changes there were no warnings. During, and right after the air counts, the server is reporting a solid 20 TPS. + + +**Prison v3.3.0-alpha.19 2024-09-07** + + +* **Mines: Air block counting on startup: Change some of the setting to be less demanding on the server.** + + +* **Change the prison TPS monitor to a singleton.** +Will be using this in the near future to monitor system loads. + + +* **Mines: Minor change: Simplify how the command is ran so there is one exit point instead of two.** + + +* **AutoFeatures: PrisonEnchants (Pulsi's): Made changes to handle explosion events that happen outside of the mine, but there are some blocks that are within the mine.** +This prevents PrisonEnchants, or bukkit, from breaking the blocks within the mine. + + +* **Auto Features: Added support for 9 new Blocking combinations.** +These can be individually controlled to disable. + + +* **Auto Manager: Use RevEnchant's fortune.** +This may have been a bug, but not sure. Was successfully loading Rev's fortune level, but it appears like the default minecraft fortune level may have overwritten it. If so, its now fixed. + + +* **Auto Features: blocking: Fixed a bug where 'blockAllBlocks' was incorrectly using 'smeltAllBlocks'.** +Fixed. 'blockAllBlocks' now works properly. + + +* **Auto features: PrisonEnchants plugin support.** Adjustments to get it to work better for all versions. +Needed to have it perform the checks in two different areas. + + +* **Auto Manager: Bug Fix! I realized by chance that the whole normal drop config was setup incorrectly! This was fixed.** +What was wrong, was that the normal drops for smelting and blocking were not tied to the perms, lore, and enchantment activators! +Also I found that if auto features (auto pickup, auto smelt, and auto blocking) is disabled, then it was bypassing normal drop processing too. +So these fixes have normal drops correctly get used if auto pickup is not used. For example, if auto smelt is enabled, but auto pickup is off, and auto pickup does not get triggered by lore, perms, or enchantments, then it will fall back to normal drops and will enable the smelting for that. + + +* **Mine reset: Not sure if this was a problem but found that the wrong value was being used as a key to access a set of blocks.** + + +* **WorldGuard Region support: Starting to add WorldGuard region support to mines.** +These initially are intended to help create regions, update regions, and view the regions based upon the mine sizes. +There are some default command listings in config.yml so they can be customized and expanded to meet your server's needs. +The commands are: `/mines worldGuard region` + + +* **Startup directory check: Changed where and how the startup directory check is ran so it is actually included on startup, which it was skipping it.** + + + +* **Mine block searches: Changed them so if the command is ran from the console, it will list all items without any paging.** + + +* **Sellall Items: Expanded the number of default sellall items.** +Can use `/sellall items setDefaults` to add the missing items. + + +* **Auto Features: Can now trigger auto pickup, auto smelt, and auto block with the use of enchantments.*** +This adds to the ability to trigger them with Lore and permissions for greater flexibility in working with other plugins. +The enchantment names must be the full qualified name as found in the blockbreak debug messages that shows the details for that tool, or you can use `/sellall items inspect` while holding a tool with the enchantment you're interested in using. +For example, enable auto features, but keep the globals turned off, then enabled the custom enchantments and add 'minecraft:smelter' to both the auto pickup and auto smelt enchantments. This enchantment is from another enchantment plugin and is not standard, but this is how it's listed. Note that you can also use the same enchantment in more than one option too. + + +* **Moved the Prison File System Check to the PrisonStatsUtil class and got it out of the SpigotPlatform.** + + + +* **Player Cache: Fixed a problem with creating missing directories.... forgot to use the parent of the file, which is the current directory for the player cache files.** + + +* **Mine bomb: Added more features for control of the animations: ** +radius, radiusDelta, alterateDirections, animation speed, and spin speed, and armorstand item location. +This is working pretty good overall, but still needs to do some work on the related spin. + + + +* **Added a new feature to the prison versions information: Directory path checks.** +If a specified directory is missing, it will be created to prevent possible errors in other parts of prison. See last commit. +This reports the path, number of directories and files, with the file's total size in that directory. + + +* **Bug fix: If someone deletes the playerCache folder, it was causing failures in trying to create new player cache files.** +Fixed by using '.mkDirs()' to ensure the path fully exists before creating the temp files. +Also eliminated the stack trace and replaced it with a one line entry in the console. + + +* **Blocks: Update the list of blocks that can be effected by gravity (fall when disturbed).** +Added falling_sand, falling_block, suspicious_sand, suspecicious_gravel + + +* **AutoFeatures: EntityExplodeEvent: Fixed a few issues with how it was setup. ** +Apparently the event can be fired with zero blocks! This now handles that situation and will bypass handling of that event, but it will log a warning in the console. + + +* **AutoFeatures: Changed the debug logging on block break events and explosions, to better encode them with color so important items stand out better.** +Plus added logging on features that were not covered before: If a mine reset was triggered, how many block events were submitted. +If the blockbreak task is submitted with how many blocks it's changing. +If minesweeper was submitted. + + +* **New feature: Mines: Prevent a block from dropping drops!** +This can be used to setup something like lucky blocks, of which the player does not get paid for this block, nor do they get the block or whatever bukkit would normally drop. +The new command is: `/mines block preventDrops help`. +This saves the new feature with the mine data, and works with normal pickaxes, explosions, and also with silktouch to prevent the drops. +The debug information for block breaks has been updated to properly report on how this is working within handling the events. + + +* **Sellall: Changed '/sellall items inspect' to print everything to the console, and to decode the lore so it shows all of the color codes.** +This is critical for understanding how lore is setup so you can use the auto features lore settings. + + +* **3.3.0-alpha.18d 2024-08-27** + + + +* **ExcellentEnchants: Added support for org.bukkit.event.entity.EntityExplodeEvent.** +This fixes some issues where the initial changes were not fully finished. + + + +* **Mine bombs: Minor adjustments.** +There still are changes that are needed, but I'm needing to post a new alpha release before I proceed to wrap up the mine bombs. +They are getting very close to working as intended, and I'm wanting to add more features to the bombs, along with changing a few other things too. +But for now, a new alpha needs to be pushed out because other issues have been addressed and fixed. + + + +* **Material validations: The validation process was generating a ton of warnings for all items and blocks that exist in minecraft, but yet cannot exist in an item stack.** Such as wall hangings, water, etc... since they are fixed in the world, and when in itemstacks, they are represented by something else, such as an ItemFrame or a Bucket of Water. +I eliminated most errors, but reduced it down to a list of items. Also starting to suppress items that are known not to be ItemStack-able so the list is greatly reduced. Still need to work on suppressing others too. + + + +* **Bug fixes: With spigot/paper 1.21.1 and the NBT lib that we are using, there were issue that were suddenly occurring that worked fine before.** +Basically, eliminated a lot of generation of stack traces, especially when dealing with NBTs. +Upgraded NBT-lib to v2.13.2 from v2.13.1. +When formatting the rank list, the defaults were set to a value of zero. But if there are no tags on any ranks within a ladder, then the width was being used with a value of zero. This was causing a failure since it cannot left-position anything with a zero width. It was trying to format '%-0s'. With a default of 1, it would always use 1 as the minimum value, which works perfectly fine. + + +* **Fixed a potential problem with null ranks being loaded within the ladder loaders.** +I cannot find a reason why this was happening, or what data was triggering it, but this fixed the issue by skipping null ranks. + + +* **New Feature: Support for Bukkit's EntityExplodeEvent which is what the ExcellentEnchantments plugin uses.** +owo + +* **Mine bombs: A lot of various changes and fixes to get them to work better.** +This new animation and mine bombs code needs more refinement and adjustments, but it's working far better than what it was. + + +* **Placeholders: Sellall multiplier: Fixed a few issues related to being offline and even OP'd.** +When offline, it was not able to get an active player object so it was bypassing the sellall multiplier calculations.** +Now it can work with bukkit's offline players. And its also able to fallback to using snapshot perms so the sellall calculations at least reflects what it was the last time the player was online. + + +* **Upgrade XSeries to v11.2.1 from v11.2.0.1. ** +This may help with a few issues with spigot v1.21.1 blocks. + + + +* **Sellall multipliers: Fixes some of the problems with sellall multipliers so they can work better when the player is offline.** +This will now use the snapshot of the player's perms as they were when they were last online. This helps to ensure better accuracy when bukkit will not provide perms when the player is not online. + + +* **Ranks player: Added the capture and storage of the player's rank multiplier and changed the command '/ranks player' display these stored values for the multipliers when the player is offline.** + + + +* **PrisonEnchants update: Updated support for Pulsi's PrisonEnchants plugin.** +The structure of the API changed with v2.0. Another change happened with v2.2.1. +Prison now supports all versions from v1.0.0, v2.x, and v2.2.1 and newer. +Created a pseudo API class in the prison-misc project to be able to compile for all three versions of support. + + +* **Gradle: Modified the gradle configs to "force" it to compile with java 1.8, which is what it needs to be for it to work with spigot 1.8 through 1.15 or so.** + + +* **AutoFeatures: Add support for using RevEnchant's fortune enchantment level using NBT data.** +Not 100% this works because I cannot test it since I do not own the RevEnchants plugin. + + + +* **BlockBreak: RevEnchants was firing one of their multi-block break events with NO blocks include. ** +Had to handle a null condition and cancel the event. + + +* **Prison backpacks: On the last commit for setting up the integrations for backpacks, I overlooked an issue when prison backpacks were disabled.** +This issue was fixed. It was causing a failure on startup which prevented prison from loading due to causing the integration manager to fail. + + +* **Sellall: Enchantments: Prevent items with enchantments from being sold.** +Unlike lore, there is no way to bypass this. Sellall cannot sell anything that is enchanted. +There was an issue that would "sell" enchanted items, but would not remove them from the inventory unless the player was holding it in their hands, which would allow the item to be sold multiple times. + + +* **Integrations: Backpacks and prison versions reporting of integrations.** +Fixed an issue with backpacks not being included in the sellall activity when they are enabled in the sellall settings. +Added BACKPACKs to the IntegrationType and made changes to include the listings of all backpacks and their status in the startup information and prison versions. + + + +* **Economy: CoinsEngine: fixed a problem with using the wrong plugin signature.** +This now works as expected. This was tested with gemsEconommy such that some currencies from both were actively being used. + + +* **Placeholders: Fixed a bug when the player is at the last possible rank on both the default and prestiges ladder.** +The fact that there isn't a next rank was causing problem when trying to get the next ranks ladder base multiplier, which does not exist. + + +* **Debugging info: Expanded the debugging info for the smelting and blocking to show the progressions.** +This is important for tracking and understanding how and if they are working. +Changed some of the coloring so it's easier to read and for various headers to standout. + + +* **Bug Fix: BlockBreakEvent ACCESS Priority. This event was not being handled in the correct place, so other fast-fail checks were intercepting this ACCESS check.** +This now has three different results.... If outside of a mine, it will fail and cancel the event. If in a mine and the player does not have access, then it will cancel the event. +If its in a mine and the player has access, then it will let the other events handle the event without it being canceled. + + +* **TheNewEconomy support: I had a wrong method signature for one of the mock functions. This should correct it.** +The jar was regenerated for java 1.8. + + +* **Mine Bombs: Updated text on the mine bomb list help details.** + + + +* **PrisonJarReporter: Update support for java 22.** + + + +* **Update the TNE API jar: TheNewEconomy_prisonBuild_v0.1.3.0.jar It was accidentally built with Java 21 instead of Java 1.8.** + + +* **Bug fix: When using a file filter, handle the condition of the result being null.** + + +* **Add support for new economy: The New Economy: Created dummy stubs to allow prison to build the new classes for the integration.** +Cannot use maven because those jars are built with Java 17 when prison can only be built with java 1.8. + + +* **Mind bombs: Minor updates to the BombAnimations class to realign a few of the settings. ** + + +* **Mine bombs: Various updates to the general mine bomb defaults to include more of the newer features.** + + +* **XSeries: Upgrade XSeries to v11.2.0.1 from v11.2.0.** + + +* **Mine Bomb: Setup a simplified constructor for animations which will not use an item.** +The purpose would be for showing only the holographic name, which is needed for animations that are actually moving the armor stand. + + +* **Mine bombs: Hooked up the animationSpeed mine bomb setting to the bounce, infinity, and orbital animations.** +Since bounce and infinity are radians based, the speed is divided by 16 to help slow it down, otherwise it would be way too fast. +Normally, for these two animations, it was using an internal speed of 0.35, so now a comparable speed can be achieved with a value of 5.6. The other animations appear to be more ideal with an animation speed around 5.0, so this is a good common ratio to use. + + +* **Mine bombs: Update the '/prison utils bomb list' command to include more of the mine bomb's features and options. ** +Added support to show the available Mine Bomb's animation patterns. + + +* **Mine Bombs: More adjustments to the animation objects.** +Mostly cleaning them up. + + +* **Mine Bombs: removed nbt info that was being passed into the creation of an ArmorStand.** +This never did work correctly since it was set on the bukkit object, which was not visible when wrapped with a prison object. + + +* **Mine Bombs: update the orbital animation to fix a few issues.** + + + +* **Mine Bombs: Added a first none animation to the animation pattern so the holograph remains in the same spot.** +Otherwise it would move with the first moving armorstand. +Orbital, orbital8, and starburst move armorstands so this allows the name to remain stationary. + + +* **Mine Bombs: Added the setup for starburst animations.** + + + +* **Mine Bombs: added two new AnimationPatterns: orbital8 and starburst.** + + +* **Mine Bombs: Add new settings for animationOffset and animationSpeed.** +Animation speed controls how much the animation angles change by adding this value to the prior value. +Smaller is slower, and larger is faster. +Animation offset is used on animations that move the actual armor stands, such as orbital, orbital8, and starburst. +If offset is zero, then it will result in a round orbit. If it non-zero, then it will rotate around a point outside of the original location. Multiple ArmorStand animations, like orbital8 and starburst, will offset each placed armorstand around the main Location, therefore creating interesting geometric patterns. + + +* **Mine bombs: Added support for "small" armorstands.** + + +* **Location and Vector: Enhance the toString() functions so they can be used in debugging and unit tests.** + + + +* **Mine bombs: Geometric: update descriptions and create unit tests to confirm if the function getPointsOnCircleXZ are producing the intended results.** + + + +* **Autofeatures: Use TokenEnchant fortune levels: Added support for the newer TE API "ITokenEnchant". "TokenEnchantAPI" is still supported.** + + + +* **Mine bombs: Hex color codes: Setup one mine bomb using hex color codes.** +Hex color support was added to minecraft with spigot v1.16. Older versions of spigot will not work. +No changes were needed to allow the hex support since prison was already handling support for hex colors. +This is triggered with a prefix of '&#' followed by the 6 hex digits, such as '&#a1b2c3'. +As a result, this simple hex color code will be translated by prison in to the code structure that spigot and paper will recognize: +'&#a1b2c3' is converted to: '&x&a&1&b&2&c&3' + + + +* **Oops... accidentally committed code that has been on the back burner for a long time. This resulted in a build failure.** +The code is going to take the `/prison support saveToFile help` output, which is HTML based, and auto generate a table of contents with a lot of cross referenced hyper links. +The intention is that if you load this document, you can quickly jump to any section of interest to help solve support issues. +This will be updated and completed in the near future... nearer now that I accidentally committed it. ;) LOL + + + +* **Mine Bombs config settings: updated some of the defaults and added a few new bombs to use the newer animations.** + + +* **Mine Bomb Animations: Added two new animations: bounce and orbital.** + + +* **Mine Bombs: Update to a lot of the core support for ItemStacks, World, Location, and ArmorStand.** +These enhancements are to help support moving mine bomb animations back to core. + + +* **Mine Bombs: Geometric shapes and functions.** + + +* **Prison command placeholders: Updated the new placeholders for "ifPerm:" and "ifNotPerm" are now working properly.** + + +* **Entity ArmorStands: ArmorStands are now able to spawn as invisible.** +Before this change you could see an armor stand appear for a fraction of a second before the invisibility kicked in. +Now armor stands are being spawned elsewhere, set to invisible, then teleported to the intended location. At the point of teleportation, they would be invisible. + + +* **Prison commands: Added support for new global placeholders: '{ifPerm:}' and '{ifNotPer:}'.** More adjustments. + + +* **Prison backups: updated some of the help text.** + + +* **Mine Bombs: cooldowns.** +Changed the cooldown handling by moving it to the mine bomb's core and created its own task to run to monitor it. +Fixed issue with the older version of cooldowns not working properly with throwing the mine bombs. + + +* **3.3.0-beta.18c Beta release - Please read!!** +I usually do not release beta versions because I do not want to expose anything risky +to any server. + +The reason why this is a beta release: There are changes to two different player file names that older releases of prison cannot correctly read or access. + + +The reason why this is a beta release: There are changes to two different player file names that older releases of prison cannot correctly read or access. + +**Since this is a beta release, use at your own risk.** +**Please backup your files**, although prison automatically updates all of prison's files when a new version is detected, and +before starting the new prison version. Those backups can be found in the `plugins/Prison/backups/` +folder. + +**Please wait and do not use this BETA release if you do not want to risk trying this beta, please wait until the next alpha is released, which will be in about a week or two.****Please wait and do not use this BETA release If you do not want to risk trying this beta, please wait until the next alpha is released, which will be in about a week or two.** + +The reason why this is a beta version, is because the file name format for RankPlayer files and the player cache files have changed. Everything is working great, but the catch is that +this is the first time with prison that you cannot easily rollback to an older version. It's possible, but you have to manually copy or rename files. + +The file names have been changed so the player's name is now part of the file name so its easier to identify which file belongs to each player. This also makes Prison more compatible with bedrock platforms. + +Prison is using an intelligent method to identify what the file name is, and it's able to use either the new format, or the old. Prison also automatically updates the file name to the newer format when the file is saved again. + +This release has been tested for about a week plus on my test servers, and it's proving to be very stable. But I would like to see a few more users to confirm there isn't an odd combination of settings that are causing issues. If you encounter any issues, please ping me on discord. You can even DM me directly. + + + +* **Prison commands: Added two new command placeholders that are globally available to allow control of commands based upon player perms.** +The new placeholders are '{ifPerm:}' and '{ifNotPerm:}' and this will control the execution of all commands that follows those placeholders. + + +* **Disabled the system settings component.** It posed too much risk for something to go wrong, especially if the config file that it was using was eliminated. Now the server is able to more intelligently deal with file names, and how to auto upgrade them. This makes it easier on the server, and it helps transition over to the new format for the file names. + + +* **RankPlayer files: minor change to how the permission snap shots are handled to fix a problem where it was not working correctly.** +When a player was online, it would properly populate the permsSnapShot array with the player's current perm list. But when they logged off, then it would be cleared. +This fix ensures that the perms updated and saved, so they can be properly loaded when they are not online. + + +* **Rankup: removed unused code to eliminate a compile warning.** +This is a trivial change that has no impact. + + + +* **Rankup messages: externalized another message related to an economy failure.*** + + +* **Mine bombs: Update and fix some issues with the new mine bomb processing and animations.** + + +* **Prison NBT: removed debug code which was generating a lot of entries in the logs.** + + +* **Mine bombs: Setup throwing of mine bombs.** +The mine bombs can now be thrown. If they don't land within the mine, then they are not removed from the player's inventory. +The check for the mine is performed where the block lands. The throwing velocity can be controlled in the settings of each mine bomb; the higher the value, the farther the player can throw the bomb, which can easily be outside of the mine. + + +* **Mine bomb defaults: Added a couple of new sample mine bombs to illustrate the new animation sequences.** +Changed the text on the bombs' tags and lore to include a `%r` at the end; a reset character. This helps to prevent bleed over when dumping the raw values to the console and logs. + + +* **Ranks: Fixed some issues with the newer formatting of the player files.** +Had an issue with using a rank name for a ladder name, which resulted in player's ranks from getting reset since the player had zero ranks due to incorrect mappings to ladders. + + +* **Mine bombs: throwing. Setup the first pass with throwing mine bombs.** +This is not fully functioning yet, but it's getting closer. + + + +* **Mine bomb findArmorStands: More work to provide more features and to work around issues with NBT data not working correctly with entities.** + + + +* **Mine bombs: Fix issue with the printing of the error message with the included json data since it contains non-encoded % signs. Setup regex comments on them by using: `\Q` and `\E`.** + + +* **Mine bombs: More work on getting the new mine bombs functional and working better. +Still not perfect and fully working yet, but getting there.** + + + +* **Rankup: removed dead code.** + + +* **NBT library: Some adjustments to make the code more "correct".** +This does not work with entities, since you can write a value to the entity, but you cannot read it. +ItemStacks do work fine. + + +* **Mine bomb animations: Throw velocity.** +Added support for throw velocity by providing a low and high range, which will randomly select a value between those points. This provides for a variation in throw speed to keep it challenging. + + +* **Mine Bomb Animations: More changes to fix more issues with the mine bombs in general, and the animations.** +These major changes has broke many things, so they are being hooked up little by little as each part is tested. + + +* **RankPlayer: Updated how some classes uses the RankPlayer object**, and how it gets it, to help improve the code by simplifying it, and helping to ensure it's accurate. +Also updated some of the comments in the PlayerManager. + + +* **Player Cache: Adjustments to improve access to the RankPlayer object.** + + +* **Mine Bombs: Refactoring how mine bombs are handled when placed.** Had to shift a lot of the variable types over to more of the prison flavors to allow for better support of the newer functions. +This is setting up support for throwing mine bombs. + + +* **More work on the findArmorStands function.** +Fixed an issue with getting the entities within an area too. Found that was not working correctly. + + +* **Spigot compatibility: Expanded some of the compatibility functions so that some other mine bomb code can be simplified.** + + +* **Mines: Converted a mine cache lookup from using longs which were a fragment of the player's uuid, to using their whole uuid. ** +This change was made to ensure that bedrock players won't have problems. + + +* **Mine Bombs: Added NBT ids to all mine bomb armor stands so they can be identified as being part of the mine bombs processes.** +Added this support to the `/prison utils bomb findArmorStand` command so it applies to only mine bomb used ones. + + +* **AutoFeatures: Added new blocking capabilities: raw to raw blocks.** +raw_gold => raw_gold_block, raw_iron => raw_iron_block, and raw_copper => raw_copper_block. + + +* **Entity clean up: Small changes that missed the last commit related to the addition of the Entity and mine bomb animations.** + + +* **Prison API: I noticed that an API class had an PrisonItemStack qualifying the class?**] +I have no idea what happened here, or why it even was added. All I can think of is that it was a stray paste or something. +This was removed. + + +* **Prison Bomb Animations: Initial setup and switch over to use the new prison bomb animations. Non-functional.** +This state of development has the animations working, but the bomb's actual explosions are not yet enabled, so this commit is non-functional. It's being committed due to the number of classes changed and for how much is working well too. +The animations were pushed back to core so that way it's not more code that is being crammed within the spigot module, which was originally intended to be a light weight layer sitting between the actual prison code, and the platform. +The animations are designed so that there can be a number of variations created, and then they would be available to use with the mine bomb configs. + + +* **Updated XSeries to v11.2.0 from v11.1.0.** +* **Update Papi to v2.11.6 from v2.11.5.** + + +* **Prison semantic version: Moved the code of prison's semantic version tools to the prison-core module.** +This was needed to be used within the core, so it's movement and the elimination of dependencies on spiget was beneficial. + + +* **Sellall: when sellall message delay is enabled for autosell, changed it to when the player does `/sellall sell` it reports the sale for that transaction instead of waiting until 15 to 20 seconds later.** + + + +* **Refactor JsonFileIO to push more of the non-json content to FileIO where it really should be located.** + + +* **RankPlayer: Added new fields to expand what is being stored in the RankPlayer object to store data that is not available when the player is offline.** +This can provide additional support for players when they are offline. + + +* **Mine Bombs: New feature to remove stray amour stands.** +`/prison utils bomb findAmourStands help` +This lists all amour stands in a given radius and you have the option to remove them. +Early on, mine bombs use of amour stands could glitch and not be removed. +This command can identify them, and remove them. +This command should be used with caution since you could also remove holographic displays too, and if you do, you may not be able to regenerate them too easily, so use with caution. + + +* **Mine bombs: potential bug fix. If a mine bomb is null, this was causing problems. This now properly handles null mine bombs.** + + +* **Player info fix: When creating the new entity support, there were times when the names were being lost and as such this code was failing because the name was null.** +Normally it never will be null, so I cannot really call this a bug. But this fixes the issue if it happens again in the future. If a name is null, it now will properly support it. + + +* **Prison Entity support added!** +This is a major change to prison. Support for bukkit Entities has been added, which had to be worked in between the SpigotCommandSender and the players. +This is a significant change since it does allow more complex support for other features, such as newer and enhanced support for mine bomb animations, which uses armour stands, which are entities. +This will allow the animations to be moved to the core and be associated with the mine bomb package. + + +* **File saves for players with the ranks and player cache: reworked how the files saves will work and how they will process the files.** +Before I had them setup to be "enabled" by a command that they admin would run. But there were some problems with that. +One thing that happened on my test server was that the save file that kept the config status disappeared and as such, there was some conflicts with which file was actually being used. +As a result, some of the settings got screwed up for a couple of players. +The solution was to change how files are read... basically it checks to see if either the new format is being used, and if not, then checks for the old format, and if not, then it uses the new file. If the old file is used, then it's renamed. +When checking for these files preexisting, it does as such with filtering all files to find files with the given prefix. Therefore, it finds the correct file even if the player's name has been changed. +This appears to be working very well at this point. +NOTE: There are other commits that need to happen, and will follow this one, that will allow everything to compile successfully. This commit may not e able to be compiled. + + +* **Mine Bombs: Finalizing the validation and hooking in the new AnimationPatterns.** +Next is to work on adding new animation patterns. + + +* **Prison platform: Added a setPlatform function so this can be used for unit testing.** The test fixture is the TestPlatform object that is not connect to any spigot runtime. + + +* **Json File IO: Changed how errors are reported.** Since the exception message may be null, provided a check and an alternative message instead of just passing a null value to the string formatting parameter. +The JSON data can be huge, so only printing the first 500 characters. + + +* **Mine Bombs: Setup reporting on when validation of bomb effects fail. ** It's not an error as much as that version of the effect is not supported by the active spigot/paper version the server is running. It's a runtime check. +**Added unit tests for the conversion of mine bombs to JSON and back to the mine bomb config objects.** **Added units for cloning** that are similar in how it validates what has been cloned and restored from json. + + +* **Mine Bombs: Added support for an AnimationPattern for the mine bombs.** +This Animation pattern will control the animation sequence as the bomb is ticking down. + + +* **Mine bombs: Setup a better system to validate mine bombs when creating the defaults and when loading from the save file.** +Now if a mine bomb effect is not valid for that version of bukkit/spigot, it will not be included in the mine bomb so this will eliminate the startup error messages. + + + +* **sellall multiplier add to many ranks: new feature to add (replace) a rank multiplier and have it apply that value to all higher ranks until the end of the ladder or until it hits another rank with a multiplier.** +So if you have p10 and p20 setup and want to fill in p11 through p19, you can use this command by reading p10 with this new option and it will apply the multiplier through p19. + + +* **ranks ladder moveRank: Added the ability to remove a rank from a ladder.** +This was not possible before, but yet prison would temporarily disconnect a rank from a ladder before assigning it to another ladder. +It should be noted that ranks should always be tied to a ladder, so this is mostly used for testing purposes. + + +** v3.3.0-alpha.18b 2024-06-23** + + +* **Prison nbtApi: Found an issue when a newer version of spigot broke the functionality of the nbtApi library, it was causing failures in prison.** +Made changes to prevent an nbt failure from causing prison to fail. Provided new controls to log a simple error message, but still enable the rest of the prison's functions to work. +The under laying problem was with a 3rd party library and not prison. But this fix allows prison to better handle when future of versions of spigot may break things again. + + +* **Upgraded nbtApi to v2.13.1 from v2.12.4.** +This better supports spigot 1.21.x. + + +* **Auto and manual smelting: List all possible smelting conditions.** +Should provide a similar list for blocking. This list shows what manual settings will effect the actual blocks, since one setting can control multiple blocks. + + +* **Rankup and Presetige: Fixed a bug where when prestiging for the first time that it was taking the cost of the default ladder's first rank (generally zero value).** +This now uses the correct ladder based upon which ladder is being targeted for the rankup or prestige. + + +* **Block break of unknown block type: Handle a condition of when a target block is not a known.*** Cancels the event. + + +* **XMaterial bug fix. If a newer version of spigot is being use that XSeries does not support**, there is a chance an error could happen if a newer block type is added to the sellall shop list, or some other need tries to access all block types on the server. +This prevents a parse error within XMaterial from shutting down prison's ability to process all of the blocks. This should have been a very rare condition, but now it's guarded against cause problems. + + +* **Upgrade XSeries to v11.1.0 to support spigot v1.21.0.** +XSeries v11.x no longer directly supports the matching to spigot 1.8 resources by the use of id and data byte. So added the support directly to the prison compatibility class for spigot 1.8 so prison can continue to use XSeries with spigot 1.8 without any issues. + + +* **New feature: AutoFeatures: Smelt and Blocking: New option to include the player's current inventory when performing a smelting and/or blocking.** +The way this works, is that before "trying" to smelt or block an item in the drops list for the player, that it removes that same item from the player's inventory, and adds them to the player's drops. +This ensures that the inventory gets smelted or blocked, and any leftovers are then returned to the inventory. +These new features default to false, which off, so as the older behavior is honored and this will not break any existing servers. + + +* **Prison support troubleshoot sellallmines: This new commmand will review all blocks used in all mines, and show a report based upon each block to identify if it is setup in the sellall shop.** +This is a good way to identify if all blocks that are used have an entry within sellall. +Note that this only reviews the blocks, but not their possible drops, which may differ. + + +* **Prison support troubleshoot autosell: Added a new feature to help identify why autosell may not be working.** +This new command also provides a lot more information about what the individual features do, and how they work. +It also provides additional information on features related to sellall that the users may not understand or are aware of, +these features may help provide understanding on how to fix issues they may have with other plugins. + + +* **Rankups: Change how rankups are working by default. They no longer require perms, but within the 'plugis/Prison/config.yml' they can be enabled.** +The reason for this change is due to the fact that a lot of people have been saying that perms are suddenly forcing a perm check, which has been failing. +So although this is a change that may break a few servers which do not want players to be able to control their own rankup or prestige, this is a fix that will make it easier for many others. + +```yaml +ranks: + rankup-bypass-perm-check: true +prestige: + prestige-bypass-perm-check: true +``` + + + +* **Spigot utils: saw a rare situation where a NPE happened when prison had custom blocks setup, but the plugin was removed.** +This prevents a NPE if the backing 3rd plugin goes away. + + + +* **Mine reset notifications: Forgot to add support for 'server' notification mode.** + + +* **Mine notifications: Added support for world and server modes.** + + + +* **Friendly player files: Slight adjustments. Added two report features so list both old and new file names for all players, for either player or cache files.** + + +* **New feature: Reloadable ranks and ladders.** + + +* **Block utils: Unbreakable blocks breaking.** There was an issue with the unbreakable blocks not identifying a collection with a Location for a key. Changed the key to a String using the world-coordinates and it fixed the issue. + + +* **Friendly player files: changes to get everything working.** +The command is able to convert player files, and to update the active player cache. +The players do not need to be reloaded, since the system will automatically use the newer file format once the conversion is ran. +The checks for which file format should be used is based upon the config.yml setting and if the conversion was ran. +Update some notes on the `/ranks reload players`. + + +* **New feature: Reloadable players.** +Players can now be reloaded with the command: `/ranks reload players` or the alias '/prison reload players' +If a player's RankPlayer file, as found in `plugins/Prison/data_storage/ranksDB/players/players_*.json', is modified manually, or replaced with a backup copy, then this command will reload all players for the server. +When this command is issued, prison will attempt to save all changed player files and remove them from the rank's PlayerManager. Once all players have been removed, the process of reloading them will begin. +There is a chance there could be a currently running process that is using the older copy of the player's RankPlayer obect/file. This will not terminate any process, or swap usage of an object in mid-stream. +All risks of using this new feature are placed on the individual using this command since it is unknown how some operations and tasks may respond. That said, this really should have minimal to no impact. +This feature should not be used frequently; it should only be used on the rare occasion. If this is used frequently, then perhaps there is a larger over arching issue that needs to be addressed. + + +* **RankPlayer files and PlayerCache files:** Update to how prison is managing these files, and how it's tracking more of the data that is added to the RankPlayer so that way the TopN process will not have to access the player cache. +RankPlayer file changes will increase the frequency of updates on this file. Used to be primarily when there would be a rank change but now it's tracking more information which will be updated when the player cache is saved or unloaded. + + +* **Player file name update: The file names used for the rank players and the player cache are being updated.** +These files have the player's name as part of them, but the big change is that the new format now is supporting bedrock players. +The bedrock player UUIDs are all zeros at the beginning of the UUID, so it was leading to possible issues when there were more than one bedrock player due to the cache trying to load the wrong file. +The transition to the new file format will not be forced yet. The old format will continue to be used until a major release is made in the future. +The new format can be enabled through the config.yml file. There is also a new task and command under '/prison support updates playerFilenameUpdate`. +The prison system is now able to track and store different events and settings in a new 'pluigins/Prison/backups/prison-system-settings.json' file. This will track the usage of the player name update. + + +* **Docs: Fixed a typo.** + + +**v3.3.0-alpha.18a 2024-05-21** +Releasing this alpha.18a because the fix of the of the new player bug was crippling servers. + + +* **Bug Fix: When a new player was joining prison, and there were placeholders being used in the rank commands for either the default ladder, or the first rank, the resolution of the placeholders was triggering a new player on-join processing within prison.** +This happed because the new RankPlayer object was not being added to the PlayerManager before ranking the player... now the player's object will be there when the rank commands are processed. +Honestly have no idea why this has not been an issue in the past.... + + +* **Docs... added curseForge.com to the list of locations where prison can be downloaded from.** + + + +* **Fix to the docs... for some reason, eclispse, or one of it's plugins failed and corrupted the markdown.** +I did not realize it was corrupted since it was still showing the correct content, but when restarting the IDE and loading the files, they were missing the first characters. + + +**Prison v3.3.0-alpha.18 2024-05-20** + +This version has been tested and confirmed to be working with Spigot v1.20.6 and Paper v1.20.6. + + + +* **Player Ranks GUI: Fixed an issue with the code not using the correct defaults for NoRankAccess when no value is provided in the configs.** + + +* **Obsolete blocks: Marked an enum as @Deprecated to suppress a compile warning.** This has not real impact on anything. + + +* **Gradle updates:** +Upgraded XSeries from v9.10.0 to v10.0.0 +Upgraded nbtApi from v2.12.2 to v2.12.4 +Upgraded luckperms-v5 from v5.0 to v5.4 + + +* **Economy: Added a feature to check if a player has an economy account.** +Currently this is not being used outside of the economy integrations, but it can be used to help suppress initial startup messages where players do not have an account, which will help prevent flooding a lot of messages to the console for some servers. + + +* **Player Cache: There was a report of a concurrent modification exception.** +This is very rare and generally should not happen. +The keySet is part of the original TreeMap collection, so the fix here is to take all keys and put them in a new collection so they are then disconnected from the original TreeSet. +This will prevent a concurrent modification exception if there is an action to add or remove users from the user cache, since the user cache remains active and cannot be locked with a synchronization for any amount of time, other than then smallest possible. +The standard solution with dealing with this TreeSet collection would be to synchronize the whole activity of saving the dirty elements of the player cache. Unfortunately, that will cause blocking transactions when player events try to access the player cache. Therefore it's a balance game of trying to protect the player cache with the minimal amount of synchronizations, but allow the least amount of I/O blocking for all other processes that are trying to use it. +Hopefully this is sufficient to allow it all to work without conflict, and to be able to provide enough protection. + + +* **Gradle: Removed a lot of the older commented out settings.** +See prior commits to better understand how things were setup before, or for references. + + +* **Gradle: A few more adjustments to add a few more items to the libs.versions.toml.** + + + +* **Placeholders: The placeholder api call from PlaceholderAPI is passing a null OfflinePlayer object.** +Not sure why this has never been an issue before, but added support for null OfflnePlayers. + + + +* **Spiget: Updated the way prison handles spiget by now submitting a task with a 5 second delay.** +The messages are more helpful now. +This also moves it out of the SpigotPrison class. + + +* **Upgraded John Rengelman's shadow, a gradle plugin, from v6.1.0 to v8.1.1** + + + +* **Upgrade gradle from v7.6.4 to v8.7** + Upgraded from: v7.6.4 -> v8.0 -> v8.0.2 -> v8.1 -> v8.1.1 + -> v8.2 -> v8.3 -> v8.4 -> v8.5 -> v8.6 -> v8.7 + v8.3 required a configuration change due to `org.gradle.api.plugins.BasePluginConvention` type has been deprecated and will be removed in gradle v9.x. This is impacting the use of the `build.gradle`'s `archivesBaseNamme`. This is being replaced by the new `base{}` configuration block. + v8.3 also required other config changes. + + + +* **Upgrade spiget from v1.4.2 to v1.4.6** + Was using a jar with v1.4.2 due to their repo going down frequently. + Switched back to pulling through maven and got rid of jar. + + +* **Upgrade gradle from v7.3.3 to v7.6.4** + Upgraded from: v7.3.3 -> v7.4 -> v7.4.1 -> v7.4.2 + -> v7.5 -> v7.5.1 -> v7.6 -> v7.6.1 -> v7.6.2 -> v7.6.3 -> v7.6.4 + Preparing for Gradle v8.x + Around v7.5.1 required a change to auto provisioning + + +**v3.3.0-alpha.17a 2024-04-29** + + +* **GUI settings: Update them to remove unused stuff.** + + +* **GUI Tools messages: refined the messages and hooked them up.** + + +* **Initial setup of the GUI tools messages that are at the bottom of a page.** +Setup the handling of the messages and added the messages to all of the language files. +Support for prior, current, and next page. Also c +* **Update the plugin.yml and removed the permissions configs since they were generating errors (lack of a schema) and the perms and handled through the prison command handler.** + + + +* **CustomItems: Fixed an issue when CustomItems is a plugin on the server, but the plugin fails to load.** +Therefore the problem was fixed to allow a failed CustomItems loading to bypass being setup and loaded for prison. +`CustomItems.isEnabled()` must exist and return a value of true before the integration is enabled. + + +* **XSeries XMaterials: Update to XSeries v9.10.0 from v9.9.0.** +Had issues with case sensitivity when using `valueOf()`, which was changed to `matchXMaterial().orElse(null)` which resolves a few issues. +XMaterials v9.10.0 sets up support for spigot 1.20.5. There may be more changes as spigot stabilizes. +The issue with using `valueOf("green_wool")` would not find any matches since the enum case must match the string value exactly. So `valueOf("GREEN_WOOL")` would have worked. This was fixed to help eliminate possible issues with configuring the server. + + +* **Auto features: normal drop processing: Added a new feature to check inventory for being full, and if it is, then display the messages.** + + + +* **Auto features: Inventory full chat notification: bug fix. This fixes using the wrong player object.** +It now use prison's player object so the color codes are properly translated. + + +* **Placeholders: bug fix: When using a search from the console which included a player name, it was generating an invalid cast to a SpigotPlayer object when it wasn't related to that class due to the player being offline.** + + +* **GUI: ranks and mines: setup and enable a new default access block type that can be used if that rank or mine has not been specifically specified.** + + +* **GUI: tool bar's prior page and next page: Suppress the page buttons if there is only one page worth of gui content. ** + + +* **GUI: Player ranks: Fixed a bug where clicking on a rank in the player's gui was trying to run an empty command, which was generating an invalid command error.** +Ignores the command running if the command is either null or blank. + + + +* **Update to plugin.yml since some soft dependencies were missing.** + + +* **Economies: fixed the display of too many economy related messages, including eliminating logging of messages for offline players.** +The vault economy check for offline players, will now only show one informational message if a player is not setup in the economy. + + +* **GUI Player ranks: The setting for Options.Ranks.MaterialType.NoRankAccess was not hooked up properly so it was not really working.** +The config creation was wrong. Also fixed the code that was generating the gui. + + +* **RankPlayer and topn ranking: This may not have an impact overall, but for both the default and prestiges ladders, they are defaulting to a value of -1 when performing a comparison between players.** + + +* **Update privatebin-java-api to a newer release that now does a better job with a failure to use the correct protocol.** +It identifies what TLS version is being used, and if TLSv1.3 is missing, then it will indicate that the java version needs to be updated. +As a fallback, if the privatebin cannot be used, it is now using the older paste.helpch.at service. But if it does, the resulting documents are not purged and not encrypted. + + +* **Economy: EdPrison's economy. Added support for use of EdPrison's economy and custom currencies.** +This will allow prison to use EdPrison's economy does not also use another established economy that is accessible through vault, or multi-currency. + + + +
+ + + +## Current Change Log - Part 2: + +**[v3.3.0-alpha - Current - Part 2](changelog_v3.3.xb.md)** + +- **v3.3.0-alpha.17** 2024-04-20 and older + + + + +
+ + + +# Older change logs: + +## 3.3.0-alpha.7 2022-01-22* + +* **3.3.0-alpha.7 2022-01-22** + +A return to the v3.3.0 release track. The alpha.7 release represents a continuation of where we left off before. Once we got to alpha.6, it became apparent that it was critical to release before v3.3.0 was ready, so we returned to the v3.2.x track, including everything up to and including the v3.3.0-alpha.6. + + + + + + + + + + +# 3.2.11 2022-01-22 + + + +# v3.2.10 2021-08-22 + + + +# v3.2.9 2021-07-03 + +- release v3.2.9 + + +# v3.2.8.1 2021-06-18 + + +* **Note: Bug fixes for 3.2.8.** + +* **Fixed a failure on startup for new installations of prison.** +Basically it was unable to deploy the language files due to try-with-resources closing the initial zip connection. + + +# v3.2.8 2021-06-17 + +Prison V3.2.8 Release! +Prison now fully support Spigot 1.17 and Java 16! + + +**NOTE:** Since the start of the development on v3.3.0, Prison has had a few other releases under v3.2.7 and v3.2.8. The reason for these releases is that the major structures (and code) that would make prison v3.4.x, are not complete. Therefore, to get out new updates sooner than later, v3.2.7 and v3.2.8 have been release. + + +* **Released v3.2.8!** + + +* **v3.2.8-alpha.3 2021-06-16** + + +* **v3.2.8-alpha.2 2021-06-12** + +* **Spigot 1.17 release - v3.2.8-alpha.1 - 2021-06-11** +Only known issues: + * Unable to use nms to get the player's preferred language + +* **v3.2.8-alpha.1 2021-06-07** +Internally set the version, but will not release it until a few other things are finished. +The prison version is set to 3.2.8-alpha.1 to prepare for the release of prison that is compatible with Java 16 and Spigot 1.17. + + +NOTE: v3.2.8-alpha.1 is identical to v3.3.0-alpha.6. V3.3.0 is far from being ready to be released. So v3.2.8 will enable Java 16 and also Minecraft 1.17. + + +# v3.3.0-alpha.6 2021-06-07 + + +* **v3.3.0-alpha.6 2021-06-07** +Setting the version. The v3.3.0 release will be put on hold since focus will be to get v3.2.8 out which will support Java 16. It is unknown how many of the spigot 1.17 blocks will be initially supported. + +* **v3.3.0-alpha.5c - 2021-06-06** + +* **v3.3.0-alpha.5 2021-06-01** + +* **v3.3.0-alpha.4 2021-05-15** + + +* Next release will be v3.3.0-alpha.3 +Please note that the correct order of releases have been: +v3.2.6, v3.3.0-alpha.1, v3.3.0-alpha.2, v3.2.7, v3.3.0-alpha.3 + + +# v3.2.7 2021-05-02 + + +* **Set version to v3.2.7** + - Note that all changes that were made under v3.3.0-alpha.1 and v3.3.0-alpha.2 have been publicly released under v3.2.7 + + +* **3.3.0-alpha.2 2021-04-23** + + +* **v3.3.0-alpha.1 2021-04-16** + + +* **v3.3.0-alpha.0 2021-04-11** + + Start on the alpha.1 release. + diff --git a/docs/prison_changelog_v3.3.0_b.md b/docs/prison_changelog_v3.3.0_b.md new file mode 100644 index 000000000..3bad87b22 --- /dev/null +++ b/docs/prison_changelog_v3.3.0_b.md @@ -0,0 +1,2272 @@ + +# Note: This is part 2 to the current change log: + +## Prison Change Logs for v3.3.x + +** Current change log:** +- **[v3.3.0-alpha - Current](changelog_v3.3.x.md)** + + + +
+ + +## Current change log - Part 2: + + +### 3.3.0-alpha.17 2024-04-20 and older: + + + + +# 3.3.0-alpha.17 2024-04-20 + +**v3.3.0-alpha.17** 2024-04-20 + + + +* **Mines messages: Secondary placeholders. Added support for mines' messages to be able to support secondary placeholders within the language files. NOTE: Not usable at this time.** +But... this is basically useless. Within the mines language files, the vast majority of all messages are related to admin messages and are not viewable by the players. +Therefore the admin-only messages will not support the secondary placeholders since the players will never see them. +At this time, there are no messages that supports the use of these secondary placeholders, although the feature has been enabled for mines. +If a need is required, then please reach out and request such features should be enabled. At this time, effort and work will not be performed blindly upon items that will never be used, so if you see a need for this, I'd be happy to add them since you would have a need. + + + +* **Placeholder bug: The placeholder 'prison_rankup_cost_percent' uses the calculated value of a percentage, but when used with the placeholder attribute, it was found to use the price instead.** As such, the actual value returned for the placeholder was incorrect. + + +* **Player Manager: Secondary Placeholders: Setup the secondary placeholder support on the PlayerManager, but it has not been enabled yet** since secondary placeholders on placeholders do not make a lot of sense because each placeholder is only one value and they cannot contain alternative text. At least not yet. + + +* **Localizable: Secondary placeholders: Rewrote the whole support of secondary placeholders related to players.*** +Expanded the support by making them generic so other data sources can also have their own custom set of placeholders too. Such as mines. +This now supports a new interface that will provide the generic support. +Player's commands have been modified to pass a RankPlayer object, which supports the new interface. Non-player commands have not been converted since players will never see those messages (such as admin commands). + + +* **Added a comment in the ranks message files indicating that there is now some support for player based placeholders to farther customize messages.** +This also fixes an issue with the broadcast messages to use the intended player instead of the target player who is being sent the message. + + + +* **Localization: If admin adds extra parameters, or other parsing failures, happens on a message, the error will now be trapped and logged to the console without formatting.** + + + +* **Economy: For economies that prison supports that has a method to check if the player has an account, prison now tries to check if there is an account for the player before trying to use the economy.** +This could potentially prevent issues or run time failures. + + +* **Prison API: Added a few new functions to work with ItemStacks.** + + + +* **Players: Shift the function of getting a player object to the Player classes, such as CommandSender.** +This is to simplify the code and to put the functionality in one location. + + + +* **Sellall: New command: '/sellall items inspect'** +This new command will inspect what the player is holding, and dump the details so the admin can see exactly how an item/block is created, including lore and enchantments. +Eventually this information can be used to enhance the ability to sell and buy non-standard items by allowing the admins to filter on lore, enchantments, and/or NBTs. + + + +* **SpigotPlayer: Fixed a potential issue if trying to use getRankPlayer() if the ranks module is not enabled.** +Added a check to ensure it's active. +We have not seen any reports of issues related to this. + + + +* **Prison Player: Added a new sendMessage function using Lists of Strings. ** +Added a new function getPlatformPlayer() which gets a bukkit player object if the player is online. This will consolidate a lot of other duplicate code. + + +* **Mine Bombs: wrapped up the changes to enable the placement of a mine bomb when using the BlockPlaceEvent which is used when using a block for the bomb's item.** + + +* **Prison ItemStack: remove enchantments from the core ItemStack since prison cannot properly represent it in versions lower than 1.13.x**, plus it was wrong for all spigot versions greater than 1.12.x. +Added the proper enchantment functions to the SpigotItemStack object. + + +* **Initial setup of sellall lore filtering** +A little clean up. + + +**3.3.0-alpha.16c 2024-03-11** + + +* **PlaceholderAPI: Upgrade from v2.11.2 to v2.11.5** + + +* **XSeries: Upgrade from v9.8.0 to v9.9.0** + + +* **Mine bombs: add support for BlockPlacementEvent so if someone is using a Block they can use it as the mine bomb's item.** + + +* **Prison's NBT: Add support for using NBTs with bukkit's Block.** + + +* **Add support for getting the "hand" from the BlockPlaceEvent.** + + +* **Prison support listeners: added support for listening to and providing dumps for PlayerDropItemEvent, PlayerPickupItemEvent, and BlockPlaceEvent.** + + +* **Promote & Demote: Improved upon reporting issues with the command.** +There were few situations where the command would exit without reporting why, which was leading to difficulties with using the command effectively. + + +* **New feature: TopN customization now possible. The messages and placeholders that you can use are located in the core multi-language files.** +See the bottom of the files for instructions on usage. +TopN data is set to delay load so it does not lengthen the startup process. As such, it now reports that the data is being loaded so it is now clear why there are no entries in the list initially. + + +* **Mines: eliminate a field no longer used: includeInLayerCalculations.** +This was obsoleted with better use of logic. + + +* **Mine resets: Reworked how prison is selecting random blocks per layer, to properly include constraints.** +The addition of various new features in the past made a mess of the logic, so it's been cleaned up greatly so it now makes sense and should work properly now. +There is a slight risk, that as blocks are removed from a layer due to reaching it's max constraint value, that future random selections were missing blocks selections and was then inserting AIR. This fixed code now will insert a filler block which has been selected with no constraints, and the largest chance value. + + +* **mines block layerStats: rewrote to improve and get rid of the collection manipulations.** +Found potential problem with air being inserted in to mines. +Renamed a lot of uses of Location objects to include the name "location" in their variable names instead of "block". + + +* **Mines block layer: Added colors for same IDs so it's easier to read.** Added a check that sees what block actually exists. If counts of what should have spawned match whats in the mine for that layer, then it shows only one number. It shows two numbers if a block's intended spawn does not match what's in the mine. + + +* **Mine reset: added a force to the reset so it will ignore an existing mine reset and allow a new one to begin.*** +When a mine is being reset, there is no way to actually cancel it. So this allows a large mine to undergo multiple concurrent resets. Use at your own risk. + + + +* **Bug fix: the check for the time the reset has been going on was incorrect and was fixed.** +Also all the code for submitting the reset task was moved in to the mutext. Now, if the reset got hung up, this will properly terminate it and resubmit it. + + +* **File format: Eliminate the check for file types since there is only one.** +Currently there isn't a setting to specify what it should be. + + +* **Mines block layerStats: Added a new command that shows which blocks are in each layer in the mine.** +There are a lot of future enhancements that can be added to this command, such as checking the actual blocks to see if they are still there, or if there was a problem with the spawning of the blocks. + + +* **Block lists: Added the total chance percentage to be displayed with the blocks.** + + +* **File output technique: Changes to how the "replace" existing files works.** +If the file does not exist, then it opens it to create it, otherwise it truncates it. + + +* **Mine bombs: Ability to prevent a bomb's blocks from count towards the player's block totals.** + + +* **Sellall and autosell: Refinements were made to the handling of the sellall settings to better stabilize the use of the commands.** Setting status for the players were moved to the player objects and is now used in all of the related calculations so there is better stability and consistency. + + +* **Mines import: prevent the processing of an importing of a mine if there are problems with the mine's name, or locations.** + + +* **AutoSell: Bug fix: When autosell and sell on inventory is full was all turned off, it would still sell.** +This fixes some of the logic to simplify the code, and to fix those issues. + + +* **Mine skip reset messaging: Did not have it hooked up in the correct location, so the skip messages were not happening.** + + +* **Mine reset: Under heavy load when performing a mine import, there were seen occasionally errors with concurrent modification errors.** +Code was changed to minimize that possibility. + + +* **Sellall and GUI message failures: a number of messages that would indicate the player does not have access to that command were changed to remove the permission from the message.** +This was requested by a couple of admins because they did not want the players to see the internal workings that would otherwise control how the software would behave. + + + +* **Mine imports: Fix some minor issues to get this to work even better.** + + +* **Mine skip reset: If a mine is reset, send a message to players, but only if the message is defined and not empty: 'skip_reset_message='** + + + +* **Player sellall Multipliers: Fixed the ranks multiplier to include all ranks that are defined within the sellall multipliers.** +Added a new function that will gather and list all multipliers that go in to the calculation of the player's total multipliers, which includes the rank multipliers (the sellall multipliers) and also permission based multipliers. +This detailed list of the individual multipliers, is viewable for each player that is online with the command `/ranks player ` and reveals the actual details of how it's calculated. + + + +**3.3.0-alpha.16b 2024-02-24** + + +* **Import Mines: Added the ability to import mines from JetPrisonMines config files.** +`/mines import jetprisonmines help` + + +* **Prison Command Handler: using config.yml you can now change all of prison's root commands with 'prisonCommandHandler.command-roots'.** +Can now map 'prison', 'mines', 'ranks', 'gui', 'sellall' to all new command that you want. + + +* **File saving: alternative technique for saving files. Do not use!** +This is a more dangerous technique that could possibly result in lost configurations. This is being provided as a degraded service if the fail-safe technique is not working ideally on a degraded server. +This should never be used, unless directed by a prison support admin. + + + +* **Prison startup bug: There was an issue with the prison startup when there was an error and prison tried to log the error**, only to find that resources that were needed for logging were not yet loaded nor were their dependencies. This fixes some of the entanglements to allow the error messages to be properly logged. + + +* **Bug fix: GUI configuration: Found a problem that when configuring the gui initial settings, that there were problems when trying to access mines and ranks when they don't yet exist.** + + +* **Add prison debug option to filter on blockConstraints when regenerating the blocks within the mines.** + + +* **Bug fix: prison support submit: if the bukkit system cannot extract a file from the jar**, such as plugin.yml, this will prevent the failure of the command. This will allow the command to continue being processed, but may just skip the extraction. + + + +* **Placeholders: Top player rank was using the wrong ladder, which was incorrectly the prestiges rank and not the default rank.** +Correcting the rank fixed the problem. This only was an issue if the player did not have a prestige rank. + + + +* **Mines set resetTime: fix typo in the description where it shows '*all' instead of '*all*'.** + + +* **ranks ladder: applyRanksCostMultiplier command was changed to allow the value of 'true' to be used along with the value of 'apply'.** This helps to eliminate some confusion on how the command works. + + +* **Bug fix: Prison command handler. When players are de-op'd, and they do the commands such as `/ranks help` or `/mines help` it was incorrectly showing other sub commands they did not have access to.** +This now shows the correct sub commands that they have access to. + + +* **Placeholders: topn players - bug fix. If a player did not have a prestige rank, then it would cause a NPE when using the `prison_top_player_rank_prestiges_nnn_tp` placeholder.** +Just check to ensure its not null... if it is, then return an empty string. + + +* **Bug fix: Player manager startup: fixed a problem where all players were being updated** even though they did not have a name change. Only when name changes are detected are the files updated or when a new player is found. + + +* **Add debug statements to identify how each block was calculated during a mine reset.** + + +* **Bug fix: block constraints: fix an issue with the selection of lower limits.** + + +* **updated the help on the `/mines block constraint` to indicate that the layer count is originating from the top, not the bottom.** + + +* **alpha.16a - 2023-12-28** + NOTE: I just noticed that alpha.16a was never committed. So this is not the correct location of when it was set with the local builds. + + +* **Mines: Fixes an issue for when mines are disabled and they are being checked in other processes to see if they are active.** +If the instance of PrisonMines is null, then it will create a temp instance just to prevent an NPE. + + +* **Mines unit tests: Setup a new constructor for mines that is only to be used with unit tests which allows the mines to be created,** but it does not initialize them since such tasks and processes are not needed in the unit tests. +As a side effect, these two unit test run much faster since it's not trying to setup tasks. + + +* **Prison Block change: Add support for display name, which is optional.** +Setup sellall so it can use the display name now, so renamed items will not be mistaken for vanilla minecraft items. +More work needs to be done to hook up displayName to other features, such as sellall and add prison block to mines. + + +* **Bug fix: Fixed the command `/mines set accessPermission` where it was apply the given perm to all mines.** + Likewise, all mines parameter was failing to do anything. + + +* **NOTE: This alpha version "should" support spigot 20.0.4.** +After a few days, if no other issues surface pertaining to 20.0.4, or other related plugins, this will be released as a public release. + + +* **Fix issue with BlockEvent's SellAll when isAutoSellIfInventoryIsFullForBLOCKEVENTSPriority feature is enabled.** +This was not using the correct new functions that checks to see if a player can use autsell, or if they have it temporarily toggled off. This also checks to see if the player has the correct perms, if perms are enabled for the sellall event. + + +* **Breaking change in XSeries: GRASS has been changed to SHORT_GRASS for v20.0.4!** It's disappointing to say the least that after all of these damn years, XSeries screwed up and pushed a breaking change to their repo. They should have kept GRASS so they would have remained compatible will all past code and configs that had to refer to GRASS directly, but nope... they opted for causing problems. Very disappointing. +Setup a converter to automatically convert all GRASS to SHORT_GRASS as the mines are loaded. + + + +* **Upgrade XSeries from v9.7.0 to v9.8.0.** +* **Upgrade nbt-api from v2.12.0 to v2.12.2.** + + +* **config.yml - changed the default values for remapping aliases and restricting players from using commands.** +The default, which used `/mines tp` was actually causing conflict with normal usage. + + +* **AutoFeatures auto permissions: enable the ability to 'disable' the perms.** Any op'd player, if perms are enabled, will have these auto features enabled. There is no other way around this, since this is the correct behavior of OP'd players. + + +* **Mine resets: If a mine reset takes longer than 4 minutes, then that is probably a failure and the mine reset did not complete.** Therefore, reset the mine reset mutex and try again. This allows a "crashed" mine reset to auto fix itself if it can. The 4 minute wait time is LONG, but it will prevent a normal reset from being canceled and restarted in the middle of a restart. + + +* **Performance: Changed the defaults for the mine reset settings to help improve the performance on larger servers.** +The older settings would allow other commands to backup and it would appear as if there was lag happening, TPS would rarely drop below 20. This helps to keep performance a little more responsive. +The side effect is that there will need to be more "chunks" submitted which could possibly result in longer wall-time for mine resets. + + +* **Mine resets: If a suggested block is null, then set it to air. This was causing an NPE under some conditions.** + + +* **BlockEvents: Added the ability to update block events** +instead of deleting them and re-adding them. Follow directions when using '/mines blockevent update help', or whenever a block event listing is shown in game, you can now click on the commands to auto populate the block event update command... then just edit the needed changes and submit. + + +* **Upgrade XSeries to v9.7.0 from v9.4.0.** + + +* **Bug Fix: Mine resets and block constraints.** +This fixes a few issues with block constrains using min and max, along with exclude from top and bottom too. + + +* **Bug Fix: GUI ranks, mines, and prestiges were not using the default item name correctly.** It was using the template correctly, but was not translating the use of placeholders. Only name and tag are supported. +Mines: `{mineName}` and `{mineTag}` +Ranks and prestiges: `{rankName}` and `{rankTag}` + + +* **Mines: Added support for '*all*' for mine names for the following mine commands: resetDelay, resetThreshhold, notificationPerm, and accessPermission** + + +* **Localizable: Bug fix. Blanks were being removed by the use of trim() so the spaces were being ignored.** + + +**v3.3.0-alpha.16 2023-11-18** + +* Update change logs for v3.3.0-alpha.16 + + +* **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** + + + +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) + + + +--------------------------- + + + +**3.3.0-alpha.13 2022-08-25** + +Highlights of some of the changes included in this alpha.13 release. Please see the change logs for all details. + + +* Added a new tool: `mines tp list` which will show a player all of the mines they have access to. They can also click on a listed mine to generate the TP command. This command can also be ran from the console to inspect what players have access to. +* Fixed a recently introduced bug where if the server starts up, but someone has no ranks, it was not able to properly assign them their first default rank. It was leading to circular references. +* Fixed an issue with color codes not being translated correctly with placeholderAPI. +* Prison has a rank cost multiplier where ranks on different ladders can increase, or decrease, the cost of all ranks the player buys. So when they prestige, it makes ranks A-Z cost more each time. What's new is that now you can control which ladders these rank cost multipliers are applied to, such as not on prestiges, but only on default. +* Fixed calculations of the placeholder `prison_rank__player_cost_rankname`. It was not fully working with every possible rank on every possible ladder. Now it works correctly if trying to get the player's cost for even many prestige ranks out (it includes cals for all A-Z mines at multiple passes). +* Mine bombs: Changed to only allow mine bombs to be setoff withn mines the player has access to. Fixed an issue with color codes within the mine bomb's tags. +* Fixes issues with NBT, color codes with prison broadcast commands. +* Rewrote topN for better performance: `/topn`. Older players are archived within topN and can be queried: `/topn archive`. +* Update ladder details on a few commands. +* Update XSeries from v8.8.0 to v9.0.0 so prison now supports 1.19.x blocks. +* Bug fixes with first join events. Bug fix with a few guis. +* CMI update: If CMI is detected at startup, and delayed startup is not enabled, prison will go in a simple delayed startup mode to allow CMI a chance to enable it's economy through vault. This reduces the learning curve with CMI users. +* New feature: Prison will now make an auto backup of all files in it's directory when it detects a change in version. Can manually backup too. The backup stores temp files then removes them from the server, this helps keep the server clean. +* Update bstats: Gained control of the account and started to add useful custom reports to help zero in on what we need to help support. +* More work on block converts. Will be added in the next alpha releases. +* Bug fixes: mines gui fixes for virtual mines. Sellall bug fixes. Placeholders fixes. + + + + +* **Minor addition to bstats.** + + +* **Player Mine GUI had the wrong calculation for volume which also threw off blocks remaining and percent remaining.** +The calculation for volume was using the surface area and not the total number of blocks. + + +**v3.3.0-alpha.12L 2022-08-25** + + +* **Updates to the bstats....** + + +* **New placeholders: `prison_rank__linked_mine_tag_rankname` and alias `prison_r_lmt_rankname`.** +Similar to `prison_rank__linked_mine_rankname` but uses the mine's tag instead of the mine's name. + + +* **Mine TP list: use mine tags and clickable mines to teleport to them.** + + +* **Mines TP list. Added a new options to mines tp command to list all mines that the player actually has access to.** +Not finished with it... will add clickable links to them when in game. + + +* **There was an unused updated tool in prison. It's against my policy to auto update this plugin, which would need to be consented to anyway, but I feel that admins need to be in full control of updates and know what is included in the updates. There was identified a potential exploit called zip-slip-vulnerability that could hijack a server if malicious zip is extracted. Prison never used this tool, so it's been fully disabled with no intention of reenabling. It may be deleted in the near future.** + + +* **TopN bug fix: If a player was in an archived state, they were not being moved to active when they would login.** + + +* **If the player is holding the mine bomb in their off hand, then remove the inventory from their off hand.** + + +* **v3.3.0-alpha.12k** + + +* **Fixed an issue when starting the server an no ranks exist. Also fixes an issue when starting the server an a player has no rank.** +Was using a mix of really old code, and the latest code, which caused a conflict since neither was doing what it was really supposed to. + + +* **Added the custom bstats report for Prison Vault Plugins.** +This reports all plugins that have been integrated through Vault. This report does not impact any other plugins report. This is segmented by integration type. + + +* **Fixed bug when server starts up when no player ranks exist.** +It will now bypass the player validation until ranks have been configured. + + +* **v3.3.0-alpha.12j 2022-08-21** + + +* **Update bstats to remove old custom reports that are not wanted/needed anymore.** +Added 6 new placeholder reports that classifies placeholders ini various categories related to how they are used within prison. Any placeholder that appears in these lists, will not be included in the generic 4-category placeholder lists. +Added a few more simple pie charts to cover a lot of the details on ranks, ladders, and players. Simple is better so you can just glance at all of them, without having to drill down on each one. + + +* **v3.3.0-alpha.12i 2022-09-19** + + +* **TopN players - fixed an issue where topN was being processed before the offline players were validated and fixed.** +There was an issue with processing an invalid player that did not have a default rank. + + +* **v3.3.0-alpha.12h 2022-08-19** + + +* **Rankup costs: Minor clean up of existing code. Using the calculateTargetPlayerRank function within the RankPlayer object.** + + +* **PAPI Placeholders: Force color code translations on all resulting placeholders.** +There were a few issues where placeholder color codes were not being properly translated. This was not consistent with everyone. Not sure why it was working for most. +These changes are more in line with how chat handlers and MVdW placeholders works. + + +* **Ladder: apply rank cost multiplier to a ladder or not.** +This new feature enables you to disable all rank cost multipliers for a specific ladder. Normally that rank cost multiplier applies to all ladders, but now you can suppress it. It's for the whole ladder, and not on a per rank basis. + + +* **Fixed an issue with calculating the player's rank cost when they already on the presetiges ladder and calculating the higher prestige ranks.** +Appears as if this becomes an issue when at the last rank on the default ladder. + + +* **v3.3.0-alpha12g 2022-08-14** + + +* **Fxing of the calculations of the placeholder prison_rank__player_cost_rankname and related placeholders.** +The original implementation did not take in to consideration the prestige ranks in relation to the default rank. +The improvements in this calculation now generates a list of all ranks between the current rank and the target rank. So if a few prestige ranks out from the player's current prestige rank will result in calculating every rank in between including multiple passes through all default ranks. So if there are 26 default ranks, and the player is at rank A with no prestiges, then to calculate rank P4 would include the following ranks: +b --> z + p1 + a --> z + p2 + a --> z + p3 + a --> z + p4. +This results in a total of 107 ranks that must be collected, then the player's cost for each rank will have to be calculated. Then all of these must be added together to get the player's cost on rank P4. +This calculation has to be performed for each rank in it's entirety +Warning: this calculation on high prestige ranks will be a performance issue. If this becomes a problem on any particular server, then the only recommendation that can be provided is not to use any of the prison_rank__player_cost placeholders. + + +* **TopN : a few more adjustments to fix a few issues with duplicates and also with using values from within the topN to include in the report to help minimize the need to recalculate everything especially with archived entries.** + + +* **Mine bombs: Fixed an issue with the mine bomb names not always working with color codes.** +Honestly the wrong function was being used so how it even worked I don't know. lol + + +* **New topN functionality: far better performance, with regular updates.** +TopN now is a singleton and is self contained. When the singleton is instantiated, it then loads and setup the prisonTopN.json file on the first run. 30 seconds after the initial load, it then hits all players to load their balances in an async thread. +The command /ranks topn, or just /topn has new parameter: "archived". Any player who has not been online for more than 90 days will be marked as archived. The archived option will show just the archived players. +Setup new parameters within config.yml to control the topn behavior with the async task. + + +* **v3.3.0-alpha.12f 2022-08-08 ** (forgot to commit when made this version) + + +* **Mine Bombs: Only allow bombs to be placed when within a mine that the player has access to.** +This will help prevent wasted bombs. + + +* **Fixed an issue with nbt items not having a value for toString().** + + +* **Encode color codes for the prison utils broadcast command.** + + +* **Added an "invalid player name" message to the rankup commands.** +Also added missing messages to the zh_TW.properties file. + + +* **BlockEvents were changed to auto display the existing rows so it's easier for the end user to know which row to select.** +All they need to do is to enter the mine's name, then press enter to submit the command, and then the existing rows details will be shown. Then the user can select the row and complete the command. +Updated docs on block events. + + +* **BlockEvents were changed to auto display the existing rows so it's easier for the end user to know which row to select.** +All they need to do is to enter the mine's name, then press enter to submit the command, and then the existing rows details will be shown. Then the user can select the row and complete the command. + + +* **minor updates for disabled mine reset times. No functional changes were made.** + + +* **Fixed a potential NPE with giving the players overflow blocks, but not sure what the exact cause was, but looked like there was an issue with mapping to a spigot item stack.** + + + **CMI delayed startup: Added new feature to try to auto enable Prison's delayed startup if CMI is detected as an active plugin, and if the delayed startup is disabled within the config.yml.** +This is to help get more CMI users up and running without more effort, but yet still provide the ability to customize how it is triggered. +If CMI is active, there is NO WAY to disable a delayed startup check.* + +* **Added the the option for playerName to the `/rankup` command so the command can be scripted and ran from the console.** + + +* **There was another issue with using `/gui` related to no ladders being loaded.** +This fixes that problem, and it appears like the issue was caused by plugman messing things up. This does not "solve" the problem with ladders not being loaded, but prevents the NPE from happening. + + +* **There was an issue with `/prison reload gui` causing a NPE.** + + +* **Fixed the `/ranks topn` command (`/topn`) to sort the list of players before printing the list.** +The list was being set a server startup time, and if someone would rankup or prestige, it was not reflecting their new position. The list is also now sorted after each rankup. Sorting should be a low cost operation since the list used never is regenerated so the changes made during sorting is minimal at best. + + +* **Added the ability to control the prefix spaces on the unit names.** +NOTE: may need to enable the use of the `core_text__time_units_short` since the long units are not being used. May need to create another placeholder for short/long. It used to be short, so may need to use long with the new placeholder and convert the calcs to the short as the default. +This was requested by PassBL. + + +* **v3.3.0-alpha.12e** + + +* **Fixed issue rank null issues when showing ladder details.** + + +* **Prison backups: Fixed an issue with folders not existing when running the backups the first time.** + + +* **v3.3.0-alpha.12d 2022-07-25** + + +* **Added more information on ladder listing to show name, number of ranks, and rank cost multiplier.** + + +* **bStats update: Added a new bstats custom chart for auto features.** + + +* **Update some docs. Added docs for Prison Backups** +[Prison Backup Document](prison_docs_050_Prison_backups.md) + + +* **Upgrade XSeries from v8.8.0 to v9.0.0** + + +* **Fixed issue with prison version check triggering a backup upon startup.** +It was always bypassing the previous version check, so it was always creating another backup. + + +* **Update bstats by moving to its own class in its own package.** +Added 4 new custom charts to split the plugins in to 4 parts. + + +* **Fixed a few issues with the ranks gui where they were using the wrong message key (placeholder).** + + +* **Prison v3.3.0-alpha.12c** + + + +* **Prison bstats: setup 4 new bstats charts for prison. May change a few charts or add new ones in the near future.** +Got control over the prison bstats so can now add custom stats. + + +* **Prison backups: Created a Prison/backups/versions.log file which gets logs when a new prison version is detected on startup, which also performs a backup.** +All backups are also logged in the versions.log file too. + + +* **v3.3.0-alpha.12b** +- Added the fix for the placeholders. See next note. + + +* **Fixed an issue with placeholders not be properly evaluated; there were 3 sections and they were combined in to one so it would not bypass any.** + + +* **Possible bug fix with first join: it appears like it was inconsistant with running the rank commands. Fixed by rewriting how the first join event is handled.** + + + +* **Prison backups: Added new features where it is generating a stats file in the root of the zip file which contains all of the "prison support submit" items.** +This is just about ready, but lacking support for auto backups when prison versions change, or job submission to run auto backups at regular intervals. + + +* **Setup a prison backup command that will backup all files within the prison plugin folder.** +When finished, it will delete all temp files since they have been included in the backup. +The new command is `/prison support backup help`. + + +* **v3.3.0-alpha.12a** + + +* **Added a new set of intelligent placeholders: these show the tags for the default ladder and prestige ladder, for the "next" rank but are linked together.** +They only apply to the default ladder and the prestige ladders. The tags are only shown if the player has that rank, or if that will become their next rank. +These ONLY show the tags that will be appropriate when the next rank up. So if the can still rankup on the default ladder, then only the default rank shows the next ranks tag. If they are at the end of the default rank, then it will show the next rank on the prestiges ladder; if they do not have a rank there currently, then it will show the next prestige rank with the default rank showing the first rank on that ladder. + + +* **When the command handler starts up, it now logs the pluigin's root command and the command prefix which is used if there are duplicate commands found during bukkit command registration.** + + +* **Bug fix: Placeholders search was missing the assignment of the placeholderKey, which is what would like the search results on the raw placeholders, with the actual data that is tied back to the player.** +In otherwords, without the PlaceholderKey it was not possible to extract the player's data to be displayed within the command: /prison placeholders search. + + +* **Added constants for the default and prestiges ladder name so it does not have to be duplicated all over the place, which can lead to bugs with typos.** + + +* **Sellall bug fix: There wasn't a common point of refernce to check if sellall is enabled. Many locations were directly checking config.yml, but the new setting has been moved to the modules.yml file. ** +If config.yml has sellall enabled in there, it will be used as a secondary setting if the sellall setting in modules.yml is not defined or set to false. Eventually the config.yml setting will be removed. + + +* **Found that bStats was erroring out with the servers hitting the rate limit so this makes a few adjustments to try to get prison to work with bstats.** +Basically plugins that load last will be unable to report their stats since every single plugin that is using bstats submits on it's own, and therefore it quickly reaches the limits. + + +* **BlockConverters: More changes to block converters.** +Added defaults for auto blocking, and for auto features with support for *all* blocks. + + +* **Bug fix: mines gui was not able to handle virtual mines with the internal placeholders. +This bug fix was included with the deployment of alpha.12 to spigotmc.org. + + + +* **Pull Request from release.branch.v3.3.0-alpha.12 to Master - 2022-06-25** + + +This represents about six months of a lot of work with many bug fixes, performance improvements, and new features that have been introduced. The last two alphas were not pulled back to main, but they were released, This PR will preserve the released alpha as it has been published. + +Also, this helps to ensure that this work will not be lost in the event the bleeding branch is lost/removed. Hopefully it won't be, but a lot of work has gone in to it and it will be impossible to recreate the current state of the alpha release. + +This version, v3.3.0-alpha.12, has 300 commits and 323 changed files. The list of actual changes since v3.2.11 is substantial and the change log should be referenced. + +Highlights of some of the changes include (a sparse list): + +* new block model - full support for CustomItems custom blocks - updated XSeries which mean prison supports Spigot 1.19. +* major improvements to auto features - streamlined and new code - higher performance - many bugs eliminated - now supports drop canceling to make prison more compatible with other plugins +* better multi-language support - supports UTF-8 +* Improved rankup - rankup commands are now ran in batch and will not lag the server if players spam it +* rewrite of the async mine resets - next to impossible for mine resets to cause lag - Uses a new intelligence design that will throttle placing blocks as the server load increases, which makes it next to impossible for it to cause lag. +* Enhanced debugging tools - if a server owner is having issues, prison has more useful tools and logging to better identify where the issues are - new areas are not able to log details when in debug mode - debug mode now has a "count down timer" where if debug mode is 8enabled like /prison debug 10 then it will only allow 10 debug messages to print, then it will turn off debug mode automatically. This is very useful on very heavy servers when a lot of players are active... it prevents massive flooding of the console. +* Major rewrite of the placeholder code that identifies which placeholder raw text is tied to, so it can then retrieve and process the data. - Pre-cache that provides mapping to raw text, so once it is mapped, it can prevent the expensive costs of finding the correct placeholder - Added the beginning of tracking stats (through the pre-cache0 and will be adding an actual placeholder cache in the near future. +* Mine Bombs - fixes and enhancements +* Starting to create a new sellall module that will support multiple shops and custom blocks (not just XMaterial names) +* Block Converters - Will allow full customization on all block specific things within auto features - will eliminate all hard coded block +* Started to add NBT support. - Used in mine bombs - Starting to use in GUI's to simplify the complexity of hooking actions up with the menu items. +* Added rank scores and top-n players - Rank score is a fair way to score players within a rank. It's currently the percentage of money they have to rank up (0 to 100 percent), but once they cross the 100% threshold, then 10% of the excess subtracts from their rank score. This prevents camping at levels. +* There is more stuff, some major, a bunch of minor, and many bug fixes along the way. + + + + + +* **v3.3.0-alpha.12 2022-06-25** + + + +* **v3.3.0-alpha.11k 2022-06-20** +Plus luckperms doc update. + + +* **Mine resets: Fixed an issue when dealing with zero-block resets on a very small mine, such as a one block mine in that the 5 second delay was preventing from rapid resets.** +Bypass both 5 second cooldown on resets and blockmatching when 25 blocks or less for the mine size. +With running resets in async mode, with rapid resets for a one-block mine, the handling of the block breaks can occur out of order, which will trigger the block mismatch. + + +* **Fix issue: On the creation of a new mine, it would reset the mine a number of times. This fixes the problem by only allowing one reset every 5 seconds at the soonest.** + + + +* **Placeholder fix: The PAPI placeholder integrations should not be prefixing raw text with "prison_"; that is the task for PlaceholderIdentifier.** + + +* **minor items changed with the GUIs... no functional changes.** + + +* **Update a number of docs...** + + +* **Fixed an issue where if you try to use a % on a number it's causing String format errors.** +This now strips off % and $ if they are used. + + +* **Update Docs: LuckPerms groups and tracks... added images and fixes a few minor things too.** + + +* **Update some of the docs on setting up luckperms and tracks.** + + +* **v3.3.0-alpha.11j** + + +* **Since the chat event is handled within the spigot module, and since ranks and mines would just duplicate the processing since they both will hit the SpigotPlaceholder class, it made sense to handle the chat event directly within the spigot module.** + + +* **Updates to the prison placeholder handler. This fixes a bug with chat messages return a null value.** +These changes also allows the pre-cache to track invalid placeholders now, so it can fast-fail them so it does not have to waste CPU time trying to look up which placeholder key they are tied to. + + +* **v3.3.0-alpha.11i** +Getting ready to release alpha.12. + + +* **Placeholder stats: A new feature that is tracking usage counts with placeholders.** +This is not a placeholder cache that caches the results, but it caches the placeholder that is associated with text placeholder. The stats currently only tracks the total number of hits, and the average run time to calculate the placeholder. +The pre-cache will reduce some overhead costs. This also provides the framework to hooking up a formal placeholder cache. + + +* **Placeholders: changed the two top_player line placeholders that are the headings** + since they originally had _nnn_ pattern that is getting messed up in some settings. So removal of the nnn helped to getting it working. + + +* **GUI MInes: Update support for custom lore support within the gui configs.** + + +* **Update XSeries from v8.7.1 to v8.8.0 to better support the newest blocks.** + + +* **Updated item-nbt-api-plugin from v2.9.2 to v2.10.0.** + + +* **v3.3.0-alpha.11h 2022-06-14** + + +* **Prison Placeholders: General clean up of obsolete code.** +Since the new placeholder system is working well with the new class PlaceholderIdentifier, obsolete code that was commented out has been removed. +The obsolete class that used to be the key component to identifying placeholders was PlaceholderResults and is no longer used anywhere. It's core components were moved to PlaceholderIdentifier and therefore all references to this obsolete class has been eliminated. +At this time, PlaceholderResults has not been deleted, but will be at some future time. + + +* **Prison Placeholders: Major rewrite the handling of placeholders.** +Prison's placeholder handling was completely rewritten to better handle the matching of a placeholder text with the actual placeholder objects. Over the last few years, many new features were added to prison's placeholders, but the way they were implemented were through patching existing code. This rewrite starts from scratch on how placeholder are decoded. Placeholders are now only decoded once instead of being decoded when attempting to match each internal placeholder. The results are significant performance improvements and eliminates a lot of redundant code. Some new features were add, such as supporting more than one placeholder attribute at a time. Also it streamlines how parameters and data is passed from the outer most layers of prison to where the placeholders are calculated. + +Another major benefit of this rewrite, beside reduction of code complexity and performance improvements, is that it opens the door to being able to implement an internal placeholder cache. Some plugins request placeholder data once per tick, or 20 times per second. Multiply that by 50 online players, and you got prison performing the same calculation 1000 times per second. Caching could help reduce that to only one calculation per second (assuming a cache time to live value of 1 second. Caching will not always be so simple, or possible, or every placeholder. Player-based placeholders can't be cached like static mine placeholders (mine names and mine tags as an example). + + +* **Add support for Portuguese.** + + +* **BlockConverters: fix issue when block converters are not active.** + + +**v3.3.0-alpha.11g - 2022-06-11** + + +* **Disable the gui for autofeatures configs. They are so out of date, they were causing problems.** +Autofeatures should be manually edited. + + +* **Fix a problem when BlockConverters are disabled, and doing a reload on auto features, it's not able to find that config file so its throwing an exception.** + + +* **The build was failing intermittently on the continual integration (CI)** +pertaining to the item-nbt-api-plugin, so an entry to added to "lock it in" to the correct path within the mavenrepository.com repo. +This should prevent the resource from being paired with the wrong repo. + + +* **There is a situation when checking for new updates to the language files, that it needs to write the new file, but the old one has not been archived.** +This now checks to make sure the old one has been renamed, and if it hasn't, then it will rename it. + + +* **Added an entry for the sellall module in the modules.yml file.** +Code has been setup to check, with a default fall-back on to the sellall settings within config.yml file. The entry in config.yml has been commented out. +Either will work, but the setting within modules.yml will take priority. + + +* **Update XSeries to v8.7.1 from v8.6.2.** +Note that this does not add any of the newer 1.19 blocks or items. + + +* **GUI: Fixed some issues with the gui and admin perms. Added some admin perms to a few gui commands to lock them down.** +Found a serious issue with non-admins being able to edit rank costs and sellall item costs. The GUIs were not locked down and if the players knew the commands, they could edit the costs. + + +* **v3.3.0-alpha.11f 2022-06-06** + + +* **BlockConverters: minor changes.** + + +* **Bug fix: Backpacks were not working properly with just ".save()" but had to add ".setChanged()" too, otherwise minepacks will not actually save the status of the backpacks.** + + +* **BlockConverters: rename targets to outputs.** + + +* **BlockConversions: hooked up the code to not only filter and return the blockConversions for the player and the block, but to also return the item stacks from the results.** +This is just about ready to be used in the code. + + +* **Romanian Locale language files were placed in the wrong location.** +Oreoezi provide two new language files for the Romanian Locale, but they were placed in the wrong location. +They were added to "prison-core/out/production/resources/lang/core/" and ".../mines/". For them to actually +work correctly, without being deleted, need to be placed within the following path: +"prison-core/src/main/resources/lang/core/" and "prison-core/src/main/resources/lang/mines". +These should now be usable. Also the LocaleManager now has alternatives setup to default to en_US; future +alternative languages can be added in the future. + + +* **BlockConverters: add some validators to the BlockConverters.** +Reports various issues, fixes non-lowercase source block names, and also disables invalid settings. + + +* **BlockConverters: Adjusting around how they are setup, and how they are generated.** +BlockConverters are now in their own config file: blockConvertersConfig.json. +They are no longer being stacked/placed in the autoFeaturesConfig.yml file, so all the conversion code is no longer required. With it being json, it now can reflect the java classes without any special considerations on the conversion process. + + +* **BlockConverters: More work on these settings.** +Setting up to work with AutoFeaturesConfig.yml, but having second thoughts about adding these configs to that file since it will complicate the config details. + + +* **Fixed a bug on the smelting of coal_ore which was yielding 10 times too much, but this was never seen since a silk touch pickaxe would have to been used.** + + +* **Placeholder fix for `prison_mines_blocks_mined_minename` since it was not being incremented after the fixing of the autopickup=false and handle normal drops = true.** +Also found that the calculated field for the mine's total blocks mined was not being recalculated after load the mines from their save files. This now is working properly. + + +* **Major exploit fix: sellall was not indicating that the inventory was changed within the Minepacks backpacks,** +and therefore players were able to sellall of their inventory, logoff, and then when they log back on, it will be restored. +Now, all inventory changes are forcing a save for the backpacks. + + +* **Fixed an incorrect mapping to a message: auto features tool is worn out.** + + +* **v3.3.0-alpha.11e 2022-05-23** + + +* **Bug fix: Fixed an issue with sellall when the module sellall is not defined but sellall is enabled in the config.yml file.** + + +* **Bug fix: Minepacks has a new function in their API to force backpack changes to be saved.** +Before it could only be marked as changed, which was not enough to get it to save in all situations. Prison is now calling "save()" to ensure its behaving better now. +NOTE: releasing this fix with alpha.11d even though it has been added after being set to 11d. + + +* **Prison v3.3.0-alpha.11d 2022-05-22** + + +* **GUI messages: a few more updates and corrections** + + +* **GUI: More fixes to the gui messages... including moving all of the new gui specific messages out of prison-sellall module to the prison-core module so they will still be accessible if the prison-sellall module is disabled.** + + +* **GUI cleaned up by eliminating so many excessive uses of translating amp color codes to the native color codes.** +Found some locations where there were at least 7 layers of function calls, with each layer trying to translate the color codes, which of course was excessive. + + +* **Change the name of the SpigotSellallUtilMessages class to SpigotVariousGuiMessages due to the fact these messages are used in more than just sellall.** +It should be noted that eventually the non-sellall messages may have to be removed from the sellall module. + + +* **Spigot GUI Messages: Hook up more messages to prison's messaging system.** + + +* **Sellall messages: Start to setup the correct usage of the multi-language message handling through the new prison-sellall module.** +This fixes the messaging within the SellAllUtil class. + + +* **Move auto feature messages to the spigot message file so they can be customized.** +Removed the inventory full messages from the AutoFeaturesConifg.yml file. + + +* **The normalDrops processing was not hooked up to the newest way auto pickup is disabled, which was skipping normalDrops if auto pickup was disabled.** +The number of blocks in the normalDrops is now being passed back through the code so it can identify that it was successful and finalize the processing. + + +* **3.3.0-alpha.11c 2022-05-14** + + +* **GUI Menus enable NBT support.** +This is a major change. The details for the menus options and commands are now stored in NBT data so they do not have to rely on the item name, lore, or other tricks. +This is a first phase, and more work needs to be done to remove hooks with the item names for other menu options. Main set of changes has been done to the menu tools. + + +* **Changed placeholder attributes to print the raw value and placeholder.** +Changes to the logging to allow & to be encoded to the unicode string of +`U+0026` so it can bypass the color code conversions, then it is converted back +to an & before sending to bukkit. This works far better than trying to +use Java regEx quotes. + + +* **Fixed signs for sellall to enable them to work with any wood variant.** + + +* **3.3.0-alpha.11b 2022-05-02** + + +* **Placeholder fix for formatted time segments to use the values setup in the language files within core.** +This allows the placeholders to use the proper notations for singular and plural units of times as configured for each language. + + +* **Placeholder fix for rankup_cost and rankup_cost_remaining on both the formating of the percents and the bar.** +The percents were being displayed as an integer, so with rounding, they were very misleading since they would show 100% when they were really hitting 99.5% and higher. Also the bar is not working better, and if the percentage is less than 100%, then it will always show a RED segment at the end of the bar; it will ONLY show GREEN when it's 100% or higher. + + +* **Mine Bombs fix to allow color codes within the bomb's name.** +The color codes are removed for the sake of matching and selecting when giving to players so you don't have to use them in the commands. + + +* **Placeholder issues when not prefixed with "prison_" is being addressed by prefixing the identifier with "prison_" right away.** +This "is" addressed, but it's deep in the code and for some reason certain parts of the code is not making the connection to the correct placeholder without that prefix. So this really is not the desired way to address this, but it eliminates the problem. The reason why it's not the desired way, is because it's exposing buisness rules of how to handle the placeholders, outside of the placeholder core code. + + +* **Bug fix... with placeholder prison_rank__player_cost_remaining_rankname, and its variants,** + eliminate the calculation of including the current rank since that has already been paid for. Prior to this fix, it was only excluding prior ranks. + + +* **3.3.0-alpha.11a 2022-04-25** + + +* **Mine Bombs and NBT settings: this fixes mine bombs to work with NBT tags, which are being used to identify which items are actually mine bombs.** + + +* **Fixes the mine bomb usage of lore where the lore that is defined in the settings is no longer altered so it's now used verbatim.** +Also the check for mine bomb is removed from using the name, or first line of lore, and now tries to use NBT data. +But note, that the NBT data is not working correctly yet. + + +* **Fixed the usage of setting up the NBT library within the gradle config file.** +Fixed issue with unknown, or incompatible items were unable to be parsed by XMaterial which was resulting in failures. This fixes the problem by preventing the use of a partial created SpigotItemStack. + + +* **Hook up the NBT library to the SpigotItemStack class.** +This has not been tested yet to see how it works, especially between server resets. + + +* **Added NBT support to prison. This loads a NBT library to be used only with the spigot sub-project.** +This has not been hooked up to anything yet. + + +* **Placeholder fix: Problem with the placeholder getting a prestige rank that was one too high.** +The following placeholders were fixed: prison_rrt, prison_rankup_rank_tag, prison_rrt_laddername, prison_rankup_rank_tag_laddername + + +* **Hooked up the BlockConvertersNode to the yaml file IO code so it will save and load changes to the auto features configs for anything with the BlockConverters data type.** +Removed unused functions. + + +* **Mine reset potential bug fix: Some rare conditions was causing problems, so using another collection to pass the blocks, and getting the size prior to calling the function to prevent the problems from happening.** +This appeared to be happening when a mine was being reset multiple times, at the same time. The mine should never be resetting multiple times, at the same time. May need to add more controls to prevent it from happening. + + +* **Bug Fix: The IGNORE block type was not marked as a block, therefore could not be used within a mine.** + + +* **New feature: Block Converters. Setup the initial core settings for block converters within the auto features.** +The core internal structure is in place and so is the ability to write the data to the file system. +This has not been hooked up to anything yet. + + +* **Setup placeholder formatted time values to use the language config file.** +This set of values will "NOT" reload when the command `/prison reload locales` is ran. The server must be restarted to reload these values. + + +* **CustomItems getDrops() debug mode will list the results of the get drops.** +This will help track what's going on with the getDrops function since it's a complicated process. + + +* **Placeholders: prison_rankup_rank_tag (and the ladder variants) now shows the prestiges next rank when at the top rank in the default ladder.** +This only applies to the default ladder and only if the prestiges ladder is activated. + + +* **Pull out the setBlock and blockAt functions from the SpigotWorld class so that way it would properly track within Timings.** + + + +** v3.3.0-alpha.10 2022-04-02** + +** Release notes for the v3.3.0-alpha.10 release as posted to spigotmc.org and polymart.org: + +v3.3.0-alpha.10 + +This alpha.10 release includes many significant performance improvements and bug fixes. Although this is an alpha release, it is proving to be stable enough to use on a production server. Please make backups and test prior to using. This v3.3.0-alpha.10 release is "still" backwards compatible with v3.2.11 so you should be able to down-grade back to v3.2.11 without major issues. The breaking changes that will be in the final v3.3.0 release have not been applied yet to these alpha releases. + +Please see our discord server for the full listing of all bug fixes and improvements, there have been more than 70 updates since the alpha.9 release. The following is just a simple short list. + +- Many bug fixes. Some that even predates the v3.2.11 release. + +- Performance improvements: startup validations moved to an async thread. Slight delay between mine validations to allow other tasks to run (needed for less powerful servers). Improvements with sellall performance. + +- Added more support for Custom Items (custom blocks) + +- Added support for top-n players and added over 30 new placeholders. Top-n support for blocks mined and tokens earned will be added shortly too. + +- Upgraded internal libraries: bstats, XSeries, gradle, custom items, and a couple others. + +- Many fixes: Mine bombs, sellall, autosell, auto features, block even listening and handling. + + +* **Ran in to an issue with spigot versions < 1.13 where a data value outside of the normal range prevents XMaterial from mapping to a bukkit block.** +This change provides a better fallback which ignores the data value, which is the varient. The drawback of ignoring the varient type, which is outside the valid ranges anyway, is that it may not accurately reflect the intended block types. But at least this will prevent errors and being unable to map to any blocks. + + +* **Change to prison startup details reporting to elminate duplication.** +Near the end of the prison startup process, prison would run the `/prison version` command to provide additional information in the logs. This was duplicating some of the information that was already printed during the actual startup process. +Changes were made to only add the information that was missing so the whole command does not need to re reran. Overall this is a small impact, but a useful one. It does shift where these functions live and ran from. + + +* **ChatDisplay: An internal change that controls if a chat display object (multi-lined content, such as command output) displays the title.** +This will be useful when integrating in to other commands and workflows, such as redesigning how the startup reporting is handled. + + +* **v3.3.0-alpha.9g 2022-03-29** + + +* **auto features: Enable player toggle on sellall for auto feature's autosell.** + + +* **sellall reload - fixed issue where the reload was not chaning any online valus or settings.** + + +* **Mine bombs cooldown - ran in to a null value in the cooldown timers. Handles this situation now. ** + + +* **Sellall - added debug logging on the calculation of sell prices.** + + +* **Sellall bug fix on calculation boolean config values; it was not returning the correct value.** +This was found by a report that `/sellall hand` was not working. + + +* **Auto features bug fix: was paying the player, instead of just reporting the value when in debug mode.** + + +* **Update debug info in auto features to properly show it's within the BLOCKEVENTS priority processing.** + + +* **Topn calculations: handle a null being returned for the prestige ladder.** + + +* **Enabled a sellall feature to enable the old functionality where sellall ignores the Display Name or is not a valid prison block type.** + + +* **Fixed an NPE issue with checking to see if a block exists within a mine.** +This issue was impacting spigot versions less than 1.13. The problem is with data values being abnormal and out of the standard range. + + +* **Fixed a NPE on the topn calculations.** + + +* **auto features autosell when inventory is full when using the priority BLOCKEVENTS.** + + +* **topn fix: If next rank is null, then try to use the next prestige rank for the cost.** + + +* **v3.3.0-alpha.9f 2022-03-25** + + +* **Placeholders top player: added new placeholders based upon the _nnn_ pattern to identify the player.** + + +* **Top-n players listing: added an alternative line.** + + +* **Placeholder Bar Attributes: Now supports a non-positional keyword "reverse" which will take any bar graph and reverse it.** + + +* **AutoFeatures debugging: Some color change in the logging details for failures so they are easier to see.** + + +* **Prepare for the handling of STATSPLAYERS placeholders, which will be the ones that provides the placeholders for the top-n players.** +This handles the workflow on handling the placeholders. + + +* **Slight update on how the top-n players are printed... simplifies and also cleans it up the formatting.** + + +* **Updated the rankup accuracy to be greater than or equal to 1.0.** +And conditionally only report the accuracy_out_of_range if >= 1.0. + + +* **When validating the success of a rankup transaction's abiliity for the rankup cost to be applied, the validation is now checking to see if it's within a plus/minus of 1.0 from the target final balance of the player.** +This covers the inability of floats and doubles not being able to accurately repesent base 10 numbers all of the time, which the accuracy may be off by a small value such as 0.000001, but that will prevent an equality check from passing. +By checking that it's within a range of plus/minus one will help prevent false failures. + + +* **Fixed issue where ranking does not which rank is associated with each rank.** +Now the ranks will properly track the players at their ranks. + + +* **3.3.0-alpha.9e 2022-03-14** + + +* **Top-n: More work to enable. Now supports /ranks topn, with alias /topn.** +The rank-score and penalty is not yet enabled. Placeholders will be enabled after the command is fully functional. + + +* **Prison startup performance fix: On large servers with many players, the process of getting the player's balance from the economy plugin can cause significant delays if that plugin is not able to handle the load...** +so the validation of the players and the sorting of the top-n list is now ran in an async thread so it will not cause lag or delays on startup. + + +* **Prison version: including more information on ranks and add the ladder rank listing to the prison version command.** + + +* **Removed some old code from block event processing...** + + +* **Mine bombs getting a replacement blocks from the player's location.** + + +* **CustomItems drops: If custom items do not produce a drop, then default to dropping the block itself.** + + +* **Sellall: prevent selling with custom name items.** + + +* **PlayerCache earningsPerMinute: Sychronize to prevent an issue with concurrent mods.** + + +* **Mine bombs: Fix an issue with the generated mine bomb tool not being enchanted with the specified fortune, which also was effecting the durability and dig_speed too.** + + +* **Reworked how some of the registered event listeners are setup, which is needed for expanding to supporting other plugin's enchanments.** + + +* **Update the bstats configs for v3.0.0.** +Although it compiled without the bstats-base, it failed to run. I suspect my local cache for gradle was incorrectly providing objects when it shouldn't have. + + +* **Upgrade bstats to v3.0.0, was at v2.2.1.** +Hoping this will better report the proper usage. +Added more custom details on the graphs: player count, defaultRankCount, prestigesRankCount, otherRankCounts. +Set api version to v3.3. + + +* **BugFix: Prevent a possible NPE when blocks are null when calculating gravity effected blocks, and ensuring there is a location when trying to place blocks.** +Both of these should never be an issue, but based upon different conditions, they can become an issue. + + +* **Added an autoFeatures to enable/disable the use of CustomItems' getDrops().** + + +* **CustomItems integration: Adding support for getDrops() from CUI.** +This integrates custom blocks in to getting the SpigotBlock (an internal prison block). +It's not yet functional due to issues within CUI, but this is the initial setup. + + +* **Report that bedrock users are not getting their tokens.** +When in debug mode, if their balance is not correctly updated it will report it in the console. + + +* **v3.3.0-alpha.9d 2022-03-10** + + +* **Within the SpigotBlock, now has hooks to load CustomItems blocks when trying to convert an org.bukkit.Block to a SpigotBlock.** + + +* **For unbreakable blocks, reinforce that the location, which is the key, will not be null.** +The block sometimes can be null, so by having the seperate location will not cause a failure if the block is null. + + +* **Fixed an issue when checking if a block is unbreakable... it should not have been null, so this is a temp fix to prevent an error.** + + +* **CustomItems custom blocks: Hook up the new drops for CustomItems plugin.** + + +* **Update some of the gradle settings and fix the new custom items api.** + + +* **Upgrade XSeries from v8.5.0.1 to v8.6.2.** + + +* **Update CustomItems API from v4.1.3 to v4.1.15.** +This update adds support for prison to get the drops from the CustomItem blocks. + + +* **Changed the development environment and updated the java 1.8 to the latest release.** + + +* **v3.3.0-alpha.9c 2022-03-06** + + +* **Enable the ability to split messages in to multiple lines by using the placeholder `{br}`.** + + +* **Small adjustments to the MineReset handing of the targetBlock collections.** +Prevent their instantiation in the constructor since they are being lazy loaded. Also synchronizing on the adding of target block, since there was one report on an issue with that not being synchronized. + + +* **Added more validation checks and reporting on rankups and demotes.** +So if something goes wrong, it can hopefully identified and tracked. +If rank change failed, or if a refund failed, it will now better report these conditions. + + +* **Setup a return of success, or failure, on custom currency functions.** +GemsEconomy does not indicate if it was successful, but added code to check to see if it was successfully manually/indirectly. + + +* **Sync set blocks fixes. Isolate the targetBlocks and add a null check to ensure thre are no problems.** + + +* **RankLadder: removed obsolete code that was never used.** + + +* **Some initial setup for a rankScore.** +This is not hooked up yet, but the the core basics are there and should work soon. + + +* **Bug fix: Fixed an issue were a block would be added, or changed, and it would change all similar blocks in all mines to have the same percentage.** +This issue was intermittent and was caused by directly getting the block from the master list, without cloning it. The correction to this issue was to use a search function that would clone the block, but it also would compensate for custom blocks if the block's namespace was not initially provided. + + +* **Bug fix: Risk of a null on the blockHit, so add checks to ensure it's not before trying to process.** + + +* **Bug fix: The clickable delete code is that is generated is off by 1 on the inserted row.** +The row number needed to be reduced by one since the row number was incremented right before this final injection. + + +* **v3.3.0-alpha.9b 2022-02-28** + + +* **Fixed the command '/ranks ladder command remove' when specifying a row value that was too large.** +The message was only providing one value when it should have had two, and the first parameter was '%d' instead of '%1'. + + +* **PlayerCache: Unloading Players... when a player is being unloaded, and they are not in the cache, the unloading process is now able to indicate that the player should not be loaded.** +Also when trying to load a player, it will not attempt the load if the file does not exist. + + +* **Sellall bug fix... was using the wrapper to map it to an XMaterial which was causing NPEs.** +Using the prison's compatibility functions to perform the mapping, which will now provide a safer mapping that will not cause NPEs. + + +* **Module prison-sellall cleaned up gradle config to remove a few configs that are not needed.** + + +* **Fixed a bug with the blockEvent block filter for adding blocks, it was using the blockEvents collection instead of the prison blocks collection.** + + +* **Fix placeholder for prison_player_tool_lore to provide the actual tool's lore.** +The placeholder was not hooked up. + + +* **Mine manager when enabling mines after the delayed loading from multiverse-core delayed loading...** +put a slight delay on each submission of the startup air counts for each mine... spacing them out by one tick so they are not all trying to run at the same time. + + +* **v3.3.0-alpha.9 2022-02-27** + + +* **Bug fix: Sellall error: Resolve an issue with the off-hand not being removed when selling.** +Turned out that you can read all inventory slots, which includes the off-and slot, but when removing ItemStacks, the remove(ItemStack) function then ignores the off-hand slot. Has to directly remove from the off-hand slot. + + +* **Mine bombs: fixed issue with lore not being added.** +Was adding the wrong source; was adding the destination to the destination. + + +* **Mine Bombs: Add some basic validations when loading the mine bombs from the config files** + + +* **Mine Bombs: add a reload function for mine bombs.** +/prison reload bombs or /prison utils bomb reload + + +* **Removed warnings from the Vault economy wrapper since NPCs can actually initiate commands and NPC will always return nulls for OfflinePlayers....** therefore just return a value of zero. + + +* **New command added to '/prison support runCmd' to allow an OP process, such as a NPC in Citizens, to run a command as a player.** +For example this is handy for having an NPC open the player's GUIs such as mines or ranks. + + +* **v3.3.0-alpha.8h 2022-02-26** + + +* **Bug fix: Synchronized some of the collections that are needing it within the PlayerCache.** + + +* **Bug fix: Fixed an inventory glitch that was preventing items from being added to the inventory.** +Basically the inventory had items, but it was not updating the contents of the inventory on the client side. This was fixed by updating inventory when finished processing the adds. +If autosell on full inventory is enabled, and there are extra drops, then sell them all before they make it to the inventory. This works most of the time, but sometimes the inventory still fills up. This is now more of a characteristic than a bug. + + +* **3.3.0-alpha.8g 2022-02-25** + + +* **More adjustments to the block events so the config setting can be shown in the header of the /prison support listeners blockevent command.** + + +* **Setting up support for the BLOCKEVENTS on all block break event listeners.** +Changed around how the listeners are created to simplify and be more accurate in the event states. + + +* **Extracted the BlockBreakPriority enum to be an object on its own.** +Added BLOCKEVENT and added information on what the various priorities should do. This is in preparation to refactoring how events are processed. + + +* **Prison tokens: externalize the messages related to the admin tokens commands.** + + +* **For the admin commands for tokens, added an option to be able to suppress the messages.** + + +* **v3.3.0-alpha.8f 2022-02-23** + + +* **The creation of a new sellall module which will eventually contain the code to manage multiple shops that will be based upon ranks.** + + +* **Adjustments to the configuration of the mutex to better ensure that only one job is submitted for the reset, and to ensure other tasks are not locked up, or locked out.** +There was a report that the prior way was causing the mines to lockup. + + +* **v3.3.0-alpha.8e 2022-02-20** + + +* **Mine reset mutex is conditionally enabled to ensure the locks remain balanced.** +To ensure the mutex is enabled ASAP, its engaged outside of the normal location... it may only be a few nano-seconds savings, but with OP pickaxes mining with many players within one mine, the mutex must be enabled rapidly. + + +* **Bug Fix: Mine reset changes: Eliminate paged resets, some code that is not being use anymore, disabled the RESET_ASYNC type to be similar to RESET_SYNC since they are now the same, locked out checkZeroBlockResets so mines cannot reset multiple times at the same time using the MineStateMutex.** +The major issue here was that mines were being reset in the middle of a reset action. Used a preexisting MineStateMutex to secure the checkZeroBlockResets() function to prevent it from kicking off many resets. These multiple resets were happening because many players were triggering the resets... as a side effect, there were many situations of collections failing due to concurrent modification exceptions. + + +* **Getting the collection size was an issue by the time it was done processing the blocks, so getting them first may help prevent errors.** + + +* **Made many changes to the default configurations of the autoFeatures.** +This is to try to make it easier to use prison by using more of the settings that are most useful. +Added more comments to make it easier to understand these settings too.f + + +* **Release v3.3.0-alpha.8d 2022-02-20** + + +- **Fixed issues with vault economy and withdrawing from a player's balance.** +It now also reports any errors that may be returned. + + +* **To prevent NPEs, isBlockAMatch has been changed to use the MineTargetPrisonBlock as a parameter and then internally, checking for nulls, it will extract the status data block.** +This was causing errors when processes were trying to access target blocks before they had a chance to initialize. + + +* **Address a rare condition where the mineTargetPrisonBlocks is being "accessed" before the system is done initializing the mine.** +This creates an empty collection, but it will prevent errors in the long run. + + +* **Add equals and hashCode to the MineTargetBlockKey so it can be better used in structures like HashMaps.** + + +* **Mine bombs: Added a {countdown} placeholder for use with the MineBomb's tagName field.** +A few other adjustments such as adding more "color" to the default bomb tagNames. + + +* **Added validation check to make sure the player's balance was decreased, or increased, successfully before actually applying the rank change.** +If the balance does not reflect the change, then the rank change will be prevented. + + +* **Slight adjustment to addBalance so as to help reduce out of synch possibilities.** +The access to economy hooks, has been moved in to the sychronized block. + + +* **v3.3.0-alpha.8c 2022-02-16** + + +* **Fixed a start up issue with multiverse-core in that it now runs the air-count processes so the mines can have their targetBlocks defined.** +Many issues were resulting from failure to get the target blocks. Not sure how it was working before, other than targetBlocks were not being used as much as they are now. + + +* **Fixed a potential error if targetBlocks are not loaded yet, or loaded at all for a given mine.** +Was causing NPEs.... + + +* **Added logging for when a delayed world comes online and list all mines that are activated.** + + +* **v3.3.0-alpha.8b** + + +* **Clean up the way the command tasks were being called.** +Added mine name to the blockEvent logging. + + +* **Fixed a reversal of some calculations when converting nano seconds to milliseconds.** + + +* **New feature: debug count down timer.** +Able to now set a debug count down timer where debugging is turned off after logging that number of entries. + + +* **Potential bug fix in better managing if sellall should be enabled by directly checking the configuration parameter that enables it.** +Better logging of sellall when inventory is full. + + +* **Commit some SellAllUtil comments that are useful for debugging timing issues.** +These are now disabled, but can be manually reenabled when needed. + + +* **Some changes to Sellall to provide more flexibility and to fix some potential bugs** +The isEnabled now uses the proper boolean settings to indicate if the sellall utility is enabled or not. Before it was trying to treat strings as boolean. + + +* **Add prison command descriptions that goes along with the placeholders.** +They are not yet hooked up, but they will provide more information to the admins on what the placeholders will provide, and also how they can use them since some of these will include examples of the formats. + + +* **Bug fix: The cancellation of the event was not being returned in the correct locations**, +so it was bypassing all of the before mine reset commands. The before mine commands will now run correctly. + + +* **Prison commands: reorganize some of the structures used for the prison commands.** +Hook up some of the logging to track run times for each command. + + +* **Prison commands: reorganize some of the structures used for the prison commands.** +Hook up some of the logging to track run times for each command. + + +* **Prevent the autosell happening just because someone is op.** +To make this work, and to prevent odd behaviors where OPs suddenly are not able to mine correctly, OP can no longer use the autosell based upon perms. + + +* **Setup the time durations on reporting of mine resets to use external settings.** +Enables the use of singular and plural unit names. + + +* **Rework how rankup commands are ran: in progress.** +This new way of dealing with rankup commands is to collect all commands that need to be ran, from all rankups, then run them in one group when the player is done being ranked up. +For most changes in rank, this will have zero effect on anything (mostly), but it has a huge impact with the **rankupmax** command. +When hooked up (which is is not), this will take all commands and run them in a sync task. So "every" command will run in a sync task. But each command will be monitored for run time, and if the runtime for one command exceeds a threshold, then the sync task will resubmit itself to run again after on tick. This will slow down the process of running all of the commands, but it will help prevent them from causing lag. +With tracking run times on each command, if prison is in debug-mode, then it will generate console logs identify how long it take to run each command. So if any given command is causing lag, then it would be possible to identify what the offending command is. + + +* **Fixed a problem before releasing... was not using the correct variable so the generated File object was not getting used.** + + +* **Bug fix: If a player cache file does not exist, it now prevents it from loading.** + + +* **Fixed an issue with the GUI, such that if the player does not have a rank on the ladder**, +that it will now force the creation of a PlayerRank object so it does not cause a NPE. + + +* **Mine bombs: Enable the use of color codes on the armor stands when setting off the bombs...** + + +* **Mine bombs: Added durability and digspeed enchantments to the mine bomb data.** +This will allow for greater flexibility in how the tool in hand behaves. + + +* **If using a mine bomb, then do not allow durability calculations to be used**, +since if the pseudo tool breaks, then what ever the player is holding will be removed, which is usually an item stack of mine bombs. + + +* **Mine Bombs: The mine bomb give command now is case insensitive.** + + +* **Mine Bombs: Add ability to set the Y offset.** +It defaults to a value of -1. This allows fine tuning of bombs to better position them to sink deeper in the mine to increase the number of blocks that are included. + + +* **Fix issue with mine bombs not dropping blocks.** +The underlying block changed and therefore so did the behavior of the equals() function. + + +* **Added various token functions to the prison spigot API class.** + + +***3.3.0-alpha.8 2022-02-12** + + +* **Enable debug mode from within the config.yml file.** +It was not hooked up before. This is useful for initial logging of the mine air-counts. + + +* **Redesigned the initial mine air-counts which not only identifies which blocks are within a mine upon startup, but it also establishes the number of air blocks in a mine to help ensure it's able to properly reset when the mine is empty.** + + +* **Bug fix: cleaned up the way PlayerCache files are managed.** +Eliminated a lot of old code and simplifed the logic to ensure the liklihood of preventing corruption of the player caches. There has been some reports that the files were not being properly tracked and stats were being replaced with new entries. This also fixes some performance issues by caching the files in the directories. So once loaded, the loaders no longer need to read the file listings, which could take a while with a lot of files. + + +* **Provide information on locale settings within the `/prison version` command.** +Falls back to the en_US properties file if the selected language file does not exist. +If the non en_US properties files are found to be missing a property, then the english property is used as a fallback. These fallbacks are not written back to the save files. + + +* **v3.3.0-alpha.7 2022-02-09** +Set this back on an alpha release schedule. The betas appear to have been pretty stable. + + +* **Disable the player's nms attempts to get their locale... spigot 1.17 and higher no longer can get that value.** +Just use the server's default value. + + +* **For the /prison support commands, the output is now sent to the player instead of just the console.** + + +* **Some minor changes to /prison debug to give it an alias of /prison support debug.** +Format a few of the messages to make it easier to understand. + + +* **Removed the backpack's object from the player's cache.** + Backpacks are too massive for the player's cache and needs thier own cache system. + + +* **On the command /ranks set tag, added the note that if a tag is removed from a rank, then the rank name will be used instead.** +Fixed the placeholder for rank tags so if it is null, it no longer show a null, but now it show the rank's name. + + +* **Fixed the generation of the player mined block count placeholders.** +Was missing one _ after generating the specific block related placeholder. + + +* **Upgrade gradle from v7.3 to v7.3.1 to v7.3.2 to v7.3.3** +This is at the latest release. + + +* **Upgrade gradle from v7.2 to v7.3** + - Changes to provide better security when runnign gradle to prevent injection attacks. + + +* **Upgrade gradle from v7.1 to v7.1.1 to v7.2.** + + +* **Upgrade gradle from v7.0.2 to v7.1.** +NOTE: There are a number of updates to apply for gradle. Will commit on the minor versions and final version. + + +* **Added a few new placeholders and a new placeholder type of PLAYERBLOCKS.** +Added raws to the player_block_total per mine. Added player_blocks_total and its raw counts, which is a PLAYERBLOCKS. + + +* **Added a few new placeholders and a new placeholder type of PLAYERBLOCKS.** +Added raws to the player_block_total per mine. Added player_blocks_total and its raw counts, which is a PLAYERBLOCKS. + + +* **Changed around the logging of messages related to the use of autofeatures autosell.** +Added permissions to enable autosell on a per block. + + +* **Update CustomItems api from v3.7.17 to v4.1.3.** +This newer version of the API still does not have a getDrops() function. + + +* **Add more support for CustomItems plugin.** +It appears like this is working really well with auto pickup. It should be noted that the CustomItems' API does not have a getDrops() so it's impossible to get the correctly configured drops for the block, so for now, it will only return the block itself and not any configured drops. +Sellall may need to be fixed and there could be some other areas that needs some fine tuning, but so far all is working well. + + +* **For CustomBlockIntegrations added getDrops().** +This has to be used instead of bukkit's getDrops() since that will return only the base item drops, which are the wrong items. +For CustomItems plugin, there currently isn't a getDrops() function in the CustomItems API so instead, the integration's getDrops() returns the block. + + +* **If cancelAllBlockEventBlockDrops is enabled when it's not valid on the server version, then it will print the error to console, then turn off this features** + + +* **CustomItems: Hook up on server startup the ability to check for custom blocks when scanning the mines to set the air counts and block counts.** + + +* **Clean up the formatting on `/mines block list` so it's easier to read and looks better.** + + +* **If fail on /mines reset, then needed a missing return so the mine reset success message won't follow the error message.** + + +* **Bug Fix: When mine reset time is disabled, set to -1, and then all mines are reset with '/mines reset `*all*` details' it would terminate the reset chain on that mine.** +This change allows the next mine to be reset by not trying to set this mine's next action... which is none because reset time is -1. + + +* **v3.3.0-beta.2 2022-02-03** + + +* **Added an error message when failed to add a prestige multiplier.** + + +* **New feature: cached adding of earnings for the default currency.** +This was causing a significant amount of lag/slow down when performing autosell, or spamming of sellall. The lag was in the economy plugin not being able to accept additions of money fast enough. +Now this simple cache, will wait 3 seconds before adding the player's earnings to the economy plugin. When it does, it will do so in an async thread so as to not impact any performance in bukkit's main thread. Also prison's getBalance() functions, which includes the use of all prison placeholders, will include the cached amount, which means the player's balances appear as if they are not being cached. +Still need to cache the custom currencies. + + +* **Update /ranks autoConfigure to set notifications to a radius of 25 blocks, and enabled skip resets at a limit of 90% with 24 skips.** +Also moved DARK_PRISMARINE down a few levels since it's not as valuable as the other blocks. + + +* **Bug fix: Correct the comparison of a prison ItemStack by using compareTo.** +The old code was using enums, so the check for equality of enums resulted in comparing pointers, which will never work. +Updated a few other parts of the code to use the compareTo function instead of the equals function since that may not work correctly all the time. + + +* **For command /mines set notification added *all* for mine name so all mines can be changed at the same time.** + + +* **Change notification alerts from runnign every 5 minutes to every hour.** +Got a few complaints within the last fewa days that the notifications are too frequent. + + +* **Modified SpigotPlayer to add getRankPlayer() and modified RankPlayer to add getRankLadder, with short cuts for default and prestige so you don't have to always refer to their names (reduce errors).** +This is to remove the "mess" from other functions that need to get these player objects, of which sometimes they are not going about it the correct way. + + +* **sellall multiplier add - Now reports if a multiplier cannot be added. Also now adds the multiplier based upon the actual rank name**, +of which it was what the user entered with the command, which may not match the actual rank name. + + +* **RankLadders - Added a boolean function to check if the ladder is the default ladder or prestiges ladder.** + + +* **sellall multiplier - Now able to list all multipliers.** +It lists them in a 5 column listing. + + +* **Add debug logging when calling the external events.** +Will have to revisit this when hooked up to multi-block events, otherwise it could overwhelm the logging. + + +* **Ladder rank cost multiplier has 100 percent limits removed.** +Value can be any positive or negative number now. + + +* **Update some documentation related to CMI Economy.** + + +* **Broadcast the prison welcome message to all online players when prison is loaded with no mines or ranks defined.** +The messag is loggd to console 8 sconds after prison loads. The broadcast messags are sent 16 seconds after logging the welcome message. +The intention is to help bring awareness to new mods/admins that there is an easy way to get started with prison. + + +* **Broadcast the failed ranks loading to all online players.** +Its important that they know ranks failed to load. + + +* **Release v3.3.0-beta.1 !! Hooray!!** 2022-01-29 2:11 PM EST + + +* **Added nano-second timing autosell to confirm if there is a performance issue.** +My initial testings are showing that sellall has significant chance of performance problems in that selling items takes way too long. Will address in the future. + + +* **Disable all ranks related commands within the GUI menus.** +GUI was bypassing safeguards that were in place when the ranks module failed to load. + + +* **Update the placeholderAPI docs to correct the formatting of the docs to match what they should be.** +Had to indent by two spaces. + + +* **Created updated documents for the placeholderAPI wiki.** +These are local copies of the content since the prior content was removed/vandelized. + + + +* **New Feature: Added support for Quests so that block breakage within mines can now be tracked and be applied towards quests.** + + +* **Bug fix: Lapis_ore appently does not drop lapis_laluzi when using the bukkit's getDrops() function, it instead drops blue_dye, then when it gets to the player's inventory, it is then converted to lapis_lazuli.** +Therefore, auto sell cannot sell lapis_ore drops unles blue_dye is within the shop. I added blue_dye with the same value of lapis_lazuli to the sellall shop. This allows it to be sold now through auto pickup and auto sell. + + + +* **Bug Fix: Damage was being applied all the time.** +Found a field being initialized with a value of 1 when it should have been 0. + + +* **Prevent sellall from loading if ranks does not load. Sellall uses too many rank functions to stand alone.** + + +* **Bug Fix: The new Ranks error message handler which intercepts all ranks messags was failing to load properly when prison startup was not set for a delayed startup,** + which was because the ranks gui command (/ranks) was always being set even when ranks module failed to load. Now /ranks gui loads only if ranks was successful in being started. + + +* **Initially setup to use the actionBar for the messages, but that is not working correctly with such high volume of messages.** +So disabled them for now, but will switch them over shortly... + + +* **Format the earnings amount properly, so it will have a consistant format.** +Once in a while, instead of showing a value like 165.00 it shows 165.000000000000001. This is caused by the fact that doubles are binary, not base-10 so it canot always show the correct values. + + +* **Deprecated the MessagesConfig class since it is not implemented correctly.** +The messages should have been handled through Prison's multi-language tool, of which this does not use. + + +* **Try to use a different way to identify the item stack, especially if the bukkit item stack does not exist.** +This was a random error when using gravel, sand, and dirt on spigot/paper 1.12.2. + + +* **Clean up some of the refrences to the new/old block models.** + + +* **Added the new command: '/sellall list' that will list all blocks and their prices.** + + +* **Added comments that usage of auto features cancel drops will not work from spigot v1.8 through 1.12.x.** +Should work with v1.13.x and newer. + + +* **Fix some block issues, mostly getting the correct block bukkit block and limit it to only one location and function that ultimately provides these hooks.** +This release appears to be more functional, but it still should not be used since it's not fully tested. + + +* **First pass at removing the old block model. Do not use this release!!** +This compiles and runs on the server. Most commands appear to work, including mine resets, but no visual confirmation has been performed in game yet. Since so much has been changed and it has not yet been tested in-game, this release should not be used until such rudementary testing can be performed. + + + +
+- + diff --git a/docs/prison_changelogs.md b/docs/prison_changelogs.md index 189d308f2..1848a928c 100644 --- a/docs/prison_changelogs.md +++ b/docs/prison_changelogs.md @@ -18,15 +18,19 @@ may be insightful in to some of the evolutionary processes. These build logs represent the work that has been going on within prison. - - **[v3.3.0-alpha - Current](changelog_v3.3.x.md)** + - **[v3.3.1 - Current](changelog_v3.3.x.md)** + - **[v3.3.0-alpha - Current - Part 2](changelog_v3.3.xb.md)** - Future updates will be under the v3.3.x release - - [v3.3.3-alpha.18 - 2024-05-20](prison_changelog_v3.3.0-alpha.18.md)   - - [v3.3.3-alpha.17 - 2024-04-20](prison_changelog_v3.3.0-alpha.17.md)   - - [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)   + - [v3.3.0 - 2026-06-19](prison_changelog_v3.3.0.md)   + - [v3.3.0-alpha.19b - 2026-06-19](prison_changelog_v3.3.0_b.md)   + + - [v3.3.0-alpha.18 - 2024-05-20](prison_changelog_v3.3.0-alpha.18.md)   + - [v3.3.0-alpha.17 - 2024-04-20](prison_changelog_v3.3.0-alpha.17.md)   + - [v3.3.0-alpha.16 - 2023-11-18](prison_changelog_v3.3.0-alpha.16.md)   + - [v3.3.0-alpha.15 - 2023-07-07](prison_changelog_v3.3.0-alpha.15.md)   + - [v3.3.0-alpha.14 - 2023-01-23](prison_changelog_v3.3.0-alpha.14.md)   - [v3.2.x - v3.2.6 2021-04-11](changelog_v3.2.x.md) diff --git a/docs/prison_docs_012_setting_up_prison_basics.md b/docs/prison_docs_012_setting_up_prison_basics.md index 71d18ace3..927072042 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-07-24* +*Documented updated: 2024-08-30*
@@ -86,6 +86,30 @@ We say an economy is required, but it's still optional. Without an economy, you Background: CMI "tries" to load last, so it can ensure all of it's dependencies and hooks are in place before it starts up. That's understandable, but Prison also has similar requirements and expectations. Unfortunately, this also causes a conflict with Prison, since Prison must perform validation on startup, and if there is no economy, then Prison could fail to start the Ranks module. The document, [Setting up CMI Economy](prison_docs_028_setting_up_CMI_economy.md), explains in detail how to get everything working perfectly. + + +**Coins Engine** is supported. A multi-currency economy. +*Need to provide more details* + + +**Gems Econommy** is supported. A multi-currency economy. +*Need to provide more details* + + +**EdPrison Economy** is supported. +*Need to provide more details* + + +**ESS Economy** is supported. +*Need to provide more details* + + +**The New Economy** is supported. +*Need to provide more details* + + +**Sane Economy** is supported. +*Need to provide more details* ### Chat Prefix Plugins - Optional @@ -200,6 +224,8 @@ But perhaps the biggest reason why I dropped support for MVdW is because it's 10 ### Enchantment Plugins +*NOTE: this section needs more work. It's not up to date, and does not list all of the various features.* + * **CustomItems** - Recommended - *A Premium Plugin* - Allows for the use of custom blocks within Prison. This provides for a great deal of customizations, including custom textures for your custom blocks. Prison supports CI at about 95% or more. If you need additional support added for CI, please contact Blue and he will add it for you. [https://polymart.org/resource/custom-items.1](https://polymart.org/resource/custom-items.1) @@ -239,10 +265,22 @@ Or if you are not using Prison Block Events, then just MONITOR should be used fo **Please note:** These settings may also apply to the other enchantment plugins if you do not want to use Prison's block handling. +* **EntityExplodeEvents** - This is a built in bukkit explosion event that lists multiple blocks. Some other enchantment plugins may support this event for their enchantments, and if they do, then prison will be able to support those plugins without the need of custom handlers. +*NOTE: This enchantment cannot identify the original block that triggered the explosion. Therefore there could be possible issues once in a while.* + + + +* **ExcellentEnchants** - Uses EntityExplodeEvents. + + +* **XPrison** - Prison supports some features form XPrison. This could allow you to continue to use XPrison for enchantment, but switch over to use prison for managing your ranks and mines. + + * **Zenchantments** - Optional - Some support is provided for zen, but it may not be 100%. More work needs to be done to improve the integration in to prison. This is an open source project. It identifies that it supports spigot 1.9 through 1.14 (different versions). [https://www.spigotmc.org/resources/zenchantments.12948/](https://www.spigotmc.org/resources/zenchantments.12948/). + * **Tokens** - **NOT SUPPORTED!!** Warning: People have paid for this plugin only to find out after the fact that it is not supported and they mistook it for *TokenEnchant* (see above). This plugin does not have a block explosion event that prison can hook in to, so it can never be supported. The developers have been asked a few times to add such an event, but they refused stating they did not see a purpose to add something like that. Hopefully in the future they will add support, and when they do, then we can add it to Prison. 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. diff --git a/docs/prison_docs_013_Prison_Help.md b/docs/prison_docs_013_Prison_Help.md index 353dfa148..f9c209877 100644 --- a/docs/prison_docs_013_Prison_Help.md +++ b/docs/prison_docs_013_Prison_Help.md @@ -7,7 +7,7 @@ This document provides some important information on how to find help in setting up your prison server, and ultimately, how and where to ask for help. -*Documented updated: 2021-12-03* +*Documented updated: 2024-08-30*
@@ -15,10 +15,14 @@ This document provides some important information on how to find help in setting 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. +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. + +We have gone out of our way, many times, to try to provide the best support that we can. We've made custom changes to prison to support specific needs, and to help solve specific problems. Many of these new features have become a standard part of prison too. So the bottom line here is, we take support seriously, and we're willing to find a solution to your challenges even if we have to some times go out of our way. + 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. * Review topics that may address your issue * At the end of the table of contents are some FAQs. Special situations may be added to them. @@ -136,14 +140,20 @@ 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. +Prison has a built in way to share your configurations and settings with support personnel. + +The way this works, is that when you generate a report, prison gathers all of the various data, and creates a single page (a very long page) document which it uploads to a 3rd party server. This information is very detailed and can help us better support everyone since we can see exactly how prison is configured. The service prison uses, is called PrivateBin. The reports are encrypted on the client (not at the server) and is held for only 7 days. Only people with the password can read the these documents. Prison defaults to a standard password for the encryption so we're able to read the reports when they are posted for us. That password, and time to live can be changed in the prison's config.yml file, but you probably do not need to change it. + + +We went with this service since the other paste bin that we were using in the past would never delete any of the documents. Generally they are only needed for a few hours, and worst case a few days. Any older than that, then they probably are not current and new docs need to be generated. So having a service that would auto-delete these was critical to find. Plus with it being encrypted on the client, no one can stumble across them and read them. So they are extra secure. Of course, with the URLs being posted within prison, anyone there can access them, and they probably can lookup the default password. Generally we're not too concerned about the Prison community seeing these documents, since they would not contain anything sensitive (except for logs maybe?) but it's your choice. You can DM them to us, change the password and DM us the password, or request that we delete the link as soon as we open it. If it's a concern to you, please let us know and ask questions and we'll figure out a procedure that will work for you. -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. +These commands will collect all of the related information from your Prison setup, and send it to the website `https://privatebin.net`. The older website that would not purge them or encrypt them is `https://paste.helpch.at`, and that is still available as a standby service. + +These commands 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 ` @@ -156,21 +166,17 @@ Once entered, it will enable the following submit 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. +**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 configs, listeners, and the command cache. This support page has expanded to include more details so there are fewer items to submit, if needed. +Listeners are dumps of the event listeners for BlockBreak, chat, and playerinteract. The blockbreak listeners include any that you have enabled. These can be used to identify problems with priorities and other possible conflicts. + **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. @@ -181,7 +187,9 @@ Here are two examples that I generated from one of my test servers on 2021-12-03 # 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. +**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. + +The reason why this format is not used with the privatebin.net service is because style sheets cannot be embedded in to a markdown document. HTML can be placed in a markdown document, which is what this version of support files are based upon, but without the style sheets and the simple javascript, these do not work and will not be formatted correctly. This file format is also good for server owners who do not want to post their server information on another website. @@ -198,7 +206,7 @@ If an existing file exists, it will generate the next one in the series. When r 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. +NOTE: Hyperlinks and table of contents will be added to this HTML support document in the near-ish future.
@@ -219,27 +227,32 @@ To enable the debugger, you can toggle them all on with `/prison debug` once to To review the options available, use the command `/prison debug help`. There are also debug targets that only enable specific debug statements and the list of the available targets can be displayed with `/prison debug targets`. +Please note, on busy servers, hundreds of messages can be logged in a very short amount of time. Therefore, one feature of the debug command is that it can target a specific user and only log a specified number of statements. That way, if you need to collect logs for sellall or block break events, you can enable it for yourself, or another player, do a few transactions, and it will auto shutoff. Please see the help text below for more information on how to use that feature. + + ``` >prison debug help -[12:16:39 INFO]: ---------- < Cmd: /prison debug > ------------- (3.2.11-alpha.9) -[12:16:39 INFO]: Enables debugging and trouble shooting information. For internal use only. Do not use unless instructed. -[12:16:39 INFO]: /prison debug [targets] -[12:16:39 INFO]: [targets] Optional. Enable or disable a debugging target. [on, off, targets, jarScan, testPlayerUtil, testLocale, rankup] 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. jarScan will identify what Java version compiled the class files within the listed jars -[12:16:39 INFO]: Permissions: -[12:16:39 INFO]: prison.debug +[23:02:19 INFO]: ---------- < Cmd: /prison debug > ------------- (3.3.0-alpha.18d) +[23:02:19 INFO]: Enables debugging and trouble shooting information. For internal use only. Do not use unless instructed. This will add a lot of data to the console. +[23:02:19 INFO]: /prison debug [targets] +[23:02:19 INFO]: [targets] Optional. Enable or disable a debugging target, or set a count down timer. [on, off, targets, (count-down-timer), selective, jarScan, testPlayerUtil, testLocale, rankup, blockConstraints, 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. 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. +[23:02:19 INFO]: Permissions: +[23:02:19 INFO]: prison.debug +[23:02:19 INFO]: Aliases: +[23:02:19 INFO]: [prison support debug] >prison debug targets -[12:17:19 INFO]: Global Debug Logging is enabled -[12:17:19 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, rankup, support +[23:03:19 INFO]: Global Debug Logging is disabled +[23:03:19 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints >prison debug [12:18:18 INFO]: Global Debug Logging is enabled -[12:18:18 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, rankup, support +[12:18:18 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints >prison debug [12:18:20 INFO]: Global Debug Logging is disabled -[12:18:20 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, rankup, support +[12:18:20 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints ``` It should be noted that every time you use the command, other than with the help keyword, it will always show the current status of the debugging information. It will show if the global logging is enabled or not, and if any targets are enabled, it will list all of the active ones. Plus it will show all of the available targets too. @@ -250,10 +263,10 @@ The following shows toggling the global settings: ``` >prison debug [21:12:10 INFO]: Global Debug Logging is enabled -[21:12:10 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, durability +[21:12:10 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints >prison debug [21:12:15 INFO]: Global Debug Logging is disabled -[21:12:15 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, durability +[21:12:15 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints ``` The following will show how you can toggle on a few features. Without using the actions 'on' or 'off' it will toggle the specified targets. The use of 'on' and 'off' can occur anywhere in the list of targets, and if both 'on' and 'off' are specified, then 'on' will take precedence over 'off'. @@ -266,13 +279,13 @@ First notice two targets are activated with two different uses of the `/prison d [21:17:23 INFO]: Global Debug Logging is disabled [21:17:23 INFO]: . Active Debug Targets: [21:17:23 INFO]: . . Target: blockBreak -[21:17:23 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, durability +[21:17:23 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints >prison debug blockBreakFortune [21:17:30 INFO]: Global Debug Logging is disabled [21:17:30 INFO]: . Active Debug Targets: [21:17:30 INFO]: . . Target: blockBreak [21:17:30 INFO]: . . Target: blockBreakFortune -[21:17:30 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, durability +[21:17:30 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints ``` Then using both of the same targets, they are toggled off. @@ -280,7 +293,7 @@ Then using both of the same targets, they are toggled off. ``` >prison debug blockBreakFortune blockBreak [21:17:42 INFO]: Global Debug Logging is disabled -[21:17:42 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, durability +[21:17:42 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints ``` Next, this is showing multiple targets being used, with the 'on' keyword mixed in. Notice it lists all of these active targets. Then `/prison debug` is used to globally turn on all features, which removes any individual targets. Then the global is used again to turn them all off. @@ -292,13 +305,13 @@ Next, this is showing multiple targets being used, with the 'on' keyword mixed i [21:18:31 INFO]: . . Target: durability [21:18:31 INFO]: . . Target: blockBreak [21:18:31 INFO]: . . Target: blockBreakFortune -[21:18:31 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, durability +[21:18:31 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints >prison debug [21:18:38 INFO]: Global Debug Logging is enabled -[21:18:38 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, durability +[21:18:38 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints >prison debug [21:18:43 INFO]: Global Debug Logging is disabled -[21:18:43 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, durability +[21:18:43 INFO]: . Valid Targets: all, on, off, blockBreak, blockBreakFortune, targetBlockMismatch, rankup, blockConstraints ``` @@ -309,6 +322,9 @@ Next, this is showing multiple targets being used, with the 'on' keyword mixed i # Prison v3.2.1 and it's Pre-Release Versions +NOTE: A lot has been added and changed since v3.2.1. This should be updated in the near future, but for now, view the current version in the console. + + The Prison startup screen contains a lot of information that can be used help identify issues that are detected by Prison on start up, and can provide useful information about the general environment. See the screen prints below. @@ -410,6 +426,14 @@ These screen prints may not contain the most recent enhancements to prison, sinc
+# Prison - Older versions + +We're happy to help support prison, but we cannot support older versions of prison. If a problem was found, we have tried to fix it, or to replace the faulty command. We also no long have the source code to go back, make a change, and produce a custom build for you. We encourage upgrading to the latest release of prison since we can better support you with those newer features, and we can make changes to the source code if needed. + +Generally, when you upgrade prison, you could always revert to an older version of prison. New features will be lost, but the data saved in the save files should be backwards compatible. This is no longer possible with Prison v3.3.0-alpha.18. That is because we are starting to change the save file formats so we can usher in newer features and also start to support database storage. + +Whenever prison upgrades, there was a new feature added a couple of years ago, to auto backup all of prison's config settings and store them in a zip file within the directory: `plugins/Prison/backups/` So although the newest versions of prison cannot be down-graded automatically, you can restore the older save files that have been backedup. + # Prison v3.1.0 and Earlier - General Information diff --git a/docs/prison_docs_101_setting_up_mines.md b/docs/prison_docs_101_setting_up_mines.md index 50c61b391..7cf480090 100644 --- a/docs/prison_docs_101_setting_up_mines.md +++ b/docs/prison_docs_101_setting_up_mines.md @@ -6,7 +6,7 @@ This document provides some highlights to how to setup mines. It is a work in progress so check back for more information. -*Documented updated: 2024-03-11* +*Documented updated: 2024-12-14*
@@ -136,6 +136,9 @@ A mine wand will allow you to set the coordinates of a mine by clicking on a blo A mine wand can also be used for debugging block break actions within a mine. If you are having issues with getting mines to work, it's one of the many built-in support tools that can help figure out what's going wrong, since a prison server can become very complex, especially when factoring in other plugins. Please contact us through our discord server for additional help if needed. +Note: You can now test block breakage with the command `/mines debugBlockBreak` while holding the tools of your choice. This may be a better way to test enchantment plugins, which will probably ignore a plain diamond pickaxe that is used by default with the mine wand. + +

Laying Out the New Mine

@@ -203,7 +206,7 @@ Some of the highlights of these commands are as follows: * `/mines set accessPermission help` : Use a mine permission to grant players access to the mine. This will override WG regions and resolve issues with strange behaviors resulting from WG. This must be a plain permission and cannot be a permission group. -* `/mines command` : **Now active!** **Take your mines to the next level!** See the document on [Mine Commands](prison_docs_111_mine_commands.md) for more information. Every time a mine resets, you can now control what commands run right before a reset, and what runs right after a reset. These commands are similar to the Rank Commands, since they can be any command that you can run from the console. The idea is that you can have unique mines that have not been possible before, such as randomly spawned forests or specific builds. +* `/mines command` : **Take your mines to the next level!** See the document on [Mine Commands](prison_docs_111_mine_commands.md) for more information. Every time a mine resets, you can now control what commands run right before a reset, and what runs right after a reset. These commands are similar to the Rank Commands, since they can be any command that you can run from the console. The idea is that you can have unique mines that have not been possible before, such as randomly spawned forests or specific builds. * `/mines delete` : Deletes a mine. You can always undelete a mine by going in to the server file system and rename the deleted mine, then restart the server. * `/mines info` : Very useful in viewing all information related to the mine. * `/mines list` : Displays all mines on your server. @@ -211,6 +214,11 @@ Some of the highlights of these commands are as follows: * `/mines rename` : Renames a mine. +* `/mines debugBlockBreak` if you need to debug what's happening with block breakage on your server, please use this new tool to get detailed account of which plugins are handling, or interfering, with the block breakage. This works both in side a mine, and outside. + * They way you use this command, is in game, you will look at a block (center the cross-hair on the block), while holding a tool, or weapon of your choice, then issue the command in-game `/mines debugBlockBreak`. Then look at the console for detailed information on the command's output. It will be very detailed, and could possibly be a few dozen lines long, or more, if there are a lot of installed plugins on your server. + + + * `/mines reset ` : Resets the mine. Forces a regeneration of all the blocks, even if the mine is in skip reset mode. `` should be the name of the mine, but can also be ** *all* ** to force all the mines to reset one after the other. If such action is performed, then all mine resets will be done through a submission with a slight delay between each reset, and it will prevent the running of the mine reset commands to prevent possible looping. `` should not be use directly without understanding what they do. * `/mines stats` : Toggles the display of stats that pertain to how long it takes to reset the mines. View /mines info or /mines list to see the stats. Use this command again to turn it off. @@ -269,7 +277,19 @@ Some of the highlights of these commands are as follows: * `/mines set notificationPerm` : Enables or Disables notifications pertaining to mine resets to be seen only by players who have permission to that mine. The permissions used are `mines.notification.[mineName]` in all lower case. * `/mines set notification` : Can turn off the notifications on a per-mine basis. Or set the notification radius, or only notify players within the mine. This command cannot change the message. * `/mines set rank ` : Links a mine to a rank, otherwise there is no way within prison to identify which mines should be associated with a given rank. If **rankName** is **none** then it removes the associated rank from the mine (deletes the rank). This is not yet needed, but it will be used in the near future with new features, or enhancements to existing features. -* `/mines set resetThreshold` : This allows you to set a percent remaining in the mine to use as a threshold for resets. For example if you set it to 20.5% then the mine will reset when it reaches 25.5% blocks remaining. When the mine resets, it will initiate the `zeroBlockResetDelay` functionality, of which it's not exactly "zero blocks" anymore. + + +* `/mines set resetThreshold` : This allows you to set a percent remaining in the mine to use as a threshold for resets. For example if you set it to 20.5% then the mine will reset when it reaches 25.5% blocks remaining. When the mine resets, it will initiate the `zeroBlockResetDelay` functionality, of which it's not exactly "zero blocks" anymore. + * Please be careful if using values that are way too high, such as over 90%, as it could possibly result in such frequent mine resets per second, that the internal mine-locks could become corrupt or stuck. If this happens, please manually reset the mine with `/mines reset force`. + * Excessive mine resets can cause lag and other server performance issues. This would not be considered a bug or a design flaw. It's more so a configuration issue, so use at your own risk. + * To find out how many mined blocks it will take to reset the mine, use this formula, which example of 98% threshold in a mine that is 30 x 15 x 30 (13,500 blocks): + * blocks-to-reset = total-blocks * (1.0 - percent-reset-threshold) + * blocks-to-reset = 13,500 * (1.0 - 0.98) + * blocks-to-reset = 13,500 * 0.02 + * blocks-to-reset = 270 blocks + * You may want to consider how quickly a player can mine blocks with the highest efficiency pickaxe that you allow on your server. Then multiply that projected value by the number of players that may be mining together in the mine. In general, you would want to increase the total blocks mined before resetting the mine, which will do a much better job of handling a large number of blocks being removed per interval. + + * `/mines set resetTime` : Changes the time between resets, as expressed in seconds. Applies to each mine independently. * **Removed:** `/mines set resetPaging` : This no longer is a setting, since Prison always uses a more advanced type of paging that dynamically prevents server lag. This is an advanced feature that can eliminate lag that might be experienced with the resetting of enormous large mines. A mine could be millions of blocks in size and without this setting it may take a few seconds, or longer to reset, and it could cause the ticks to fall far behind, even to the point of forcing a shutdown. This command instead will breakdown the mine's reset in to very small chunks that will prevent the TPS from slowing down, and it will allow other critical tasks to continue to run. The total length of time for the rest may be increased, but it will not hurt the server. Prison does not use async resets due to eventual corruption of the bukkit and spigot components. * `/mines set size` : Allows you to resize a mine without redefining it with the prison selection wand. Just specify which direction to increase or decrease. It also uses the `/mines set liner repair` feature to fill in voids when reducing an edge. @@ -478,7 +498,7 @@ The feature zero blocks reset delay identifies what should happen when Prison de If this feature is enabled, and the delay value is set to Zero, then the mine is forced to reset with no delay. If there is a light load of jobs running on the server, then it will be instantly reset, otherwise there will be a delay for the job to wait its turn to run. -If the reset delay is non-zero, the value is measured in seconds, with a valid value of 0.01 seconds. But keep in mind that in reality the seconds are converted to ticks and is scheduled within the Bukkit job queue. Therefore, since there are 1000 milliseonds within one second, and 20 ticks within one second, one tick is the smaller possible value, which equates to 50 milliseconds. This is equivalent to 0.05 seconds. When the seconds are converted to ticks, the values will be rounded down to a whole integer value. So if a value is provide such as 0.049 it will be submitted as 0 ticks, which will result in zero delay (if possible) before running. +If the reset delay is non-zero, the value is measured in seconds, with a valid value of 0.01 seconds. But keep in mind that in reality the seconds are converted to ticks and is scheduled within the Bukkit job queue. Therefore, since there are 1000 milliseconds within one second, and 20 ticks within one second, one tick is the smaller possible value, which equates to 50 milliseconds. This is equivalent to 0.05 seconds. When the seconds are converted to ticks, the values will be rounded down to a whole integer value. So if a value is provide such as 0.049 it will be submitted as 0 ticks, which will result in zero delay (if possible) before running. The bottom line is that this feature can force an earlier reset of the mine when it becomes totally empty of blocks. A delay may be needed, or desired, to reach your perfection for the mine. @@ -487,6 +507,9 @@ The bottom line is that this feature can force an earlier reset of the mine when By using the command `/mines set resetThreshold` it is effectively able to shift when the mine resets. It does not delay when the mine resets, but instead it provides way to trigger a reset based upon a percentage of the mine that remains. It works in conjunction with Zero Block Reset Delay too, where instead of waiting until zero blocks remain, it then applies a percentage to change the reset level. +A mine that is 10,000 blocks, when the resetThreshold is set to 90%, the mine will reset after about 1,000 blocks are mined (10%). Setting this value too high, like even over 80%, does not make sense. It would be far more efficient, and easier on the server's TPS to instead make the mine much, much smaller. Setting this to a high percentage is bad overall, because the mine will reset with a fraction of it's total blocks being mined, but yet a mine reset will replace all 100% of the blocks in the mine, which can contribute to server lag if the frequency is way too high. + +Very high values can also result in prison resetting the mine many times per second, especially if there are multiple players mining with very high efficiency pickaxes being used. It is also very much possible, that if the mines are being reset a few times per second, or even every few seconds, that the internal mine-locks that are being used could have their state become corrupt and therefore prevent the mine from resetting. If this happens, the locks should auto-release after 5 minutes. But you can also manually force a reset to fix them with `/mines reset force`. diff --git a/docs/prison_docs_310_guide_placeholders.md b/docs/prison_docs_310_guide_placeholders.md index 0dd29d5ca..e28600cd9 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: 2023-10-01* +*Documented updated: 2023-09-21*
@@ -21,6 +21,12 @@ On the surface they appear to be simple, but there are a lot of moving parts bel Add in to the mix, that different plugins deal with placeholders in slightly different ways, and you can wind up with a challenge to get them to work under different circumstances. + +**New Feature!** Custom Placeholders! + +Prison now supports the creation of custom placeholders, which can include any text, with formatting, and any number of placeholders too. Even non-prison placeholders. The benefit of custom placeholders is that you can create complex placeholders in one place, within prison, at any length, and then use them in any of your other plugins such as holographic displays, scoreboards, etc... Prison will expand all placeholders, including from other plugins, and provide the final result. + +
@@ -91,7 +97,7 @@ Prison has numerous placeholders, with number of different types. Each of these * **Total Available Placeholders:** 294 including aliases -* **Player Related:** 110 including aliases +* **Player Related:** 112 including aliases * **Rank Related:** 8 including aliases * **Rankup Related:** 20 including aliases * **Player Balance Related:** 8 including aliases @@ -103,7 +109,7 @@ Prison has numerous placeholders, with number of different types. Each of these * **Player Walk Speed:** 2 including aliases -* **Ladders Related:** 32 including aliases **times** each ladder +* **Ladders Related:** 34 including aliases **times** each ladder > A LADDERS placeholder must include the ladder's name in the placeholder and therefore is static. @@ -116,7 +122,7 @@ Prison has numerous placeholders, with number of different types. Each of these -* **Ranks Related:** 22 including aliases **times** each rank +* **Ranks Related:** 24 including aliases **times** each rank > A RANKS placeholder needs to specify the Rank name as part of the placeholder. Each placeholder must specify a Rank and is static. @@ -150,7 +156,7 @@ This results in a total of 107 ranks that must be collected, then the player's c * **Player Ladder Balance Related:** 32 including aliases **times** each Mine -* **Mines Related:** 32 including aliases **times** each ladder +* **Mines Related:** 28 including aliases **times** each ladder > A MINES placeholder must specify the Mine mine as part of the placeholder. @@ -174,7 +180,7 @@ This results in a total of 107 ranks that must be collected, then the player's c > Every block type that a player breaks within a mine is tracked. These provide the stats on those blocks. -* **STATSMINES Related:** 14 including aliases +* **STATSMINES Related:** 18 including aliases > These list the blocks within a mine. They are referred to with a `_nnn_` notation where "nnn" is the line number @@ -190,9 +196,17 @@ This results in a total of 107 ranks that must be collected, then the player's c +* **ONLY_DEFAULT_OR_PRESTIGES:** 4 including aliases + +> A couple of placeholders that will only include the default and prestige ladder's rank tag name. These are handy such that you only need to use the one, and it will ensure none of the other ladder's ranks will be included. + + + +* **CUSTOM:** Depends upon how many are configured on your server. + +> Custom placeholders allow for the creation of complex text that can include many other placeholders, including their placeholder attributes and other plugin placeholders. The benefit is that when using these in another plugin, you just need to use the short simple placeholder name and it will auto expand everything for you. -
@@ -204,7 +218,10 @@ There is always more than one way to do things, and the same goes for having mor **PlaceholderAPI** - [Setting up PlaceholderAPI](prison_docs_0xx_setting_up_PlaceholderAPI.md) - Strongly Suggested if using placeholders. -**Holographs** - There are actual a couple of holograph display plugins. Most of the references in this document refer to Holographic Displays, but some of the newer plugins can provide the same functionality, plus many new features. +**Holographs** and **Scoreboards** - There are actual a couple of holograph display plugins. Most of the references in this document refer to Holographic Displays, but some of the newer plugins can provide the same functionality, plus many new features. + +Some of example of other holographic plugins are: AnimatedScoreboard, DecentHolograms, Scoreboard Revision, and etc.. +
@@ -520,15 +537,230 @@ Example of this attribute's usage is as follows, using descriptions for each par
+# Prison's Custom Placeholders + + +Have you ever tried to setup one row in a scoreboard that included three or four placeholders? Did any of them include placeholder attributes? Some scoreboards even impose limits on how many characters you can use in the config settings. + +With Prison's new Custom Placeholders, you can define any number of them within the prison's `config.yml` file, and then use just the custom placeholder's short name. Prison will automatically expand all included placeholders, even non-prison placeholders. + + +
+ +### Custom Placeholder Configurations + +Prison's custom placeholders are defined in the `plugins/Prison/config.yml` file, under the grouping of `placeholder`. + + +```yaml +placeholder: + + # Custom Placeholders: + # They MUST begin with 'prison__', which has two underscores, or they will not work. + # Custom placeholders can have an abbreviated format where it is the placeholder + # with the quoted value, which can be multi-lined. + # The extended format can have additonal settings. The actual placeholder is + # paired with 'placeholder'. + # If the custom placeholder contains non-prison placeholders, then you can set + # the 'papi_expansion' to true. + # If a description is provided, it will be shown within the placeholder listing. + # Note that the use of hex colors will not work with bukkit versions prior to + # spigot 1.14. + custom-placeholders: + prison__chat_prefix: + placeholder: "{prison_rank_tag_default}{prison_rank_tag_prestiges}" + papi_expansion: true + description: "Can use this in your chat prefix. May have to use %% instead of {}." + prison__player_stats: "{prison_rank_tag_default} -> {prison_rankup_rank_tag_default} + {prison_rankup_cost_remaining_bar_default::bar:50:&a:|:&d:|} + {prison_rankup_cost_remaining_formatted_default} needed to rankup" + +# Pre-spigot 1.14: Cannot do RGB colors: + prison__branding_pre_1_14: "&2P&3r&4o &5M&6i&4n&3e&2s" + + prison__branding: "&#e81416P&#ffa500r&#faeb36o + Oc314Mǧde7ib369dn𑋡de&#ac7ad1s" + +``` + + +
+ + +### Custom Placeholders Format - Name + +A custom placeholder is only identified as a custom placeholder by the prefix of it's name. Therefore, all custom placeholders must start with `prison__`. That is two underscores. If it does not have two underscores, it will be ignored. + +The remainder of the custom placeholder's name can be any valid character combination, excluding any white space. We strongly suggest it is kept to alpha-numeric with underscores. But you may be able to use dashes, other symbols, including colons. If you try to use something other than alpha-numeric plus underscores, then do so at your own risk because other plugins, including Prison, may not handle them correctly or successfully. + + +
+ + +#### Custom Placeholders Format - Abbreviated (simple) + +The abbreviated form of a custom placeholder is simply the name of the placeholder, followed by the String value. + +Two examples are as follows, where the first is a one liner, and the other is a multi-line example. + +```yaml +placeholder: + custom-placeholders: + prison__branding: "&2P&3r&4o &5M&6i&4n&3e&2s" + prison__multi_line: "This is a simple example with + no placeholders, but it's on multiple lines + as this placeholder implies." + +``` + +Please note that multi-line String values wraps to the next line, indented two character more than the placeholder's name. + + +
+ + +#### Custom Placeholders Format - Expanded (complex) + +The complex form of a custom placeholder has at least one attribute, and potentially other settings that can expand the functionality of a placeholder. + +**placeholder** attribute - This contains the actual placeholder String value. It can be multiple lines in length, and can have none, or many other placeholders in it. + +**papi_expansion** attribute - Defaults to a value of `false`. If this value is `true`, then after prison expands all prison placeholders, Prison will then have PAPI expand all non-prison placeholders. If a non-prison placeholder is used in the abbreviated placeholders, or if this one is set to `false`, then it will be ignored and you may see it displayed in the final text. + +**description** attribute - This is a description of the custom placeholder, which is optional. It is ONLY displayed in the placeholder listings: `/prison placeholders list` + + +Two examples are as follows, where the first is a one liner, and the other is a multi-line example. + +```yaml +placeholder: + custom-placeholders: + prison__branding: "&2P&3r&4o &5M&6i&4n&3e&2s" + prison__chat_prefix: + placeholder: "{prison_rank_tag_default}{prison_rank_tag_prestiges}: &3{player}:&r" + papi_expansion: true + description: "Can use this in your chat prefix. May have to use %% instead of {}." + +``` + +Please note that multi-line String values wraps to the next line, indented two character more than the placeholder's name. + + +
+ + + +# Prison Command Placeholders - Mines, Ranks, Ladders, and Block Commands + +This document is not intended to cover Prison command placeholders, but within Prison there are many areas where you can setup commands. Each of them have their own set of placeholders. Prison supports many placeholders to allow you to better customize command. + +The commands can contain more than one command. Keep them all on one line, but end each command with a semi-colon: `;`. + + +To see the list of placeholders, most commands have command parameter that will show all of them. This is a list of all of these commands, and their related placeholders. Please run these commands in the console, for yourself, to confirm that there have not been any new updates since this document was last updated. + +Keep in mind that the use of these placeholder are very strict. They include the curly braces, and they must be in case in which they are listed. + +`/ranks command add placeholders` + +**{player} {player_uid} {msg} {broadcast} {title} {actionBar} {inline} {inlinePlayer} {sync} {syncPlayer} {range: } {ifPerm:} {ifNotPerm:} {firstJoin} {promote} {demote} {balanceInitial} {balanceFinal} {currency} {originalRankCost} {rankupCost} {ladder} {rank} {rankTag} {targetRank} {targetRankTag}** + +`/ranks ladder command add placeholders` + +**{player} {player_uid} {msg} {broadcast} {title} {actionBar} {inline} {inlinePlayer} {sync} {syncPlayer} {range: } {ifPerm:} {ifNotPerm:} {firstJoin} {promote} {demote} {balanceInitial} {balanceFinal} {currency} {originalRankCost} {rankupCost} {ladder} {rank} {rankTag} {targetRank} {targetRankTag}** + +`/mines command add placeholders` + +**{player} {player_uid} {msg} {broadcast} {title} {actionBar} {inline} {inlinePlayer} {sync} {syncPlayer} {range: } {ifPerm:} {ifNotPerm:}** + +`/mines blockevent add placeholders` + +**{player} {player_uid} {msg} {broadcast} {title} {actionBar} {inline} {inlinePlayer} {sync} {syncPlayer} {range: } {ifPerm:} {ifNotPerm:} {blockName} {mineName} {locationWorld} {locationX} {locationY} {locationZ} {coordinates} {worldCoordinates} {blockCoordinates} {blockChance} {blockIsAir} {blocksPlaced} {blockRemaining} {blocksMinedTotal} {mineBlocksRemaining} {mineBlocksRemainingPercent} {mineBlocksTotalMined} {mineBlocksSize} {blockMinedName} {blockMinedNameFormal} {blockMinedBlockType} {eventType} {eventTriggered} {utilsDecay}** + + -# Rank Command Placeholders +#### Prison Command Placeholder Descriptions -The Rank Commands recognize only two placeholders, but they are not considered part of the standard placeholders. There are also only two placeholders that are recognized and both are case sensitive (must be lower case), and must also include curly braces too. +Detailed information on what exactly each of these placeholders do, is not intended to be a part of this document. But the following is a brief description. + +Additional information on the BlockEvent placeholders can be found in the [BlockEvent documentation](prison_docs_115_using_BlockEvents.md). + +If a placeholder is marked with **Non-Positional**, that means that the placeholder can appear anywhere in the command to trigger the effect. It's non-positional since it's removed when detected, therefore when the command is ran, it will not be encountered. + + +* **{player}** - The player's name. +* **{player_uid}** - The player's UUID. +* **{msg}** - Send a message to the player. The message follows this placeholder. +* **{broadcast}** - Broadcast a message to all players on the server. +* **{title}** - Send a message to the player, but show in the screen's title region. +* **{actionBar}** - Send a message to the player, but show in the action bar. + + +* **{inline}** - Run the command "inline" with the processing of the original prison command, but run as console. **Non-Postional.** +* **{inlinePlayer}** - Run the command "inline" with the processing of the original prison command, but run the command as the player. **Non-Postional.** +* **{sync}** - Submit the command to run in a synchronous thread at the first opportunity. This runs the command as console. Since the command is submitted, it may have to wait behind other tasks. **Non-Postional.** +* **{syncPlayer}** - Submit the command to run in a synchronous thread at the first opportunity. This runs the command as the player; if the player does not have access to run the specified command, then it will fail. Since the command is submitted, it may have to wait behind other tasks. **Non-Postional.** + + +* **{range: }** - This is a global placeholder that will insert an integer value that is randomly selected from the specified range from to , inclusive of the high value. So `{range: 5 7}` would have possible values of 5, 6, and 7. These randomly selected values are not weighted and may not present an even distribution. Negative values are also supported too. + + +* **{ifPerm:};** - Runs the commands that follows this placeholder, only if the player has the specified permission. NOTE: In order for this to work properly, it must be immediately be followed by a semi-colon so it's treated as it's own "command". +* **{ifNotPerm:};** - Runs the commands that follows this placeholder, but only if the player DOES NOT have the specified permission. NOTE: In order for this to work properly, it must be immediately be followed by a semi-colon so it's treated as it's own "command". + + +* **{firstJoin}** - Runs the commands that follows this placeholder, only if the rankup is based upon first join. This protects the commands that follows from being ran each time when the player hits the specified rank in the future. Example would be Rank A's command such that it runs on first join, but it will not run when the player prestiges and they are set back to A on the default ladder. **Non-Positional.** + + +* **{promote}** - This runs the command only on promotions such as rankup, promote, and setRank. **Non-Positional.** +* **{demote}** - This runs the command only on demotions such as demote. **Non-Positional.**c + + +* **{balanceInitial}** - The player's balance before the rankup event was ran. +* **{balanceFinal}** - The player's balance after the rankup event was ran. +* **{targetRank}** - The next rank's name. +* **{targetRankTag}** - The next ranks's tag value. +* **{currency}** - If the rank is using a different currency, then this parameter would provide the name of that currency. +* **{originalRankCost}** - The rank cost for ranking up, but without the global rank cost multipliers. +* **{rankupCost}** - The rank cost for ranking up, including the global rank cost multipliers. +* **{ladder}** - The current ladder name. +* **{rank}** - The current rank name. +* **{rankTag}** - The current rank's tag value. + +* **{blockName}** - The name of the block that was mined. +* **{mineName}** - The mine where the block was mined. +* **{locationWorld}** - The world name where the mine exists. + + + +* **{locationX}** - The **X** coordinates for the broken block. This is an integer value. +* **{locationY}** - The **Y** coordinates for the broken block. This is an integer value. +* **{locationZ}** - The **Z** coordinates for the broken block. This is an integer value. + + +* **{coordinates}** - This provides the X, Y, and Z coordinates for the broken block. These are double values, surrounded by parenthesis and separated by commas. Format: **(X,Y,Z)** Example: `(183.2,88.3792,-3828.248)` +* **{blockCoordinates}** - This is similar to the **{coordinates}** placeholder, except for the use of integer values. Format: **(blockName,world,X,Y,Z)** Example: `(,prisonWorld,183,88,-3828)` +* **{worldCoordinates}** - This combines both the **{locationWorld}** and **{blockCoordinates}** placeholder in to one placeholder. The coordinates are integer values. Format: **(world,X,Y,Z)** Example: `(prisonWorld,183,88,-3828)` + + +* **{blockChance}** - For the block type that was mined, what was the chance of it's spawn rate. +* **{blockIsAir}** - Indicates if the block being processed was AIR. This could be true if an included block within an explosion was already replaced with AIR. +* **{blocksPlaced}** - +* **{blockRemaining}** - +* **{blocksMinedTotal}** - +* **{mineBlocksRemaining}** - +* **{mineBlocksRemainingPercent}** - +* **{mineBlocksTotalMined}** - +* **{mineBlocksSize}** - +* **{blockMinedName}** - +* **{blockMinedNameFormal}** - +* **{blockMinedBlockType}** - +* **{eventType}** - This contains the name of the event that prison is handling. This is an internal event name as specified by Prison. +* **{eventTriggered}** - If Prison was handling a multi-block event, such as an explosion, and if that event supports identifying what triggered it, then this will contain that information. Example could be what enchantment was used to produce the explosion, or the name of the potion, etc. +* **{utilsDecay}** - -* {player} -* {player_uid} This is mentioned here since these rank command placeholders are not part of all the other placeholders, so as such, it may be difficult to find information for these items. @@ -540,7 +772,8 @@ This is mentioned here since these rank command placeholders are not part of all -

Prison Placeholder Command Listing

+# Prison Placeholder Command Listing + Prison Placeholder Commands diff --git a/docs/prison_docs_311_guide_automanager.md b/docs/prison_docs_311_guide_automanager.md index 78c9e2404..f4f322084 100644 --- a/docs/prison_docs_311_guide_automanager.md +++ b/docs/prison_docs_311_guide_automanager.md @@ -12,23 +12,60 @@ See below for information on:
-# Auto Manager +# Auto Manager, Auto Features -AutoManager is Prison's block handler. It provides support for breaking blocks within mines, auto pickup, normal drops, fortune, mine access, block events, auto-sell, and many other features. Auto Manager has been one of the most enhanced features of Prison, and what it is capable of doing is probably more that what has been documented in this document due to the complexities involved, and the number of new features added that have not made it to this document. +AutoManager is Prison's block handler. It's also referred to as Auto Features, mostly because of the name of the config file. It provides support for breaking blocks within mines, auto pickup, normal drops, fortune, mine access, block events, auto-sell, and many other features. Auto Manager has been one of the most enhanced features of Prison, and what it is capable of doing is probably more that what has been documented in this document due to the complexities involved, and the number of new features added that have not made it to this document. Extensive work has been done with auto manager to improve the performance, and to extend the compatibility with other plugins. Many plugins have direct support (Auto Manager has event listeners for their custom events), but prison has been modified to work with many plugins that do not provide custom events too. +The configuration file for the auto features is: `plugins/Prison/autoFeaturesConfig.yml`. + + +*Documented updated: 2024-09-02* + +
+ + +# Canceling by Event or by Drops + +Perhaps one of the most important items to setup correctly is how prison should cancel the events or cancel the drops. + +These two settings are: + +`options.blockBreakEvents.cancelAllBlockBreakEvents: false` +`options.blockBreakEvents.cancelAllBlockEventBlockDrops: true` + + +For spigot versions 1.8.x through v1.11.x it's a moot point, since the only option is cancel by event. If you try to cancel by drops it will mess up your server, so don't do it. + +If you are using spigot v1.12.x or higher (paper and other flavors included), then you should almost always use cancel by drops. There may be a few situations where you may need to cancel the events, but that maybe due to other plugins not being written correctly to handle canceled drops. This would be more of an issue for plugins that have been written for spigot versions less than 1.12 or around 1.12's release. Modern plugins properly handle the cancel by drops. + + +Canceling by drops is where prison will change the drops on an event so the drops are empty. No drops. That way other plugins can properly handle the event, and get access to which block (or blocks) are part of the event, but using bukkit's `getDrop()` function will result in zero items. This will prevent double or triple drops for each block being broken. Some of the older plugins would ignore the `getDrops()` function and would generate their own drops incorrectly. + + +By using Canceling by drops, this can allow prison to be one of the lowest priority listeners on the event, and handle the block breakage and the drops, but then allow all the other plugins to properly handle the event too. If they honor the zero drops, then those other plugins can behave as if prison was not even there. Hence prison can seamlessly work with almost any plugin. But as you can imagine, not all plugins are created equally, and not all handles the events in the same way either. It's not to say they are wrong in how they handle the event, it's just that they have different requirements and expectations, and it's those perspectives that gives their plugins a unique appeal for everyone wanting to use them. + + +In general, there isn't much variation in how to setup this setting. It's either cancel by event for older versions of bukkit(paper), or by drops for all the newer versions. But once in a while this can be a significantly important setting to get correct for your environment. + + +Prison currently allows both of these settings to be set with the same value. It may give warnings in the console, but it will allow it happen. And if it does, then things will never work correctly. So never, ever, set them to the same values. I've been tempted to create a new setting that will replace these two settings, and the values would be something more obvious and clear, such as `CANCEL_BY_EVENT` or `CANCEL_BY_DROPS`. This could eliminate the rare situation where both settings are set to the same value. + -*Documented updated: 2023-02-28*
+ # Auto Manager Event Listener Priorities Prison listens to a number of block break event types, and each one can be enabled or disabled. By enabling these listeners, any combination of priorities can be applied to any of the listeners. These priorities cover the standard Bukkit priorities (LOWEST to HIGHEST, plus MONITOR), but also has custom Prison priorities to extend the behaviors. -At this time, these event listeners only apply within mines. In the near future they may be extended to work outside of mines and in other worlds too, but for now, they are only Prison mine specfic. +At this time, these event listeners only apply within mines. In the near future they may be extended to work outside of mines and in other worlds too, but for now, they are only Prison mine specific. + +These priorities are tied to the parameters that are under the path of: +`options.blockBreakEvents.` Valid values for the priorities are: @@ -50,21 +87,73 @@ Valid values for the priorities are: - `ACCESSBLOCKEVENTS` - Same as `ACCESS` but adds a second listener to the stack for a `BLOCKEVENTS` priority too. So this generates two listeners; see both `ACCESS` and `BLOCKEVENTS`. +NOTE that the standard bukkit priorities are: LOWEST, LOW, NORMAL, HIGH, HIGHEST, and MONITOR. Prison extends those basic priorities to provide variations in how it will respond. Some of the custom priorities will actually enable two monitors, such as the ACCESSMONITOR where it uses LOWEST for prison access features, and then MONITOR to record block breakage. + +
+ + +# Event Processor Handling - Sync Tasks for Breaking Blocks + +Prison is capable handling the processing of breaking the blocks in two different ways. It can handle it "inline" or by running it in another sync task which could speed up reactions times. + +Also see the section **Sync Tasks for Breaking Blocks** below for more information. + + +The config setting is in the same block as the other event listeners: +`options.blockBreakEvents.applyBlockBreaksThroughSyncTask: true` -Valid event listeners are as follows, including their default values. Any of the above Prison priorities can be used with the following: +The value of `true` is the default value. + +The concept of this feature is to take an expensive part of the block break handling, the actual breaking of the blocks, and run it in another sync task thread so the original event can be freed up and continue to allow other plugins to process it. The reason why it can be expensive is because the block breakage must run in the synch task (only one sych task thread on a server, and it's the primary thread at that). And it will make changes to the world, which will in turn trigger chunk saving. If it crosses the boundaries of multiple chunks, then it could add more delays. The chunks should be preloaded because the player is already in the area, unlike a mine reset which may have no players in the region. + +This setting is very important. It saves some time, but what makes it important is that on some servers, with higher loads with less resources to process them (cores, cpu, clock frequencies, etc) it can appear like it is causing lag. It actually does not cause lag, but because there could be a slight delay from when the processing of the event happens, and when the blocks are actually broken, that delay could be more obvious. If this is the situation, then just set this value to `false` and force the block breakage to happen while the thread is still processing the event. + + + + +# Event Listeners and Event Priorities + + +The event listeners, and their related event priorities are under the path of: +`options.blockBreakEvents.` + + +Valid event listeners are as follows, including their default values. Any of the above Prison priorities can be used with the following. Pay careful attention to the parameter name and which enchantment plugin it supports since some of the parameter names have become confusing since they are similar to each other (it's too late to change them now, since it will break existing configs). + + + + + +- `blockBreakEventPriority: LOW` - This applies to the 'org.bukkit.BlockBreakEvent' and is the primary way Prison deals with standard block events. There may be some situations where prison would need to DISABLE this listener. All other enchantment plugins MUST also listen to this event too, so it can become complicated on how to properly configure. +- `entityExplodeEventPriority: LOW` - This applies to the 'org.bukkit.event.entity.EntityExplodeEvent'. This is the multi-block explosion event that bukkit has always used for creepers and probably TNT too. But this is also used by the enchantment plugin ExcellentEnchants, and probably others too. + + The only problem with this event, and a few others listed here, is that it does not identify what the initial block was that triggered this event. Prison uses the first block to identify which mine the explosion is in, and if the player has access. This potentially becomes a problem if the player break a block on the edge of the mine, but the first block in this list of blocks is outside the mine; prison will reject the whole explosion event. -- `blockBreakEventPriority: LOW` - This applies to the org.bukkit.BlockBreakEvent and is the primary way Prison deals with standard block events. There may be some situations where prison would need to DISABLE this listener. - `ProcessPrisons_ExplosiveBlockBreakEventsPriority: LOW` - This is the event that must be enabled for Prison Mine Bombs to work. Other plugins may also use this Prison multi-block explosion event too. + - `TokenEnchantBlockExplodeEventPriority: DISABLED` - For TokenEnchant (premium) + - `CrazyEnchantsBlastUseEventPriority: DISABLED` - For CrazyEnchant (open source) + - `RevEnchantsExplosiveEventPriority: DISABLED` - For RevEnchants ExplosiveEvent (premium) - `RevEnchantsJackHammerEventPriority: DISABLED` - For RevEnchants JackHammerEvent (premium) - `ZenchantmentsBlockShredEventPriority: DISABLED` - For ZenChantments (open source) -- `PrisonEnchantsExplosiveEventPriority: DISABLED` - Pulsi's Plugin - (Premium and free... not currently in active development for at this time) +- `PrisonEnchantsExplosiveEventPriority: DISABLED` - Pulsi's Plugin - (Premium and free) Prison supports all version of Pulsi's plugin. + + +- `XPrisonExplosionTriggerEventPriority: DISABLED` (discontinued premium) +- `XPrisonLayerTriggerEventPriority: DISABLED` +- `XPrisonNukeTriggerEventPriority: DISABLED` + + Prison supports XPrison's enchantments. So if you were using XPrison, and you move over to prison, you can continue to use XPrison's enchantment tools. If you have them setup and they are still working well for you, you might as well keep using them since it can be very difficult to reconfigure enchantments in another plugin. + + +NOTE: Prison currently supports importing mine configurations from JetPrisonMines. Visit our discord server and talk to Blue if you would like prison to import from other plugins; it may not be possible, but it also could be. -Do not enable any event listener if you are not using that plugin. Doing so will not contribute to lag, but it will try to setup a useless event listener that could delay startup, and consume a little more memory. + +Do not enable an event listener if you are not using that plugin. Doing so will not contribute to any lag, but it will try to setup a useless event listener that could slightly delay startup while trying to detect that plugin. Overall, if you try to enable a plugin event that you do not have setup on your server, it's not a big deal and prison will ignore them. @@ -74,6 +163,12 @@ Do not enable any event listener if you are not using that plugin. Doing so wil # Sync Tasks for Breaking Blocks +NOTE: This is additional information on the following setting. See the section above titled **Event Processor Handling - Sync Tasks for Breaking Blocks**: +`options.blockBreakEvents.applyBlockBreaksThroughSyncTask: true` + +The value of `true` is the default value. + + Prison is trying its best to optimize performance so your server will have the best experience with no lag. In order to provide the best performance, some features do not always work the best on all servers due to memory limitations, processor performance, huge number of plugins, or almost any other variable which is outside of the control of Prison. Therefore, there are some performance features that work really well on some servers, but not on others. This is not a "problem" with any specific plugin, or server, but it's an expected behavior because all servers are different and they can perform in very different ways based upon configurations. One way Prison is able to improve performance when breaking blocks, is to process as much as it can within the block break events, except for breaking the actual blocks, and for that, prison submits a task that performs the actual block breakage. Since the act of breaking the blocks can be considerably slower than performing the calculations that lead up to the block breakage, it has been shown that by submitting the breakage as a task will improve the overall performance when you have very high over powered tools, and when there are many players online mining. @@ -88,6 +183,7 @@ This feature can be turned off with a simple setting change. The following is t
+ # Auto Manager's Canceling the Event vs. Canceling the Drops Prison's primary way of dealing with BlockBreakEvents, and other block events, has always been done by the canceling the event. @@ -156,7 +252,7 @@ options: # Prison's Auto Manager - Setting Up and Enabling Other Plugins -Prison's Auto Manger deals with the whole block breaking events. It's able to provide advanced features such as auto pickup, auto smelt, and auto block, along with providing the player with XP, applying OP fortune, plus many other features. All with maintaining full compatibility from Spigot v1.8 through Spigot v1.16. +Prison's Auto Manger deals with the whole block breaking events. It's able to provide advanced features such as auto pickup, auto smelt, and auto block, along with providing the player with XP, applying OP fortune, plus many other features. All with maintaining full compatibility from Spigot v1.8 through Spigot v1.21.x Auto Manager is a very complex "process" and as a result, there are many features that can be configured, and many possible interactions with other plugins. Needless to say, there are many things that can go wrong, especially when it may not be configured correctly. diff --git a/docs/prison_docs_626_configuring_worldguard_regions.md b/docs/prison_docs_626_configuring_worldguard_regions.md index 5eb5c9347..145783c2f 100644 --- a/docs/prison_docs_626_configuring_worldguard_regions.md +++ b/docs/prison_docs_626_configuring_worldguard_regions.md @@ -10,13 +10,294 @@ This document explains how to setup WorldGuard to protect your mines and how to The preferred way is with using **Access by Ranks**, but other alternative techniques are also included in this document, but some may not be supported (read carefully). It also explains how to setup the permissions in the Prison's **/ranks command add +# WorldGuard Regions, WorldEdit, Permission PLugins, and Prison + +Initially, Prison did not have any direct support for WorldGuard, but it used WorldGuard regions to control access to the mines. Getting WorldGuard properly configured was the admin's responsibility, but yet we would spend a huge number of hours trying to help many people new to WorldGuard try to figure out how to get everything working properly. This also included having to have a working understanding of a few WorldEdit selection commands, and a moderate understanding of how permissions worked, including a good understanding of your perms plugin. All of these plugins, and their related commands, had to be crafted in Prison rankup commands to provide a controlled adjustments when a player is ranking up. All of this was complex with way too many moving parts. Of course, with many new people exploring setting up their first minecraft server, there was a large learning curve, and we helped many people figure it out. + +Helping with WorldGuard, or a perms plugin, was not ideal, because that prevented us from working on prison to allow it to grow and become a more enhanced plugin. So we had to find a way to move on from a harsh dependency upon WorldGuard. + +Enter Prison's **Access by Ranks**. This shift the focus from WorldGuard to allowing Prison to self-manage access to the mines through a player's ranks. On the surface, this simplified a lot of things because Prison no longer had to depend upon WorldGuard regions. This holds true for today even, but it's not that simple when you start to try to add enchantment plugins, because they still rely on WorldGuard regions. + +This document was initially created when WorldGuard Regions were the only way to control access. As things evolved, this document really only provided "hints" to working with WorldGuard for the sake of other plugins. Prison still needs to provide hooks to help with ranking up, but with LuckPerm tracks, the complexity within prison has greatly been reduced. + +There is a dedicated document related to [LuckPerms Groups & Tracks](prison_docs_030_LuckPerms_Groups_Tracks.md) (*[prison_docs_030_LuckPerms_Groups_Tracks.md](prison_docs_030_LuckPerms_Groups_Tracks.md)*), and how to set them up to work with prison. Please review that document if needed. + + +
+ +# Prison's New Support for WorldGuard Regions + +This support is a new work in progress. Some features may not fully work, or may not be well documented. These features were initially introduced with version *3.3.0-alpha.19c*. + +WorldGuard region support, within Prison, is through the mines commands, since they are physically associated with mines and their physical locations in the worlds. + +Prison does not understand WorldGuard Regions and there is no way to teach it either. This is true because everyone may want to use regions in a different way, with different setup of perms, groups, and flags. So Prison cannot force our limited experience upon everyone else. Trust me on this, we know Prison, but may not know anything about the other plugins that you are trying to use. + +To provide you with the ultimate control for Prison's use of WorldGuard regions, we will allow the best expert to control everything. Who is that expert? It's you! Yes... You. + +This way, if prison is not configured properly with it's use of WorldGuard regions, you can customize any way you want, and Prison will obey. If you're new to WorldGuard regions, then we have you covered because we provide a simplified way we would use WorldGuard to interact with just Prison. As you learn more, or encounter more complex needs, then you can customize everything to suite your needs. + +But the important thing to realize, is that you're in control, and you can customize anything you want. + + +How is this possible? + +It's easy... In the file `plugins/Prison/config.yml` are various WorldEdit and WorldGuard scripts setup under different commands. So when a prison command is ran, prison takes those scripts and replaces the provided placeholders and then displays the commands in the console. You can do whatever you want with them at that point, such as **view**ing them or copying a pasting them in to your game's console so they can be applied. + +Prison also has the feature where you can **run** them through a player that is online. The way that works, is that the player must be in game, and then prison will teleport them to the mine to ensure they are in the correct world. Then prison will run the specified commands as that player. Therefore, the commands use the implied world and Prison injects all of the mine specific settings. + +This makes it simple. But yet there is still a lot of lack of automation because this requires a player to be online in the game. Why does the player have to be in the game? WorldEdit. Because WorldEdit does not provide a way to specify a target world on some of their commands, such as `//pos1` and `//pos2`, which is the primary way to set a regions area through the use of x,y,z coordinates. Sucks doesn't it? If this was not a limitation, then it would be trivial to script everything. + +
+ + +# Running the Prison Mines WorldGuard Region commands + +These new commands are located under this command, which will list all available commands: +`/mines worldGuard region` + +``` +>mines worldguard region +[INFO]: ----- < Cmd: /mines worldguard region > ------- (3.3.0-alpha.19c) +[INFO]: /mines worldguard region +[INFO]: Subcommands: +[INFO]: /mines worldguard region globalDefine [playerName] [options] +[INFO]: /mines worldguard region globalInfo [playerName] [options] +[INFO]: /mines worldguard region globalMobSpawningDeny [playerName] [options] +[INFO]: /mines worldguard region mineAreaDefine [mineName] [playerName] [options] +[INFO]: /mines worldguard region mineAreaInfo [mineName] [playerName] [options] +[INFO]: /mines worldguard region mineAreaRedefine [mineName] [playerName] [options] +[INFO]: /mines worldguard region mineAreaSelect [mineName] [playerName] [options] +[INFO]: /mines worldguard region mineDefine [mineName] [playerName] [options] +[INFO]: /mines worldguard region mineInfo [mineName] [playerName] [options] +[INFO]: /mines worldguard region mineRedefine [mineName] [playerName] [options] +[INFO]: /mines worldguard region mineSelect [mineName] [playerName] [options] +``` + +
+ +# Prison's config.yml settings + +In the file `plugins/Prison/config.yml`, under the settings of `prison-mines.world-guard` are the configs. They are numerous. They will be listed at the end of this section. But first let me explain a few things. + +All of the scripts are grouped under a command header. This allows full customization and helps organize each command. + +The scripts are stored in an array of Strings, so they must be quoted (yaml actually will allow you not to quote them, but we advise you use quotes). And you can have as many as you want for each command. We do not impose limitations. + +Prison uses placeholders in these commands, so some commands have placeholders that will be removed and nothing will be inserted in their place. This is how it's designed to work. And that is also why it is important to understand why the placeholders are used, what they do, and why you need to use them. At this time, mine areas are not supported, but they have been added so as to be ready for this support when they are added. + + +| Placeholder | Description | Notes | +| :--- | :--- | ------------------- | +| {world} | Inserts the world name | When ran from the console, many commands must include `-w worldName`. Prison will inject this as needed, and only when the commands are viewed or ran from the console. | +| {mine-pos1} | One corner of the mine | Prison inserts the `x,y,z` coordinates for the first position. | +| {mine-pos2} | The other corner of the mine | Prison inserts the `x,y,z` coordinates for the second position.| +| {region-mine-name} | The generated region name to use | This is configured under `prison-mines.world-guard.region-mine.region-mine-name`. | +| {region-group-permission} | The generated group permission name to use | This is configured under `prison-mines.world-guard.region-mine.region-group-permission`. | +| {mine-area-pos1} | One corner of the mine area | Prison inserts the `x,y,z` coordinates for the first position. | +| {mine-area-pos2} | The other corner of the mine area | Prison inserts the `x,y,z` coordinates for the second position.| +| {region-mine-area-name} | The generated region name to use | This is configured under `prison-mines.world-guard.region-mine-area.region-mine-name`. | + + + +
+ +## WorldGuard Region Scripts - Examples + +If your `config.yml` file does not contain these entries, you can copy and paste them from this document. + +But the actual preferred method would be to allow prison to regenerate the `config.yml` file. This can be achieved by renaming config.yml to something else, restart the server, then prison will generate one, and then you can shut down the server, rename the original and copy and paste what you need. Yeah this is a bit of a messy way of doing it, but this ensures you have the latest published version of these settings. + + +```yaml +prison-mines: + + world-guard: + WARNING: WorldGuard may not be fully supported yet. + + global-region-commands: + info: + - '/rg list {world}' + - '/rg info {world} __global__' + define: + - '/rg flag {world} __global__ passthrough deny' + deny-mob-spawning: + - 'rg flag {world} __global__ mob-spawning deny' + - '/gamerule doMobSpawning false' + mine-region-commands: + info: + - '/rg list {world}' + - '/rg info {world} {region-mine-name}' + redefine: + - '//pos1 {mine-pos1}' + - '//pos2 {mine-pos2}' + - '//region redefine {world} {region-mine-name}' + define: + - '/region define {world} {region-mine-name}' + - '/region addmember {world} {region-mine-name} {region-group-permission}' + - '/region setpriority {world} {region-mine-name} 20' + - '/region flag {world} {region-mine-name} block-break allow' + - '/region flag {world} {region-mine-name} item-pickup allow' + - '/region flag {world} {region-mine-name} exp-drops allow' + - '/region flag {world} {region-mine-name} item-drop allow' + select: + - '/region select {world} {region-mine-name}' + + mine-area-region-commands: + info: + - '/rg list {world}' + - '/rg info {world} {region-mine-area-name}' + redefine: + - '//pos1 {mine-area-pos1}' + - '//pos2 {mine-area-pos2}' + - '/region redefine {world} {region-mine-area-name}' + define: + - '/region define {world} {region-mine-area-name}' + - '/region addmember {world} {region-mine-area-name} {region-group-permission}' + - '/region setpriority {world} {region-mine-area-name} 10' + - '/region flag {world} {region-mine-area-name} block-break deny' + - '/region flag {world} {region-mine-area-name} item-pickup allow' + - '/region flag {world} {region-mine-area-name} exp-drops allow' + - '/region flag {world} {region-mine-area-name} item-drop allow' + select: + - '/region select {world} {region-mine-area-name}' + + region-mine: + enable: true + region-mine-name: 'prison_mine_{mine}' + region-group-permission: 'g:prison.mines.{mine}' + region-mine-area: + enable: false + region-mine-area-name: 'prison_mine_area_{mine}' + increase-x: 15 + increase-z: 15 + increase-y: 9999 + +``` + +Please note that `mine-area-region-commands`, `region-mine-area`, and mine areas in general, are not yet implemented in prison, and are not currently used. + + +
+ +# WorldGuard Help + +Let's be honest, it's not always easy to get all plugins properly configured and working with each other as we may envision our servers. Plus, when access is being controlled by another plugin, such as WorldGuard and LuckPerms, it makes things even more complicated, especially when it's your first time working with these tools and plugins. + +Generally, googling with specific problems helps, but since Spigot, WorldGuard, and LuckPerms has been out for so many years, sometimes the suggested search results are not exactly what your plugin versions need, or they can be just flat-out bad advice. So as a suggestion, look at when your version of plugins were released and then compare those release dates to the time stamps that google sometimes provides (they don't always tell you how old a post is). This is important if you're running Spigot 1.8.8 and using WG v6.x. That old version is not supported by WG support anymore, so you won't get live help from them. But don't give up, solutions usually exist and you will find them if you keep looking. + +One general challenge to getting Prison to work with WorldGuard when using it with BlockBreakEvents, are the priorities of the event listeners. To help with these kind of issues of who is canceling, or denying access to my mines!? Prison has some tools you can use to help debug which plugin is doing what to the BlockBreakEvents. + +`/prison support listeners blockBreak` + +This lists all block-break events that Prison is enabled to listen for (see the `autoFeaturesConfig.yml` file for enabling others if needed). And it shows their priorities. This alone can be very helpful in understanding which plugins before Prison my be denying the access to a mine (canceling the event). + +These reports can become pretty complex, especially if there are many events that prison has been setup to listen to. + +``` +> prison support listeners blockbreak +[INFO]: PEExplosionEvent: org.bukkit.event.HandlerList +[INFO]: ||Listeners blockBreak||-- < Event Dump: BlockBreakEvent (LOW) > ---- (3.3.0-alpha.19c) +[INFO]: All registered EventListeners (15): +[INFO]: . Plugin: ExcellentEnchants LOWEST (su.nightexpress.excellentenchants.registry.wrapper.WrappedEvent) +[INFO]: . Plugin: FastAsyncWorldEdit LOWEST (com.fastasyncworldedit.bukkit.listener.ChunkListener9) +[INFO]: . Plugin: ExcellentEnchants LOW (su.nightexpress.excellentenchants.registry.wrapper.WrappedEvent) +[INFO]: . Plugin: Prison LOW (tmps.ae.AutoManagerBlockBreakEvents$AutoManagerBlockBreakEventListener) +[INFO]: . Plugin: ExcellentEnchants NORMAL (su.nightexpress.excellentenchants.registry.wrapper.WrappedEvent) +[INFO]: . Plugin: WorldGuard NORMAL (com.sk89q.worldguard.bukkit.listener.EventAbstractionListener) +[INFO]: . Plugin: WorldGuard NORMAL (com.sk89q.worldguard.bukkit.listener.EventAbstractionListener) +[INFO]: . Plugin: PrisonEnchants NORMAL (me.pulsi_.prisonenchants.listeners.customEnchantListener.CustomEnchantListenerNormal) +[INFO]: . Plugin: Prison NORMAL (tmps.SpigotListener) +[INFO]: . Plugin: ExcellentEnchants HIGH (su.nightexpress.excellentenchants.registry.wrapper.WrappedEvent) +[INFO]: . Plugin: WorldGuard HIGH (com.sk89q.worldguard.bukkit.listener.WorldGuardBlockListener) +[INFO]: . Plugin: ExcellentEnchants HIGHEST (su.nightexpress.excellentenchants.registry.wrapper.WrappedEvent) +[INFO]: . Plugin: ExcellentEnchants HIGHEST (su.nightexpress.excellentenchants.enchantment.impl.armor.FlameWalkerEnchant) +[INFO]: . Plugin: Essentials HIGHEST (com.earth2me.essentials.signs.SignBlockListener) +[INFO]: . Plugin: ExcellentEnchants MONITOR (su.nightexpress.excellentenchants.registry.wrapper.WrappedEvent) +[INFO]: NOTE: Prison's Block-Event Listeners: +[INFO]: . . Prison Internal BlockBreakEvents (non-auto features): tmps.SpigotListener +[INFO]: . . Auto Features: tmps.ae.AutoManagerBlockBreakEvents$*] +[INFO]: . . Prison Abbrv: 'tmps.' = 'tech.mcprison.prison.spigot.' & 'tmps.ae.' = 'tmps.autofeatures.events.' +[INFO]: < Event Dump: Pulsi_'s PEExplosionEvent (NORMAL) > (3.3.0-alpha.19c) +[INFO]: All registered EventListeners (1): +[INFO]: . Plugin: Prison NORMAL (tmps.ae.AutoManagerPrisonEnchants$AutoManagerPEExplosiveEventListener) +[INFO]: < Event Dump: ExplosiveBlockBreakEvent (LOW) > (3.3.0-alpha.19c) +[INFO]: All registered EventListeners (1): +[INFO]: . Plugin: Prison LOW (tmps.ae.AutoManagerPrisonsExplosiveBlockBreakEvents$AutoManagerExplosiveBlockBreakEventListener) +[INFO]: < Event Dump: EntityExplodeEvent (LOW) > (3.3.0-alpha.19c) +[INFO]: All registered EventListeners (8): +[INFO]: . Plugin: Essentials LOW (com.earth2me.essentials.signs.SignEntityListener) +[INFO]: . Plugin: Essentials LOW (com.earth2me.essentials.TNTExplodeListener) +[INFO]: . Plugin: Prison LOW (tmps.ae.AutoManagerEntityExplodeEvents$AutoManagerEntityExplodeEventListener) +[INFO]: . Plugin: ExcellentEnchants NORMAL (su.nightexpress.excellentenchants.enchantment.impl.tool.BlastMiningEnchant) +[INFO]: . Plugin: ExcellentEnchants NORMAL (su.nightexpress.excellentenchants.enchantment.impl.armor.FlameWalkerEnchant) +[INFO]: . Plugin: WorldGuard NORMAL (com.sk89q.worldguard.bukkit.listener.EventAbstractionListener) +[INFO]: . Plugin: PrisonEnchants NORMAL (me.pulsi_.prisonenchants.listeners.EntityListener) +[INFO]: . Plugin: WorldGuard HIGH (com.sk89q.worldguard.bukkit.listener.WorldGuardEntityListener) +> +``` + +Prison also has a debug mode that allows debugging of an actual block breakage event, and inspects what each plugin does with that event. + + +You can enable it with: +* `/prison debug` (run in console: enables debug mode in prison) +* `/mines wand ` (run in game: gives your admin charater a mine wand) +* `` on a block (sneak click with your right mouse button to trigger the event) + + +The details will be printed to the console. To turn off Prison's debug mode: `/prison debug` + + +``` +[INFO]: Transaction log: RoyalBlueRanger multiplier: 1.00 ItemStacks: 1 ItemCount: 1 TotalAmount: 45.00 [raw_gold:1:45.00] +[INFO]: ### ** handleBlockBreakEvent ** ### (event: BlockBreakEvent, config: LOW, priority: LOW, canceled: FALSE) EventInfo: results_passed RoyalBlueRanger Mine: blue_a GOLD_ORE (world,365,82,226) +[INFO]: || validateEvent:: itemInHand=[Diamond pickaxe ] blocks(1+0) (PassedValidation) (Fire pmEvent *start*) +[INFO]: || (applyAutoEvents: GOLD_ORE Pickup [disabled:mines] Smelt [disabled:mines] Block [disabled:mines] )(NormalDrop handling enabled: normalDropSmelt[disabled:] normalDropBlock[disabled:] normalDropCheckForFullInventory[disabled:] ) +[INFO]: || [normalDrops:: Raw gold:1] (getToolFort: fort=0) (dropping: Raw gold qty: 1 value: 45.0) +[INFO]: || [normalDrops total: qty: 1 value: 45.0] (autoEvents totalDrops: 1) (applyDropsBlockBreakage multi-blocks: 0) (breakBlocks:submitTask:1)(Fire pmEvent *completed*) (sellallEnabled:userToggleable)(autosellPlayerToggled: enabled) +[INFO]: || ### ** End Event Debug Info ** ### [50.996 ms] +[INFO]: DebugBlockInfo: Mine blue_a Rank: --- GOLD_ORE (world,365,82,226) +[INFO]: TargetBlock: gold_ore Mined: false Broke: false Counted: false +[INFO]: isEdge: false Exploded: false IgnoreAllEvents: false +[INFO]: BlockBreakEvent Dump: GOLD_ORE (365, 82, 226) +[INFO]: Tool Used for drops: Diamond pickaxe +[INFO]: Legend: EP: EventPriority EC: EventCanceled DC: DropsCanceled EB: EventBlock Ds: Drops ms: dur ms + +[INFO]: Plugin: -initial- EP: EC: false DC: normal EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: --- +[INFO]: Plugin: ExcellentEnchants EP: LOWEST EC: false DC: normal EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.059400 +[INFO]: Plugin: FastAsyncWorldEdit EP: LOWEST EC: false DC: normal EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.020100 +[INFO]: Plugin: ExcellentEnchants EP: LOW EC: false DC: normal EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.022800 +[INFO]: Plugin: Prison EP: LOW EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 51.845600 +[INFO]: Plugin: ExcellentEnchants EP: NORMAL EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.048900 +[INFO]: Plugin: WorldGuard EP: NORMAL EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 10.979900 +[INFO]: Plugin: WorldGuard EP: NORMAL EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.053500 +[INFO]: Plugin: PrisonEnchants EP: NORMAL EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 10.162000 +[INFO]: Plugin: Prison EP: NORMAL EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 1.030600 +[INFO]: Plugin: ExcellentEnchants EP: HIGH EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.023500 +[INFO]: Plugin: WorldGuard EP: HIGH EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.033300 +[INFO]: Plugin: ExcellentEnchants EP: HIGHEST EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.007500 +[INFO]: Plugin: ExcellentEnchants EP: HIGHEST EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.041100 +[INFO]: Plugin: Essentials EP: HIGHEST EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.178200 +[INFO]: Plugin: ExcellentEnchants EP: MONITOR EC: false DC: canceled EB: minecraft:GOLD_ORE Ds: Raw gold(1) ms: 0.075300 +[INFO]: - - End DebugBlockInfo - - +> +``` + + +
# Please READ This First - Using Access by Ranks to Simplify Many Things +*Note: This part of the document, through to the end, represents older notes. These may still be useful.* The latest versions of Prison has a new feature called **Access by Ranks** where a player, based upon their rank, is able to access a mine (break blocks within a mine) and also they can use the `/mtp` feature (mines teleport). By using **Access by Ranks** you do not have to setup any WorldGuard regions to allow players to break blocks within the mines, and you don't have to setup any permissions. @@ -47,6 +328,7 @@ If you need to manually setup Access By Ranks: # Prison's Event Priorities and WorldGuard Regions +*Note: This represents older notes. These may still be useful.* **NOTE:** You can also grant access through WorldGuard regions, and then prison will allow anyone to break blocks in the mines. The catch is that you must ensure WorldGuard checks access prior to Prison getting control of the BlockBreakEvents. This requires setting up WorldGuard regions and permissions. @@ -86,6 +368,8 @@ You cannot set any of the above event priorities to MONITOR since that goes agai # Please READ This Next +*Note: This represents older notes. These may still be useful.* + This document is a work in progress. This is a complex topic and depending upon how your environment is setup, the actual configurations may need to vary from what's covered in this document. @@ -187,7 +471,7 @@ Then **in game**, give yourself a WorldEdit wand: **Purpose:** This prevents players from breaking any blocks in the world. It also prevents mobs from spawning. -As op, protect the whole world with a passthrough flag set to deny. This will prevent building, PVP, and everything else. Basically, any action that “passthrough†all over defined regions, will be denied. The command with the **-w world** parameter has been added to the following list too. Use that version from console, the other without **-w world** in game. And where the name **world** is the actual name of your world. +As op, protect the whole world with a passthrough flag set to deny. This will prevent building, PVP, and everything else. Basically, any action that “passthroughâ€� all over defined regions, will be denied. The command with the **-w world** parameter has been added to the following list too. Use that version from console, the other without **-w world** in game. And where the name **world** is the actual name of your world. Note: the minimum you will need is the first line. The other two shuts down mob spawning, which is optional. @@ -217,6 +501,8 @@ Note that the **/gamerule doMobSpawning false** may also help prevent mobs from # Various LuckPerm Commands for Templates and Mines +*Note: This represents older notes. These may still be useful.* + *Not supported - For informational purposes only* The WorldGuard regions are covered below, but first you need to setup the groups within LuckPerm. Failure to create the groups prior to using them with the regions and prison rank commands may result in failures to work properly. @@ -272,6 +558,8 @@ And to now hook this up to prison, you do same command, dropping the leading sla # Unprotecting a Mine for its members - Required for all Mines +*Note: This represents older notes. These may still be useful.* + *Not supported - For informational purposes only* @@ -282,7 +570,7 @@ And to now hook this up to prison, you do same command, dropping the leading sla This defines a WorldGuard region, and needs to be applied to all mines, unless the Mine Access Permissions are used. -Select the same area of the mine with the WorldEdit **wand**, then use the following commands to define a mine. It will define a region with the mine’s name, and set the parent to mine_template, with the only member ever being the permission group **prison.mines.**. Never add a player to a WorldGuard region since it will get messy. Always use permission based groups and then add the player to that group. +Select the same area of the mine with the WorldEdit **wand**, then use the following commands to define a mine. It will define a region with the mine’s name, and set the parent to mine_template, with the only member ever being the permission group **prison.mines.**. Never add a player to a WorldGuard region since it will get messy. Always use permission based groups and then add the player to that group. This example includes an owner of this mine which is the group owner. And added the group admin as a member so the admins will have full access to this mine, even if they do not personally have the player's rank to access this mine. The actual members you add are up to you, but these are just two examples that you should consider. @@ -321,7 +609,7 @@ The following region setting for access and deny may *appear* to be useful, but **NOTE:** -It’s a bad idea to deny access to the mines through these regions. Such as with **-g nonmembers deny** on the **prison_mine_** regions. If the players doesn't have access to the mines, and they try to enter from the top, WorldGuard will continually prevent them from entering, or more specifically it will prevent them from falling in to the mine. This will basically keep them floating in the air which will trigger a fly event within anti-hacking tools. It will be far more professional to protect the area that contains the mine, thus you can protect it over the whole y-axis too. Players can also get caught in a rapid loop where WorldGuard is trying to kick them out of the mine when restricting just the mine; could possibly cause a lot of lag, depending upon how many event’s are being triggered. +It’s a bad idea to deny access to the mines through these regions. Such as with **-g nonmembers deny** on the **prison_mine_** regions. If the players doesn't have access to the mines, and they try to enter from the top, WorldGuard will continually prevent them from entering, or more specifically it will prevent them from falling in to the mine. This will basically keep them floating in the air which will trigger a fly event within anti-hacking tools. It will be far more professional to protect the area that contains the mine, thus you can protect it over the whole y-axis too. Players can also get caught in a rapid loop where WorldGuard is trying to kick them out of the mine when restricting just the mine; could possibly cause a lot of lag, depending upon how many event’s are being triggered.
@@ -332,6 +620,8 @@ It’s a bad idea to deny access to the mines through these regions. Such as wit # Protecting a Mine's Area - Required for all Mine Areas +*Note: This represents older notes. These may still be useful.* + *This kind of a region is partially supported. It is used to physically prevent a player from entering an a mine's area.** @@ -341,17 +631,17 @@ It’s a bad idea to deny access to the mines through these regions. Such as wit **Important:** You don't need to define mine-area regions if your mines are geographically isolated, such as islands in a void world. -In general, it may be tempting to restrict access to the mine itself so non-members cannot mine it. But there is a serious problem with just protecting the mine, and that’s when non-members walk on top of the mine. They will fall in to the mine, as expected, but WorldGuard will try to keep them out, so they will be bumped back above the mine, thus triggering a “fly†event, or a “hover†event. This action may trigger anti-hacking software to auto kick them, or auto ban the players, or the players could get stuck, and it may even cause a lot of lag on the server too. +In general, it may be tempting to restrict access to the mine itself so non-members cannot mine it. But there is a serious problem with just protecting the mine, and that’s when non-members walk on top of the mine. They will fall in to the mine, as expected, but WorldGuard will try to keep them out, so they will be bumped back above the mine, thus triggering a “fly� event, or a “hover� event. This action may trigger anti-hacking software to auto kick them, or auto ban the players, or the players could get stuck, and it may even cause a lot of lag on the server too. This also happens really fast, in a very repeated action, so it could lock up the player so they cannot jump back out before they get banned. I do not know if this could contribute to server lag, but a lot of processing appears to be happening so it is possible. -The suggested action is to create a new region around the mine and protect that from entry from non-members. This region can then be extended from y=0 to y=255 with the WorldEdit command `//expand vert``. If anyone does get past it, they still won’t be able to mine. +The suggested action is to create a new region around the mine and protect that from entry from non-members. This region can then be extended from y=0 to y=255 with the WorldEdit command `//expand vert``. If anyone does get past it, they still won’t be able to mine. The primary purpose is to keep non-members out of the region. It will also prevent non-members from TP'ing in to the area too. It will also supply the player with an error message to inform them they don't have the rn -Select the an area around the mine with the WorldEdit **wand**. Only select a rectangle area around the mine, ignoring the **y** axis. Then use the following commands to define a mine. It will define a region with the mine’s name, and set the parent to mine_template, with the only member ever being the permission **g:prison.mines.**: +Select the an area around the mine with the WorldEdit **wand**. Only select a rectangle area around the mine, ignoring the **y** axis. Then use the following commands to define a mine. It will define a region with the mine’s name, and set the parent to mine_template, with the only member ever being the permission **g:prison.mines.**: The command **//expand vert** will take your selection and extend the **y** to cover the whole vertical range in your region. This is why you don't have to be concerned with the *y* axis when defining your mine area regions. @@ -393,6 +683,8 @@ Of course, just like **prison_mine_** region, we also give `owner` an # Granting Access to a Mine and Removal of the access +*Note: This represents older notes. These may still be useful.* + **Purpose:** From either the console, or from within game, manually grant a player access to a mine. To add a player to the mine regions is as simple as giving the user the permission associated with the mine region. @@ -468,6 +760,8 @@ The following is an example of adding and removing a permission to a player. Th # Adding Rank Commands to run when /rankup is Performed +*Note: This represents older notes. These may still be useful.* + **Purpose:** Adds the permission to access the mine area and to mine within a mine, when a player successfully runs /rankup. @@ -503,6 +797,7 @@ So to recap, for every rank, ideally you should add the new perms for that rank, # Adding the Prison Rank Commands - Summary of Rank Commands +*Note: This represents older notes. These may still be useful.* This is an example of setting up Rank Commands for mines a and b, we now need to add the Rank Commands to active the permission for both. Also included in these commands are the permissions for the mines.tp command, where mines.tp. is a permission and not a group. @@ -536,6 +831,8 @@ And that's it! Just repeat for all your other mines. # Alternatives +*Note: This represents older notes. These may still be useful.* + There are many ways to accomplish the same goals and that's what makes Minecraft so versatile and interesting to play. The Prison Plugin does not want to impose a specific way to do most things, since it may not be the ideal way for your sever. One of the primary focuses for this document has been protecting the area around your mine to prevent players who should not access the mine, from enter that region. One alternative to needing to protect a mine, would be to limit the access to the mine so it does not have to be protected. One simple way of accomplishing that, is to have the mines in a void world, and then each mine would be a separate island. Then all that would need to be protected, or controlled, would be the warping to that location. @@ -554,6 +851,7 @@ One of the primary focuses for this document has been protecting the area around # Other Commands That May Be Important: +*Note: This represents older notes. These may still be useful.* /region redefine mine_ @@ -563,7 +861,7 @@ One of the primary focuses for this document has been protecting the area around -Set’s the WorldEdit selection to the dimensions of the given mine: +Set's the WorldEdit selection to the dimensions of the given mine: /region select prison_mine_ /region select prison_mine_area_ diff --git a/gradle.properties b/gradle.properties index 94e87c1b7..29e72a067 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,8 +3,16 @@ ## # 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.18a - +version=3.3.1 +##version=3.4.0-alpha.1 + +## version progressions: +## v3.4.0-alpha.1 +## v3.4.0-alpha.2 +## v3.4.0-beta.1 +## v3.4.0-beta.2 +## v3.4.0-rc.1 +## v3.4.0 ## org.gradle.warning.mode=(all,none,summary) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 62104e59f..84d8e639f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,13 @@ # https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 # https://mvnrepository.com/artifact/com.google.guava/guava # -# Note: papi has two possible URLs: The second one is the offical but the repo does not work well. +## NOTE: mavenrepository.com is not the official repo. +## NOTE: This item-nbt MUST use the API and not the plugin version! +## Good: https://repo.codemc.io/service/rest/repository/browse/maven-public/de/tr7zw/item-nbt-api/ +## Bad?: https://repo.codemc.io/service/rest/repository/browse/maven-public/de/tr7zw/item-nbt-api-plugin/2.11.3/ + + +# Note: papi has two possible URLs: The second one is the official but the repo does not work well. # com.github.placeholderapi:placeholderapi # me.clip:placeholderapi # @@ -28,13 +34,20 @@ commons-lang3 = "3.12.0" groovy = "3.0.9" gson = "2.10.1" spiget = "1.4.6-SNAPSHOT" -xseries = "10.0.0" + +# NOTE: xseries v13.8.0 is required for spigot v26.1.x, but will fail to run under java 1.8. +#xseries = "13.8.0" +xseries = "11.3.0" junit = "4.12" guava = "31.1-jre" spigotApi = "1.13.2-R0.1-SNAPSHOT" -nbtApi = "2.12.4" -papi = "2.11.5" +nbtApi = "2.15.7" +#nbtApi = "2.15.5" +#nbtApi = "2.15.3" +#nbtApi = "2.15.0" +#nbtApi = "2.14.1" +papi = "2.11.6" vault = "1.7.1" luckperms-v4 = "4.4" @@ -42,6 +55,9 @@ luckperms-v5 = "5.4" itemsAdder = "3.5.0b" +worldedit-v6 = "6.0.1" +worldedit-v7 = "7.2.15" +worldguard-v7 = "7.0.4" @@ -72,6 +88,11 @@ spigotApi = { module = "org.spigotmc:spigot-api", version.ref = "spigotApi" } vault = { module = "com.github.MilkBowl:VaultAPI", version.ref = "vault" } + + +## VaultUnlocked does not stand by itself.. it's using the vault signatures, but has a vault2 package name: +##vaultUnlocked = { module = "com.github.MilkBowl:VaultUnlockedAPI", version.ref = "vaultUnlocked" } + xseries = { module = "com.github.cryptomorin:XSeries", version.ref = "xseries" } @@ -80,6 +101,20 @@ xseries = { module = "com.github.cryptomorin:XSeries", version.ref = "xseries" } # gson = { module = "com.google.code.gson:gson", version = "2.9.1" } +worldedit-core-v6 = { module = "com.sk89q.worldedit:worldedit-core", version.ref = "worldedit-v6" } +worldedit-bukkit-v6 = { module = "com.sk89q.worldedit:worldedit-bukkit", version.ref = "worldedit-v6" } + + +## WARNING: v7.0.4 is the last release that is java 1.8 compatible +## https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-core +## https://mvnrepository.com/artifact/com.sk89q.worldguard/worldguard-bukkit +## https://mvnrepository.com/artifact/com.sk89q.worldguard.worldguard-libs/core +worldedit-core-v7 = { module = "com.sk89q.worldedit:worldedit-core", version.ref = "worldedit-v7" } +worldedit-bukkit-v7 = { module = "com.sk89q.worldedit:worldedit-bukkit", version.ref = "worldedit-v7" } + +worldguard-core-v7 = { module = "com.sk89q.worldguard:worldguard-core", version.ref = "worldguard-v7" } +worldguard-bukkit-v7 = { module = "com.sk89q.worldguard:worldguard-bukkit", version.ref = "worldguard-v7" } +worldguard-libs-v7 = { module = "com.sk89q.worldguard.worldguard-libs:core", version.ref = "worldguard-v7" } diff --git a/prison-core/build.gradle b/prison-core/build.gradle index 8deb786e6..072c2e2a3 100644 --- a/prison-core/build.gradle +++ b/prison-core/build.gradle @@ -1,25 +1,19 @@ -/* - * Prison is a Minecraft plugin for the prison game mode. - * Copyright (C) 2017-2020 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 . - */ - compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = "UTF-8" + +ext.targetArchiveClassifier = 'Java1.8' +//ext.targetArchiveClassifier = 'Java16' + +// Lists all versions of java that are available to the toolchain +// $ ./gradlew -q javaToolchains + +// Specify the java version's location as found in the javaToolchains. +// $ ./gradlew build -Dorg.gradle.java.home="C:\Program Files\Java\jdk1.8.0_291" + + + dependencies { implementation( libs.commons.lang3 ) diff --git a/prison-core/module_conf/mines/mineBombsConfig.json b/prison-core/module_conf/mines/mineBombsConfig.json new file mode 100644 index 000000000..166b714fb --- /dev/null +++ b/prison-core/module_conf/mines/mineBombsConfig.json @@ -0,0 +1,1253 @@ +{ + "dataFormatVersion": 3, + "bombs": { + "bouncebomb": { + "name": "BounceBomb", + "description": "This old bomb is a dud.&r", + "lore": [ + "This is a bomb?&r" + ], + "nameTag": "&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "IRON_INGOT", + "radius": 2, + "radiusInner": 0, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 50.0, + "explosionShape": "sphere", + "toolInHandName": "STONE_PICKAXE", + "toolInHandFortuneLevel": 1, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 300, + "cooldownTicks": 20, + "itemRemovalDelayTicks": 5, + "animationPattern": "bounce", + "animationOffset": 0.0, + "animationSpeed": 10.0, + "animationRadius": 1.0, + "animationRadiusDelta": 0.0, + "animationAlternateDirections": false, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "hand", + "throwVelocityLow": 0.25, + "throwVelocityHigh": 1.5, + "glowing": false, + "gravity": true, + "autosell": false, + "customModelData": 0, + "allowedMines": [], + "preventedMines": [], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "FLAME", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "BUBBLE_COLUMN_UP", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + } + ] + }, + "cubebomb": { + "name": "CubeBomb", + "description": "The most anti-round bomb you will ever be able to find. It's totally cubic.&r", + "lore": [ + "A Cubic Bomb&r" + ], + "nameTag": "&a-=- &7{name}&a -=--&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "SLIME_BALL", + "radius": 2, + "radiusInner": 0, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 100.0, + "explosionShape": "cube", + "toolInHandName": "DIAMOND_PICKAXE", + "toolInHandFortuneLevel": 7, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 300, + "cooldownTicks": 20, + "itemRemovalDelayTicks": 5, + "animationPattern": "orbital", + "animationOffset": 0.0, + "animationSpeed": 10.0, + "animationRadius": 1.0, + "animationRadiusDelta": 0.0, + "animationAlternateDirections": false, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "head", + "throwVelocityLow": 1.5, + "throwVelocityHigh": 3.0, + "glowing": true, + "gravity": true, + "autosell": false, + "customModelData": 0, + "allowedMines": [], + "preventedMines": [], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "FLAME", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "BUBBLE_COLUMN_UP", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + } + ] + }, + "largebomb": { + "name": "LargeBomb", + "description": "A large mine bomb made from TNT with some strange parts that maybe be described as alien technology.&r", + "lore": [ + "Large Mine Bomb" + ], + "nameTag": "&a-=- &7{name}&a -=--&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "tnt", + "radius": 12, + "radiusInner": 3, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 100.0, + "explosionShape": "sphereHollow", + "toolInHandName": "DIAMOND_PICKAXE", + "toolInHandFortuneLevel": 3, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 100, + "cooldownTicks": 60, + "itemRemovalDelayTicks": 5, + "animationPattern": "infinity", + "animationOffset": 0.0, + "animationSpeed": 10.0, + "animationRadius": 1.0, + "animationRadiusDelta": 0.0, + "animationAlternateDirections": false, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "hand", + "throwVelocityLow": 1.5, + "throwVelocityHigh": 3.0, + "glowing": false, + "gravity": true, + "autosell": false, + "customModelData": 0, + "allowedMines": [], + "preventedMines": [], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 2.0, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "FLAME", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE_NORMAL", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "ENCHANTMENT_TABLE", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "EXPLOSION_NORMAL", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ] + }, + "mediumbomb": { + "name": "MediumBomb", + "description": "A medium mine bomb made from leftover fireworks, &rbut supercharged with a strange green glowing liquid.&r", + "lore": [ + "Medium Mine Bomb&r" + ], + "nameTag": "&6&k1 23 456&r&a-=- &7{name}&a -=-&6&k654 32 1&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "firework_rocket", + "radius": 5, + "radiusInner": 0, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 100.0, + "explosionShape": "sphere", + "toolInHandName": "DIAMOND_PICKAXE", + "toolInHandFortuneLevel": 3, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 100, + "cooldownTicks": 60, + "itemRemovalDelayTicks": 5, + "animationPattern": "infinity", + "animationOffset": 0.0, + "animationSpeed": 10.0, + "animationRadius": 1.0, + "animationRadiusDelta": 0.0, + "animationAlternateDirections": false, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "hand", + "throwVelocityLow": 1.5, + "throwVelocityHigh": 3.0, + "glowing": false, + "gravity": true, + "autosell": false, + "customModelData": 0, + "allowedMines": [], + "preventedMines": [], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "FLAME", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE_NORMAL", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "ENCHANTMENT_TABLE", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "EXPLOSION_NORMAL", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ] + }, + "nonebomb": { + "name": "NoneBomb", + "description": "This old bomb is a dud.&r", + "lore": [ + "This is a bomb?&r" + ], + "nameTag": "&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "COAL", + "radius": 2, + "radiusInner": 0, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 25.0, + "explosionShape": "sphere", + "toolInHandName": "STONE_PICKAXE", + "toolInHandFortuneLevel": 1, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 300, + "cooldownTicks": 20, + "itemRemovalDelayTicks": 5, + "animationPattern": "none", + "animationOffset": 0.0, + "animationSpeed": 10.0, + "animationRadius": 1.0, + "animationRadiusDelta": 0.0, + "animationAlternateDirections": false, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "hand", + "throwVelocityLow": 0.25, + "throwVelocityHigh": 3.5, + "glowing": false, + "gravity": true, + "autosell": false, + "customModelData": 0, + "allowedMines": [], + "preventedMines": [], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "FLAME", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "BUBBLE_COLUMN_UP", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + } + ] + }, + "oofbomb": { + "name": "OofBomb", + "description": "An oof-ably large mine bomb made with a minecart heaping with TNT. Unlike the large mine bomb, this one obviously is built with alien technology.&r", + "lore": [ + "Oof Mine Bomb&r" + ], + "nameTag": "&c&k1&6&k23&e&k456&r&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&e&k654&6&k32&c&k1&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "tnt_minecart", + "radius": 21, + "radiusInner": 3, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 100.0, + "explosionShape": "sphereHollow", + "toolInHandName": "GOLDEN_PICKAXE", + "toolInHandFortuneLevel": 13, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 260, + "cooldownTicks": 60, + "itemRemovalDelayTicks": 5, + "animationPattern": "infinity", + "animationOffset": 0.0, + "animationSpeed": 10.0, + "animationRadius": 1.0, + "animationRadiusDelta": 0.0, + "animationAlternateDirections": false, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "hand", + "throwVelocityLow": 1.5, + "throwVelocityHigh": 3.0, + "glowing": true, + "gravity": true, + "autosell": true, + "customModelData": 0, + "allowedMines": [], + "preventedMines": [], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 10, + "volumne": 0.25, + "pitch": 0.25 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 20, + "volumne": 0.5, + "pitch": 0.5 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 0.75 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 40, + "volumne": 2.0, + "pitch": 1.5 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 50, + "volumne": 5.0, + "pitch": 2.5 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 3.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_DRAGON_FIREBALL_EXPLODE", + "effectState": "explode", + "offsetTicks": 5, + "volumne": 1.5, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 10, + "volumne": 2.5, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_DRAGON_FIREBALL_EXPLODE", + "effectState": "explode", + "offsetTicks": 15, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 20, + "volumne": 2.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_DRAGON_FIREBALL_EXPLODE", + "effectState": "explode", + "offsetTicks": 25, + "volumne": 0.75, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 30, + "volumne": 1.5, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_DRAGON_FIREBALL_EXPLODE", + "effectState": "explode", + "offsetTicks": 35, + "volumne": 0.55, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 40, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_DRAGON_FIREBALL_EXPLODE", + "effectState": "explode", + "offsetTicks": 45, + "volumne": 0.25, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 50, + "volumne": 0.5, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_DRAGON_FIREBALL_EXPLODE", + "effectState": "explode", + "offsetTicks": 55, + "volumne": 0.15, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "ENCHANTMENT_TABLE", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE_NORMAL", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE_NORMAL", + "effectState": "placed", + "offsetTicks": 20, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE_LARGE", + "effectState": "placed", + "offsetTicks": 60, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "DRAGON_BREATH", + "effectState": "placed", + "offsetTicks": 90, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "EXPLOSION_HUGE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "EXPLOSION_NORMAL", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "EXPLOSION_HUGE", + "effectState": "explode", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "EXPLOSION_HUGE", + "effectState": "explode", + "offsetTicks": 60, + "volumne": 1.0, + "pitch": 1.0 + } + ] + }, + "orbital8bomb": { + "name": "Orbital8Bomb", + "description": "This old bomb is a dud.&r", + "lore": [ + "This is a bomb?&r", + "&7Hex Colors: &#e81416Red&#ffa500Orange&#faeb36YellowOc314Greenǧde7Blueb369dIndigo𑋡dViolet" + ], + "nameTag": "&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "DIAMOND", + "radius": 2, + "radiusInner": 0, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 50.0, + "explosionShape": "sphere", + "toolInHandName": "STONE_PICKAXE", + "toolInHandFortuneLevel": 1, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 300, + "cooldownTicks": 20, + "itemRemovalDelayTicks": 5, + "animationPattern": "orbitalEight", + "animationOffset": 0.0, + "animationSpeed": 10.0, + "animationRadius": 1.0, + "animationRadiusDelta": 0.0, + "animationAlternateDirections": false, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "head", + "throwVelocityLow": 0.25, + "throwVelocityHigh": 1.5, + "glowing": false, + "gravity": true, + "autosell": false, + "customModelData": 0, + "allowedMines": [], + "preventedMines": [], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "FLAME", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "BUBBLE_COLUMN_UP", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + } + ] + }, + "orbitalbomb": { + "name": "OrbitalBomb", + "description": "This old bomb is a dud.&r", + "lore": [ + "This is a bomb?&r" + ], + "nameTag": "&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "GOLD_INGOT", + "radius": 2, + "radiusInner": 0, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 50.0, + "explosionShape": "sphere", + "toolInHandName": "STONE_PICKAXE", + "toolInHandFortuneLevel": 1, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 300, + "cooldownTicks": 20, + "itemRemovalDelayTicks": 5, + "animationPattern": "orbital", + "animationOffset": 0.0, + "animationSpeed": 10.0, + "animationRadius": 1.0, + "animationRadiusDelta": 0.0, + "animationAlternateDirections": false, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "head", + "throwVelocityLow": 0.25, + "throwVelocityHigh": 1.5, + "glowing": false, + "gravity": true, + "autosell": false, + "customModelData": 0, + "allowedMines": [], + "preventedMines": [], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "FLAME", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "BUBBLE_COLUMN_UP", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + } + ] + }, + "smallbomb": { + "name": "SmallBomb", + "description": "A small mine bomb made with some chemicals and a brewing stand.&r", + "lore": [ + "&dSmall &6Mine &eBomb &3(lore line 1)&r", + "&4Lore line 2&r", + "&aLore line &73&r" + ], + "nameTag": "&6&kABC&r&c-= &7{name}&c =-&6&kCBA&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "brewing_stand", + "radius": 2, + "radiusInner": 0, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 100.0, + "explosionShape": "sphere", + "toolInHandName": "DIAMOND_PICKAXE", + "toolInHandFortuneLevel": 0, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 100, + "cooldownTicks": 10, + "itemRemovalDelayTicks": 5, + "animationPattern": "infinity", + "animationOffset": 0.0, + "animationSpeed": 10.0, + "animationRadius": 1.0, + "animationRadiusDelta": 0.0, + "animationAlternateDirections": false, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "hand", + "throwVelocityLow": 1.5, + "throwVelocityHigh": 3.0, + "glowing": false, + "gravity": true, + "autosell": false, + "customModelData": 0, + "allowedMines": [], + "preventedMines": [], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "FLAME", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE_NORMAL", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "ENCHANTMENT_TABLE", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "EXPLOSION_NORMAL", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ] + }, + "starburstbomb": { + "name": "starburstBomb", + "description": "This old bomb is a star!r", + "lore": [ + "This is a bomb?&r", + "&7Hex Colors: &#e81416Red&#ffa500Orange&#faeb36YellowOc314Greenǧde7Blueb369dIndigo𑋡dViolet" + ], + "nameTag": "&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "WHEAT", + "radius": 2, + "radiusInner": 0, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 50.0, + "explosionShape": "sphere", + "toolInHandName": "STONE_PICKAXE", + "toolInHandFortuneLevel": 1, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 300, + "cooldownTicks": 20, + "itemRemovalDelayTicks": 5, + "animationPattern": "starburst", + "animationOffset": 0.0, + "animationSpeed": 9.0, + "animationRadius": 1.5, + "animationRadiusDelta": 0.75, + "animationAlternateDirections": true, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "hand", + "throwVelocityLow": 0.25, + "throwVelocityHigh": 1.5, + "glowing": false, + "gravity": true, + "autosell": false, + "customModelData": 0, + "allowedMines": [], + "preventedMines": [], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "FLAME", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "BUBBLE_COLUMN_UP", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + } + ] + }, + "wimpybomb": { + "name": "WimpyBomb", + "description": "A whimpy bomb made with gunpowder and packs the punch of a dull wooden pickaxe. For some reason, it only has a 30 percent chance of removing a block.&r", + "lore": [ + "A Wimpy Mine Bomb&r", + "&r", + "A whimpy bomb made with gunpowder and packs the punch &r", + "of a dull wooden pickaxe. For some reason, it only &r", + "has a 40% chance of removing a block.&r", + "&r", + "Not labeled for retail sale.&r" + ], + "nameTag": "&7A &2Wimpy &cBomb&r", + "itemName": "&c-= &7{name}&c =-", + "itemType": "GUNPOWDER", + "radius": 2, + "radiusInner": 1, + "height": 0, + "placementAdjustmentY": 0, + "removalChance": 30.0, + "explosionShape": "sphere", + "toolInHandName": "WOODEN_PICKAXE", + "toolInHandFortuneLevel": 0, + "toolInHandDurabilityLevel": 0, + "toolInHandDigSpeedLevel": 0, + "fuseDelayTicks": 300, + "cooldownTicks": 5, + "itemRemovalDelayTicks": 5, + "animationPattern": "infinityEight", + "animationOffset": 0.0, + "animationSpeed": 10.0, + "animationRadius": 1.0, + "animationRadiusDelta": 0.0, + "animationAlternateDirections": false, + "animationSpinSpeed": -35.0, + "animationArmorStandItemLocation": "hand", + "throwVelocityLow": 0.25, + "throwVelocityHigh": 1.25, + "glowing": true, + "gravity": false, + "autosell": false, + "customModelData": 0, + "allowedMines": [ + "a", + "b", + "c" + ], + "preventedMines": [ + "d", + "e" + ], + "applyToPlayersBlockCount": true, + "small": false, + "soundEffects": [ + { + "effectType": "sounds", + "effectName": "ENTITY_CREEPER_PRIMED", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "CAT_HISS", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "sounds", + "effectName": "ENTITY_GENERIC_EXPLODE", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + } + ], + "visualEffects": [ + { + "effectType": "visuals", + "effectName": "FIREWORKS_SPARK", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "FLAME", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "SMOKE_NORMAL", + "effectState": "placed", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "ENCHANTMENT_TABLE", + "effectState": "placed", + "offsetTicks": 10, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "BUBBLE_COLUMN_UP", + "effectState": "placed", + "offsetTicks": 30, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "EXPLOSION_NORMAL", + "effectState": "explode", + "offsetTicks": 0, + "volumne": 1.0, + "pitch": 1.0 + }, + { + "effectType": "visuals", + "effectName": "EXPLOSION_LARGE", + "effectState": "explode", + "offsetTicks": 5, + "volumne": 1.0, + "pitch": 1.0 + } + ] + } + } +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/Prison.java b/prison-core/src/main/java/tech/mcprison/prison/Prison.java index 8c8b4d5a5..51601a7f4 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/Prison.java +++ b/prison-core/src/main/java/tech/mcprison/prison/Prison.java @@ -47,7 +47,7 @@ import tech.mcprison.prison.troubleshoot.TroubleshootManager; import tech.mcprison.prison.util.EventExceptionHandler; import tech.mcprison.prison.util.PrisonStatsUtil; -import tech.mcprison.prison.util.PrisonTPS; +import tech.mcprison.prison.util.PrisonTPSSingleton; /** * Entry point for implementations.

An instance of Prison can be retrieved using the static @@ -96,7 +96,6 @@ public class Prison private LocaleManager localeManager; private File moduleDataFolder; -// private ItemManager itemManager; private ErrorManager errorManager; private TroubleshootManager troubleshootManager; private IntegrationManager integrationManager; @@ -106,7 +105,7 @@ public class Prison private Database metaDatabase; private PrisonStatsUtil statsUtil; - private PrisonTPS prisonTPS; + private PrisonTPSSingleton prisonTPS; private List localeLoadInfo; @@ -115,11 +114,11 @@ public class Prison private static boolean dfSymStatic = false; private Prison() { - super(); - - this.serverStartupTime = System.currentTimeMillis(); - - this.localeLoadInfo = new ArrayList<>(); + super(); + + this.serverStartupTime = System.currentTimeMillis(); + + this.localeLoadInfo = new ArrayList<>(); } /** @@ -136,24 +135,24 @@ public static Prison get() { } public DecimalFormat getDecimalFormat( String format ) { - DecimalFormat dFmt = new DecimalFormat( format, getDecimalFormatSymbols() ); - return dFmt; + DecimalFormat dFmt = new DecimalFormat( format, getDecimalFormatSymbols() ); + return dFmt; } public DecimalFormat getDecimalFormatInt() { - return getDecimalFormat("#,##0"); + return getDecimalFormat("#,##0"); } public DecimalFormat getDecimalFormatDouble() { - return getDecimalFormat("#,##0.000"); + return getDecimalFormat("#,##0.000"); } public static DecimalFormat getDecimalFormatStatic( String format ) { - DecimalFormat dFmt = new DecimalFormat( format, getDecimalFormatSymbolsStatic() ); + DecimalFormat dFmt = new DecimalFormat( format, getDecimalFormatSymbolsStatic() ); return dFmt; } public static DecimalFormat getDecimalFormatStaticInt() { - return getDecimalFormatStatic("#,##0"); + return getDecimalFormatStatic("#,##0"); } public static DecimalFormat getDecimalFormatStaticDouble() { - return getDecimalFormatStatic("#,##0.000"); + return getDecimalFormatStatic("#,##0.000"); } /** @@ -174,29 +173,29 @@ public static DecimalFormat getDecimalFormatStaticDouble() { * @return */ private DecimalFormatSymbols getDecimalFormatSymbols() { - if ( dfSym == null || dfSymStatic ) { - - String location = getPlatform().getConfigString( "number-format-location", "en_US" ); - String[] loc = location.split("_"); - - Locale locale = new Locale( - loc != null && loc.length >= 1 ? loc[0] : "en", - loc != null && loc.length >= 2 ? loc[1] : "US" ); - -// Locale locale = new Locale( "en", "US" ); - dfSym = new DecimalFormatSymbols( locale ); - dfSymStatic = false; - } - return dfSym; + if ( dfSym == null || dfSymStatic ) { + + String location = getPlatform().getConfigString( "number-format-location", "en_US" ); + String[] loc = location.split("_"); + + Locale locale = new Locale( + loc != null && loc.length >= 1 ? loc[0] : "en", + loc != null && loc.length >= 2 ? loc[1] : "US" ); + + // Locale locale = new Locale( "en", "US" ); + dfSym = new DecimalFormatSymbols( locale ); + dfSymStatic = false; + } + return dfSym; } private static DecimalFormatSymbols getDecimalFormatSymbolsStatic() { - if ( dfSym == null ) { - - Locale locale = new Locale( "en", "US" ); - dfSym = new DecimalFormatSymbols( locale ); - dfSymStatic = true; - } - return dfSym; + if ( dfSym == null ) { + + Locale locale = new Locale( "en", "US" ); + dfSym = new DecimalFormatSymbols( locale ); + dfSymStatic = true; + } + return dfSym; } /** @@ -211,16 +210,16 @@ private static DecimalFormatSymbols getDecimalFormatSymbolsStatic() { */ public LocaleManager getLocaleManager() { - if ( this.localeManager == null ) { - - synchronized ( this ) { - if ( this.localeManager == null ) { - - this.localeManager = new LocaleManager(this, "lang/core"); - } + if ( this.localeManager == null ) { + + synchronized ( this ) { + if ( this.localeManager == null ) { + + this.localeManager = new LocaleManager(this, "lang/core"); + } } - - } + + } return localeManager; } @@ -233,20 +232,20 @@ public LocaleManager getLocaleManager() { */ public File getModuleDataFolder() { - if ( moduleDataFolder == null ) { - if ( this.localeManager == null ) { - if ( moduleDataFolder == null ) { - - this.moduleDataFolder = Module.setupModuleDataFolder( "core" ); - - } - } - } + if ( moduleDataFolder == null ) { + if ( this.localeManager == null ) { + if ( moduleDataFolder == null ) { + + this.moduleDataFolder = Module.setupModuleDataFolder( "core" ); + + } + } + } return moduleDataFolder; } - + public void setupJUnitInstance( Platform platform ) { - this.platform = platform; + this.platform = platform; } @@ -259,11 +258,9 @@ public void setupJUnitInstance( Platform platform ) { * Note that modules should not call this method. This is solely for the implementations. */ public void init(Platform platform, String minecraftVersion ) { - long startTime = System.currentTimeMillis(); - - - this.platform = platform; - this.minecraftVersion = minecraftVersion; + + this.platform = platform; + this.minecraftVersion = minecraftVersion; } @@ -277,10 +274,6 @@ public void init(Platform platform, String minecraftVersion ) { public boolean init( File dataFolder ) { long startTime = System.currentTimeMillis(); - -// this.platform = platform; -// this.minecraftVersion = minecraftVersion; - this.dataFolder = dataFolder; if (!initDataFolder()) { @@ -293,10 +286,10 @@ public boolean init( File dataFolder ) { this.statsUtil = new PrisonStatsUtil(); - this.prisonTPS = new PrisonTPS(); + this.prisonTPS = PrisonTPSSingleton.getInstance(); this.prisonTPS.submitAsyncTPSTask(); - + // Setup the LocalManager if it is not yet started: getLocaleManager(); @@ -306,11 +299,13 @@ public boolean init( File dataFolder ) { Output.get().logInfo("Enabling and starting..."); + + // Initialize various parts of the API. The magic happens here :) initManagers(); if (!initMetaDatabase()) { - Output.get().logInfo("&cFailure: &eInitializing the Prison Database!" ); - Output.get().logInfo("&e&k!=&d Prison Plugin Terminated! &e&k=!&7" ); + Output.get().logInfo("&cFailure: &eInitializing the Prison Database!" ); + Output.get().logInfo("&e&k!=&d Prison Plugin Terminated! &e&k=!&7" ); return false; } Alerts.getInstance(); // init alerts @@ -323,7 +318,8 @@ public boolean init( File dataFolder ) { long stopTime = System.currentTimeMillis(); Output.get() - .logInfo("Enabled &3Prison v%s in %d milliseconds.", getPlatform().getPluginVersion(), + .logInfo("Enabled &3Prison v%s in %d milliseconds.", + getPlatform().getPluginVersion(), (stopTime - startTime)); registerInbuiltTroubleshooters(); @@ -346,33 +342,36 @@ public boolean init( File dataFolder ) { private void sendBanner() { - ChatDisplay display = new ChatDisplay(""); - - display.addText(""); - display.addText("&6 _____ _ "); - display.addText("&6| __ \\ (_) "); - display.addText("&6| |__) | __ _ ___ ___ _ __ "); - display.addText("&6| ___/ '__| / __|/ _ \\| '_ \\"); - display.addText("&6| | | | | \\__ \\ (_) | | | |"); - display.addText("&6|_| |_| |_|___/\\___/|_| |_|"); - display.addText(""); - display.addText("&7Loading Prison version: &3%s", PrisonAPI.getPluginVersion()); - display.addText("&7Running on platform: &3%s", platform.getClass().getSimpleName()); - display.addText("&7Minecraft version: &3%s", getMinecraftVersion()); - // display.addText("&7Server runtime: %s", getServerRuntimeFormatted() ); - display.addText(""); - - displaySystemSettings( display ); - displaySystemTPS( display ); - - display.addText(""); - - display.sendtoOutputLogInfo(); + ChatDisplay display = new ChatDisplay(""); + + display.addText(""); + display.addText("&6 _____ _ "); + display.addText("&6| __ \\ (_) "); + display.addText("&6| |__) | __ _ ___ ___ _ __ "); + display.addText("&6| ___/ '__| / __|/ _ \\| '_ \\"); + display.addText("&6| | | | | \\__ \\ (_) | | | |"); + display.addText("&6|_| |_| |_|___/\\___/|_| |_|"); + display.addText(""); + display.addText("&7Loading Prison version: &3%s", PrisonAPI.getPluginVersion()); + display.addText("&7Running on platform: &3%s", platform.getClass().getSimpleName()); + display.addText("&7Minecraft version: &3%s", getMinecraftVersion()); + // display.addText("&7Server runtime: %s", getServerRuntimeFormatted() ); + display.addText(""); + + displaySystemSettings( display ); + displaySystemTPS( display ); + + display.addText(""); + + + getPrisonStatsUtil().checkDirectoryStructures( display ); + + display.sendtoOutputLogInfo(); } public void displaySystemSettings( ChatDisplay display ) { - display.addText("&7Server runtime: %s", Prison.get().getServerRuntimeFormatted() );; + display.addText("&7Server runtime: %s", Prison.get().getServerRuntimeFormatted() ); Runtime runtime = Runtime.getRuntime(); @@ -476,14 +475,14 @@ public PrisonStatsUtil getPrisonStatsUtil() { public void displaySystemTPS( ChatDisplay display ) { DecimalFormat iFmt = getDecimalFormatInt(); - PrisonTPS prisonTPS = Prison.get().getPrisonTPS(); + PrisonTPSSingleton prisonTPS = Prison.get().getPrisonTPS(); display.addText( "&7Prison TPS Average: %s Min: %s Max: %s%s " + "Interval: %s ticks Samples: %s", prisonTPS.getAverageTPSFormatted(), prisonTPS.getTPSMinFormatted(), ( prisonTPS.getTpsMax() >= 100 ? ">" : ""), prisonTPS.getTPSMaxFormatted(), - iFmt.format( PrisonTPS.SUBMIT_TICKS_INTERVAL ), + iFmt.format( PrisonTPSSingleton.SUBMIT_TICKS_INTERVAL ), iFmt.format( prisonTPS.getTpsSamples() ) ); @@ -491,28 +490,17 @@ public void displaySystemTPS( ChatDisplay display ) { String tpsHistory = prisonTPS.getLastFewTPS(); if ( tpsHistory.length() > 0 ) { - display.addText( "&7TPS History: %s", tpsHistory ); + display.addText( "&7TPS History: %s", tpsHistory ); } } public void getSystemTPS( LinkedHashMap fields ) { - //DecimalFormat iFmt = getDecimalFormatInt(); - PrisonTPS prisonTPS = Prison.get().getPrisonTPS(); - - fields.put( "tps", prisonTPS.getAverageTPSFormatted() ); - fields.put( "tpsMin", prisonTPS.getTPSMinFormatted() ); -// fields.put( "tpsMax", ( prisonTPS.getTpsMax() >= 100 ? ">" : "") + prisonTPS.getTPSMaxFormatted() ); - //fields.put( "tpsInterval", iFmt.format( PrisonTPS.SUBMIT_TICKS_INTERVAL ) ); - //fields.put( "tpsSamples", iFmt.format( prisonTPS.getTpsSamples() ) ); - - -// String tpsHistory = prisonTPS.getLastFewTPS(); -// if ( tpsHistory.length() > 0 ) { -// -// fields.put( "tpsHistory", prisonTPS.getLastFewTPS() ); -// } - + PrisonTPSSingleton prisonTPS = Prison.get().getPrisonTPS(); + + fields.put( "tps", prisonTPS.getAverageTPSFormatted() ); + fields.put( "tpsMin", prisonTPS.getTPSMinFormatted() ); + } private void getPrisonDiskSpaceUsage( ChatDisplay display, @@ -542,26 +530,22 @@ private void getPrisonDiskSpaceUsage( ChatDisplay display, public void getPrisonDiskSpaceUsage( LinkedHashMap fields ) { File prisonFolder = Prison.get().getDataFolder(); - PrisonDiskStats diskStats = new PrisonDiskStats(); - - // Increment folder count for prison's plugin folder: - diskStats.incrementFolderCount(); - - calculatePrisonDiskUsage( diskStats, prisonFolder ); - - DecimalFormat dFmt = getDecimalFormatDouble(); - DecimalFormat iFmt = getDecimalFormatInt(); - - String prisonFileCount = iFmt.format( diskStats.getFileCount() ); -// String prisonFolderCount = iFmt.format( diskStats.getFolderCount() ); - //String prisonOtherObjectCount = iFmt.format( diskStats.getOtherObjectCount() ); - String prisonStorageSize = PlaceholdersUtil.formattedIPrefixBinarySize( - diskStats.getStorageSize(), dFmt, " " ); - - fields.put( "prisonStorageFiles", prisonFileCount ); -// fields.put( "prisonStorageFolders", prisonFolderCount ); - fields.put( "prisonStorageSize", prisonStorageSize ); - //fields.put( "prisonStorageObjects", prisonOtherObjectCount ); + PrisonDiskStats diskStats = new PrisonDiskStats(); + + // Increment folder count for prison's plugin folder: + diskStats.incrementFolderCount(); + + calculatePrisonDiskUsage( diskStats, prisonFolder ); + + DecimalFormat dFmt = getDecimalFormatDouble(); + DecimalFormat iFmt = getDecimalFormatInt(); + + String prisonFileCount = iFmt.format( diskStats.getFileCount() ); + String prisonStorageSize = PlaceholdersUtil.formattedIPrefixBinarySize( + diskStats.getStorageSize(), dFmt, " " ); + + fields.put( "prisonStorageFiles", prisonFileCount ); + fields.put( "prisonStorageSize", prisonStorageSize ); } @@ -589,18 +573,18 @@ else if ( file.isFile() ) { public class PrisonDiskStats { - long fileCount = 0L; - long folderCount = 0L; - long otherObjectCount = 0L; - long storageSize = 0L; + long fileCount = 0L; + long folderCount = 0L; + long otherObjectCount = 0L; + long storageSize = 0L; - public PrisonDiskStats() { - super(); - } - - public void incrementFileCount() { - fileCount++; - } + public PrisonDiskStats() { + super(); + } + + public void incrementFileCount() { + fileCount++; + } public long getFileCount() { return fileCount; } @@ -642,7 +626,6 @@ public void setStorageSize( long storageSize ) { private boolean initDataFolder() { // Creates the /Prison directory, for core configuration. -// this.dataFolder = getPlatform().getPluginDirectory(); return this.dataFolder.exists() || this.dataFolder.mkdirs(); } @@ -678,15 +661,6 @@ private void initManagers() { this.integrationManager = new IntegrationManager(); this.placeholderManager = new PlaceholderManager(); - -// try { -// this.itemManager = new ItemManager(); -// } catch (Exception e) { -// this.errorManager.throwError(new Error( -// "Error while loading items.csv. Try running /prison troubleshoot item_scan.") -// .appendStackTrace("when loading items.csv", e)); -// Output.get().logError("Try running /prison troubleshoot item_scan."); -// } } private void registerInbuiltTroubleshooters() { @@ -695,15 +669,10 @@ private void registerInbuiltTroubleshooters() { private void scheduleAlertNagger() { - // Nag the users with the correct perms 5 mins after server starts, and every - // hour thereafter. - Alerts.getInstance().submitShowAlertsTask(); + // Nag the users with the correct perms 5 mins after server starts, and every + // hour thereafter. + Alerts.getInstance().submitShowAlertsTask(); -// // Nag the user with alerts every 5 minutes -// PrisonAPI.getScheduler().runTaskTimerAsync(() -> PrisonAPI.getOnlinePlayers().stream() -// .filter(player -> player.hasPermission("prison.admin") -// && Alerts.getInstance().getAlertsFor(player.getUUID()).size() > 0) -// .forEach(Alerts.getInstance()::showAlerts), 60 * 20 * 5, 60 * 20 * 5); } // End initialization steps @@ -716,7 +685,6 @@ public void deinit() { moduleManager.unregisterAll(); } - // Getters public String getMinecraftVersion() { @@ -724,34 +692,34 @@ public String getMinecraftVersion() } public List getMVersionMajMin() { - if ( versionMajMin == null ) { - - this.versionMajMin = new ArrayList<>(); - - String v = Prison.get().getMinecraftVersion(); - String versionStr = v.substring( v.indexOf( "(MC:" ) + 4, v.lastIndexOf( ")" ) ); - String[] vMN = versionStr.split( "\\." ); - - for ( int x = 0; x < vMN.length; x++ ) { - String ver = vMN[x]; + if ( versionMajMin == null ) { - try { - this.versionMajMin.add( - Integer.parseInt( ver.trim() ) ); - } - catch ( NumberFormatException e ) { - // ignore... just break out: - break; + this.versionMajMin = new ArrayList<>(); + + String v = Prison.get().getMinecraftVersion(); + String versionStr = v.substring( v.indexOf( "(MC:" ) + 4, v.lastIndexOf( ")" ) ); + String[] vMN = versionStr.split( "\\." ); + + for ( int x = 0; x < vMN.length; x++ ) { + String ver = vMN[x]; + + try { + this.versionMajMin.add( + Integer.parseInt( ver.trim() ) ); + } + catch ( NumberFormatException e ) { + // ignore... just break out: + break; + } } - } - -// Output.get().logInfo( "#### Prison.getMVersionMajMin() : " + -// ( versionMajMin != null && versionMajMin.size() > 0 ? versionMajMin.get(0) : "?" ) + " " + -// ( versionMajMin != null && versionMajMin.size() > 1 ? versionMajMin.get(1) : "?" ) + " " + -// ( versionMajMin != null && versionMajMin.size() > 2 ? versionMajMin.get(2) : "?" ) -// ); - } - return versionMajMin; + + // Output.get().logInfo( "#### Prison.getMVersionMajMin() : " + + // ( versionMajMin != null && versionMajMin.size() > 0 ? versionMajMin.get(0) : "?" ) + " " + + // ( versionMajMin != null && versionMajMin.size() > 1 ? versionMajMin.get(1) : "?" ) + " " + + // ( versionMajMin != null && versionMajMin.size() > 2 ? versionMajMin.get(2) : "?" ) + // ); + } + return versionMajMin; } @Override @@ -768,6 +736,17 @@ public String getName() { public Platform getPlatform() { return platform; } + + /** + * Do not use! + * This is for junit tests only to create and use a test fixture. + * DO NOT USE! + * + * @param platform + */ + public void setPlatform( Platform platform ) { + this.platform = platform; + } /** * Returns the core data folder, which is located at "/plugins/Prison". This contains the @@ -836,12 +815,6 @@ public SelectionManager getSelectionManager() { return selectionManager; } -// /** -// * Returns the item manager, which manages the "friendly" names of items -// */ -// public ItemManager getItemManager() { -// return itemManager; -// } /** * Returns the meta database, which is used to store data from within the core. @@ -869,7 +842,7 @@ public IntegrationManager getIntegrationManager() { * Returns the integration manager, which returns {@link tech.mcprison.prison.integration.Integration}s. */ public PlaceholderManager getPlaceholderManager() { - return placeholderManager; + return placeholderManager; } @@ -881,12 +854,12 @@ public void setServerStartupTime( long serverStartupTime ) { } public String getServerRuntimeFormatted() { - long currentTime = System.currentTimeMillis(); - long runtimeMs = currentTime - getServerStartupTime(); - return PlaceholdersUtil.formattedTime( runtimeMs / 1000 ); + long currentTime = System.currentTimeMillis(); + long runtimeMs = currentTime - getServerStartupTime(); + return PlaceholdersUtil.formattedTime( runtimeMs / 1000 ); } - public PrisonTPS getPrisonTPS() { + public PrisonTPSSingleton getPrisonTPS() { return prisonTPS; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonAPI.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonAPI.java index fbe6ade48..27eb52f8d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonAPI.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonAPI.java @@ -20,7 +20,6 @@ import tech.mcprison.prison.internal.scoreboard.ScoreboardManager; import tech.mcprison.prison.modules.ModuleManager; import tech.mcprison.prison.store.Storage; -import tech.mcprison.prison.troubleshoot.TroubleshootManager; import tech.mcprison.prison.util.Location; /** @@ -43,10 +42,6 @@ public static EventBus getEventBus() { return Prison.get().getEventBus(); } -// public static ItemManager getItemManager() { -// return Prison.get().getItemManager(); -// } - public static Optional getWorld(String name) { return Prison.get().getPlatform().getWorld(name); } @@ -88,18 +83,15 @@ public static void dispatchCommand(String cmd) { } public static void dispatchCommand(tech.mcprison.prison.internal.CommandSender sender, String cmd) { - Prison.get().getPlatform().dispatchCommand( sender, cmd); + Prison.get().getPlatform().dispatchCommand( sender, cmd); } public static Scheduler getScheduler() { return Prison.get().getPlatform().getScheduler(); } -// public static GUI createGUI(String title, int numRows) { -// return Prison.get().getPlatform().createGUI(title, numRows); -// } - - @Deprecated public static void toggleDoor(Location doorLocation) { + @Deprecated + public static void toggleDoor(Location doorLocation) { Prison.get().getPlatform().toggleDoor(doorLocation); } @@ -127,10 +119,6 @@ public static ScoreboardManager getScoreboardManager() { return Prison.get().getPlatform().getScoreboardManager(); } - public static TroubleshootManager getTroubleshootManager() { - return Prison.get().getTroubleshootManager(); - } - public static IntegrationManager getIntegrationManager() { return Prison.get().getIntegrationManager(); } 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 6eea9900f..9985eceea 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommand.java @@ -54,8 +54,6 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.output.Output.DebugTarget; import tech.mcprison.prison.placeholders.PlaceholdersStats; -import tech.mcprison.prison.troubleshoot.TroubleshootResult; -import tech.mcprison.prison.troubleshoot.Troubleshooter; import tech.mcprison.prison.util.PrisonJarReporter; /** @@ -93,24 +91,19 @@ public void versionCommand(CommandSender sender, @Wildcard(join=true) @Arg(name = "options", description = "Options [basic, all]", def = "basic" ) String options) { - if ( options != null && !"basic".equalsIgnoreCase( options ) && !"all".equalsIgnoreCase( options ) ) { - Output.get().logInfo( "&7Invalid option. [basic, all]" ); - return; - - } - else if ( options == null ) { - options = "basic"; - } + if ( options != null && !"basic".equalsIgnoreCase( options ) && !"all".equalsIgnoreCase( options ) ) { + Output.get().logInfo( "&7Invalid option. [basic, all]" ); + return; + + } + else if ( options == null ) { + options = "basic"; + } - ChatDisplay display = Prison.get().getPrisonStatsUtil().displayVersion(options); + ChatDisplay display = Prison.get().getPrisonStatsUtil().displayVersion(options); display.send(sender); -// if ( options != null && "all".equalsIgnoreCase( options )) { -// // Display all Ranks in each ladder: -// boolean includeAll = true; -// PrisonRanks.getInstance().getRankManager().ranksByLadders( includeAll ); -// } } /** @@ -125,31 +118,31 @@ else if ( options == null ) { * */ public class RegisteredPluginsData { - private String pluginName; - private String pluginVersion; - private List registeredCommands; - - private boolean registered = false; - private int aliasCount = 0; - - public RegisteredPluginsData( String pluginName, String pluginVersion, boolean registered ) { - super(); - - this.pluginName = pluginName; - this.pluginVersion = pluginVersion; - this.registered = registered; - - this.registeredCommands = new ArrayList<>(); - } - - public void addCommand( String commandName, List commandAliases ) { - RegisteredPluginCommandData command = - new RegisteredPluginCommandData( commandName, commandAliases ); - - getRegisteredCommands().add( command ); - - setAliasCount( getAliasCount() + commandAliases.size() ); - } + private String pluginName; + private String pluginVersion; + private List registeredCommands; + + private boolean registered = false; + private int aliasCount = 0; + + public RegisteredPluginsData( String pluginName, String pluginVersion, boolean registered ) { + super(); + + this.pluginName = pluginName; + this.pluginVersion = pluginVersion; + this.registered = registered; + + this.registeredCommands = new ArrayList<>(); + } + + public void addCommand( String commandName, List commandAliases ) { + RegisteredPluginCommandData command = + new RegisteredPluginCommandData( commandName, commandAliases ); + + getRegisteredCommands().add( command ); + + setAliasCount( getAliasCount() + commandAliases.size() ); + } public Object formatted() @@ -228,15 +221,15 @@ public void setAliasCount( int aliasCount ) { } public class RegisteredPluginCommandData { - private String command; - private List aliases; - - public RegisteredPluginCommandData( String command, List aliases ) { - super(); - - this.command = command; - this.aliases = aliases; - } + private String command; + private List aliases; + + public RegisteredPluginCommandData( String command, List aliases ) { + super(); + + this.command = command; + this.aliases = aliases; + } public String getCommand() { return command; @@ -254,196 +247,6 @@ public void setAliases( List aliases ) { } -// -// public ChatDisplay displayVersion(String options) { -// -// boolean isBasic = options == null || "basic".equalsIgnoreCase( options ); -// -// ChatDisplay display = new ChatDisplay("/prison version"); -// display.addText("&7Prison Version: %s", Prison.get().getPlatform().getPluginVersion()); -// -// display.addText("&7Running on Platform: %s", Prison.get().getPlatform().getClass().getName()); -// display.addText("&7Minecraft Version: %s", Prison.get().getMinecraftVersion()); -// -// -// // System stats: -// display.addText(""); -// -// Prison.get().displaySystemSettings( display ); -// -// Prison.get().displaySystemTPS( display ); -// -// -// display.addText(""); -// -// -// // This generates the module listing, the autoFeatures overview, -// // the integrations listings, and the plugins listings. -// boolean showLaddersAndRanks = true; -// Prison.get().getPlatform().prisonVersionFeatures( display, isBasic, showLaddersAndRanks ); -// -// -// -//// List features = Prison.get().getPlatform().getActiveFeatures(); -//// if ( features.size() > 0 ) { -//// -//// display.addText(""); -//// for ( String feature : features ) { -//// -//// if ( !feature.startsWith( "+" ) ) { -//// -//// display.addText( feature ); -//// } -//// else if ( !isBasic ) { -//// -//// display.addText( feature.substring( 1 ) ); -//// } -//// } -//// } -//// -//// -//// display.addText(""); -//// -//// // Active Modules: -//// display.addText("&7Prison's root Command: &3/prison"); -//// -//// for ( Module module : Prison.get().getModuleManager().getModules() ) { -//// -//// display.addText( "&7Module: %s : %s %s", module.getName(), -//// module.getStatus().getStatusText(), -//// (module.getStatus().getStatus() == ModuleStatus.Status.FAILED ? -//// "[" + module.getStatus().getMessage() + "]" : "") -//// ); -//// // display.addText( ". &7Base Commands: %s", module.getBaseCommands() ); -//// } -//// -//// List disabledModules = Prison.get().getModuleManager().getDisabledModules(); -//// if ( disabledModules.size() > 0 ) { -//// display.addText( "&7Disabled Module%s:", (disabledModules.size() > 1 ? "s" : "")); -//// for ( String disabledModule : Prison.get().getModuleManager().getDisabledModules() ) { -//// display.addText( ". &cDisabled Module:&7 %s. Related commands and placeholders are non-functional. ", -//// disabledModule ); -//// } -//// } -//// -//// display.addText(""); -//// display.addText("&7Integrations:"); -//// -//// IntegrationManager im = Prison.get().getIntegrationManager(); -//// String permissions = -//// (im.hasForType(IntegrationType.PERMISSION) ? -//// " " + im.getForType(IntegrationType.PERMISSION).get().getDisplayName() : -//// "None"); -//// -//// display.addText(". . &7Permissions: " + permissions); -//// -//// String economy = -//// (im.hasForType(IntegrationType.ECONOMY) ? -//// " " + im.getForType(IntegrationType.ECONOMY).get().getDisplayName() : -//// "None"); -//// -//// display.addText(". . &7Economy: " + economy); -//// -//// -//// List integrationRows = im.getIntegrationComponents( isBasic ); -//// for ( DisplayComponent component : integrationRows ) -//// { -//// display.addComponent( component ); -//// } -//// -//// -//// display.addText(""); -//// display.addText("&7Locale Settings:"); -//// -//// for ( String localeInfo : Prison.get().getLocaleLoadInfo() ) { -//// display.addText( ". . " + localeInfo ); -//// } -// -//// -//// Prison.get().getPlatform().identifyRegisteredPlugins(); -//// -//// // NOTE: This list of plugins is good enough and the detailed does not have all the info. -//// // Display all loaded plugins: -//// if ( getRegisteredPlugins().size() > 0 ) { -//// display.addText(""); -//// display.addText( "&7Registered Plugins: " ); -//// -//// List plugins = getRegisteredPlugins(); -//// Collections.sort( plugins ); -//// List plugins2Cols = Text.formatColumnsFromList( plugins, 2 ); -//// -//// for ( String rp : plugins2Cols ) { -//// -//// display.addText( rp ); -//// } -//// -////// StringBuilder sb = new StringBuilder(); -////// for ( String plugin : getRegisteredPlugins() ) { -////// if ( sb.length() == 0) { -////// sb.append( ". " ); -////// sb.append( plugin ); -////// } else { -////// sb.append( ", " ); -////// sb.append( plugin ); -////// display.addText( sb.toString() ); -////// sb.setLength( 0 ); -////// } -////// } -////// if ( sb.length() > 0 ) { -////// display.addText( sb.toString()); -////// } -//// } -//// -//// // This version of plugins does not have all the registered commands: -////// // The new plugin listings: -////// if ( getRegisteredPluginData().size() > 0 ) { -////// display.text( "&7Registered Plugins Detailed: " ); -////// StringBuilder sb = new StringBuilder(); -////// Set keys = getRegisteredPluginData().keySet(); -////// -////// for ( String key : keys ) { -////// RegisteredPluginsData plugin = getRegisteredPluginData().get(key); -////// -////// if ( sb.length() == 0) { -////// sb.append( " " ); -////// sb.append( plugin.formatted() ); -////// } else { -////// sb.append( ", " ); -////// sb.append( plugin.formatted() ); -////// display.text( sb.toString() ); -////// sb.setLength( 0 ); -////// } -////// } -////// if ( sb.length() > 0 ) { -////// display.text( sb.toString()); -////// } -////// } -//// -//// -////// RegisteredPluginsData plugin = getRegisteredPluginData().get( "Prison" ); -////// String pluginDetails = plugin.getdetails(); -////// -////// display.text( pluginDetails ); -//// -//// -////// if ( !isBasic ) { -////// Prison.get().getPlatform().dumpEventListenersBlockBreakEvents(); -////// } -//// -//// -//// Prison.get().getPlatform().getWorldLoadErrors( display ); -//// -//// if ( !isBasic && getPrisonStartupDetails().size() > 0 ) { -//// display.addText(""); -//// -//// for ( String msg : getPrisonStartupDetails() ) { -//// display.addText( msg ); -//// } -//// } -// -// return display; -// } - /** * A test to see if these dummy command placeholders could possibly lock out @@ -454,25 +257,25 @@ public void setAliases( List aliases ) { @Command(identifier = "prison", onlyPlayers = false, permissions = "prison.commands") public void prisonSubcommands(CommandSender sender) { - sender.dispatchCommand( "prison help" ); + sender.dispatchCommand( "prison help" ); } @Command(identifier = "prison placeholders", onlyPlayers = false, permissions = "prison.commands") public void prisonPlaceholdersSubcommands(CommandSender sender) { - sender.dispatchCommand( "prison placeholders help" ); + sender.dispatchCommand( "prison placeholders help" ); } @Command(identifier = "prison reload", onlyPlayers = false, permissions = "prison.commands") public void prisonReloadSubcommands(CommandSender sender) { - sender.dispatchCommand( "prison reload help" ); + sender.dispatchCommand( "prison reload help" ); } @Command(identifier = "prison utils", onlyPlayers = false, permissions = "prison.commands") public void prisonUtilsSubcommands(CommandSender sender) { - sender.dispatchCommand( "prison utils help" ); + sender.dispatchCommand( "prison utils help" ); } @@ -494,48 +297,6 @@ public void modulesCommand(CommandSender sender) { display.send(sender); } -// @Command(identifier = "prison troubleshoot", description = "Runs a troubleshooter.", -// onlyPlayers = false, permissions = "prison.troubleshoot") - public void troubleshootCommand(CommandSender sender, - @Arg(name = "name", def = "list", description = "The name of the troubleshooter.") String name) { - // They just want to list stuff - if (name.equals("list")) { - sender.dispatchCommand("prison troubleshoot list"); - return; - } - - TroubleshootResult result = - PrisonAPI.getTroubleshootManager().invokeTroubleshooter(name, sender); - if (result == null) { - Output.get().sendError(sender, "The troubleshooter %s doesn't exist.", name); - return; - } - - ChatDisplay display = new ChatDisplay("Result Summary"); - display.addText("&7Troubleshooter name: &b%s", name.toLowerCase()) // - .addText("&7Result type: &b%s", result.getResult().name()) // - .addText("&7Result details: &b%s", result.getDescription()) // - .send(sender); - - } - -// @Command(identifier = "prison troubleshoot list", description = "Lists the troubleshooters.", -// onlyPlayers = false, permissions = "prison.troubleshoot") - public void troubleshootListCommand(CommandSender sender) { - ChatDisplay display = new ChatDisplay("Troubleshooters"); - display.addText("&8Type /prison troubleshoot to run a troubleshooter."); - - BulletedListComponent.BulletedListBuilder builder = - new BulletedListComponent.BulletedListBuilder(); - for (Troubleshooter troubleshooter : PrisonAPI.getTroubleshootManager() - .getTroubleshooters()) { - builder.add("&b%s &8- &7%s", troubleshooter.getName(), troubleshooter.getDescription()); - } - display.addComponent(builder.build()); - - display.send(sender); - } - @Command(identifier = "prison placeholders test", description = "Converts any Prison placeholders in the test string to their values. " @@ -550,69 +311,69 @@ public void placeholdersTestCommand(CommandSender sender, description = "Placeholder text to test using { } as escape characters" ) String text ) { - if ( playerName != null && playerName.contains( "%" ) || - text != null && text.contains( "%" ) ) { - Output.get().logInfo( "&3You cannot use &7 %%%% &3 as escape characters. Use &7{&3 &7}&3 instead." ); - return; - } - - - // blank defaults do not work when there are more than one at a time. So had to - // default to periods. So convert periods to blanks initially: - playerName = (playerName.equals( "." ) ? "" : playerName ); - - // Try to get player from the supplied playerName first: - Player player = getPlayer( null, playerName ); - if ( player == null ) { - // No player found, or none specified. Need to shift parameters over by one: - if ( text != null && text.trim().length() > 0 ) { - - // playerName should be moved to the pageNumber, after pageNumber is moved to patterns: - text = (playerName.trim() + " " + text).trim(); - } - else { - text = playerName; - } - - // Try to get player from the sender: - player = getPlayer( sender ); - } - - boolean isShort = text.startsWith( "-s " ); - if ( isShort ) { - text = text.substring( 3 ); - } - - ChatDisplay display = new ChatDisplay("Placeholder Test"); - - BulletedListComponent.BulletedListBuilder builder = - new BulletedListComponent.BulletedListBuilder(); - - - UUID playerUuid = player == null ? null : player.getUUID(); - playerName = player != null ? player.getName() : - (playerName.isEmpty() ? sender.getName() : playerName); - - String translated = Prison.get().getPlatform().getPlaceholders() - .placeholderTranslateText( playerUuid, playerName, 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)); - - display.addComponent(builder.build()); - display.send(sender); + if ( playerName != null && playerName.contains( "%" ) || + text != null && text.contains( "%" ) ) { + Output.get().logInfo( "&3You cannot use &7 %%%% &3 as escape characters. Use &7{&3 &7}&3 instead." ); + return; + } + + + // blank defaults do not work when there are more than one at a time. So had to + // default to periods. So convert periods to blanks initially: + playerName = (playerName.equals( "." ) ? "" : playerName ); + + // Try to get player from the supplied playerName first: + Player player = getPlayer( null, playerName ); + if ( player == null ) { + // No player found, or none specified. Need to shift parameters over by one: + if ( text != null && text.trim().length() > 0 ) { + + // playerName should be moved to the pageNumber, after pageNumber is moved to patterns: + text = (playerName.trim() + " " + text).trim(); + } + else { + text = playerName; + } + + // Try to get player from the sender: + player = getPlayer( sender ); + } + + boolean isShort = text.startsWith( "-s " ); + if ( isShort ) { + text = text.substring( 3 ); + } + + ChatDisplay display = new ChatDisplay("Placeholder Test"); + + BulletedListComponent.BulletedListBuilder builder = + new BulletedListComponent.BulletedListBuilder(); + + + UUID playerUuid = player == null ? null : player.getUUID(); + playerName = player != null ? player.getName() : + (playerName.isEmpty() ? sender.getName() : playerName); + + String translated = Prison.get().getPlatform().getPlaceholders() + .placeholderTranslateText( playerUuid, playerName, 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)); + + display.addComponent(builder.build()); + display.send(sender); } private Player getPlayer( CommandSender sender ) { @@ -638,9 +399,11 @@ private Player getPlayer( CommandSender sender, String playerName ) { if ( playerName != null ) { Optional opt = Prison.get().getPlatform().getPlayer( playerName ); if ( !opt.isPresent() ) { - opt = Prison.get().getPlatform().getOfflinePlayer( playerName ); + + result = Prison.get().getPlatform().getRankPlayer( null, playerName ); } - if ( opt.isPresent() ) { + + else { result = opt.get(); } } @@ -659,58 +422,58 @@ public void placeholdersSearchCommand(CommandSender sender, - // blank defaults do not work when there are more than one at a time. So had to - // default to periods. So convert periods to blanks initially: - playerName = (playerName.equals( "." ) ? "" : playerName ); - pageNumber = (pageNumber.equals( "." ) ? "" : pageNumber ); - patterns = (patterns.equals( "." ) ? "" : patterns ); - - Player player = getPlayer( null, playerName ); - if ( player == null ) { - // No player found, or none specified. Need to shift parameters over by one: - if ( pageNumber != null && pageNumber.trim().length() > 0 ) { - - // playerName should be moved to the pageNumber, after pageNumber is moved to patterns: - patterns = (pageNumber.trim() + " " + patterns).trim(); - } - pageNumber = playerName; - } - - - int page = 1; - - /** - * Please note: Page is optional and defaults to a value of 1. But when it is not - * provided, it "grabs" the first pattern. So basically, if pageNumber proves not - * to be a number, then we must prefix whatever is in patterns with that value. - */ - if ( pageNumber != null ) { - - try { - page = Integer.parseInt( pageNumber ); + // blank defaults do not work when there are more than one at a time. So had to + // default to periods. So convert periods to blanks initially: + playerName = (playerName.equals( "." ) ? "" : playerName ); + pageNumber = (pageNumber.equals( "." ) ? "" : pageNumber ); + patterns = (patterns.equals( "." ) ? "" : patterns ); + + Player player = getPlayer( null, playerName ); + if ( player == null ) { + // No player found, or none specified. Need to shift parameters over by one: + if ( pageNumber != null && pageNumber.trim().length() > 0 ) { + + // playerName should be moved to the pageNumber, after pageNumber is moved to patterns: + patterns = (pageNumber.trim() + " " + patterns).trim(); + } + pageNumber = playerName; + } + + + int page = 1; + + /** + * Please note: Page is optional and defaults to a value of 1. But when it is not + * provided, it "grabs" the first pattern. So basically, if pageNumber proves not + * to be a number, then we must prefix whatever is in patterns with that value. + */ + if ( pageNumber != null ) { + + try { + page = Integer.parseInt( pageNumber ); } - catch ( NumberFormatException e ) { - // If exception, add pageNumber to the beginning patterns. - // So no page number was specified, it was part of the patterns - patterns = (pageNumber.trim() + " " + patterns).trim(); + catch ( NumberFormatException e ) { + // If exception, add pageNumber to the beginning patterns. + // So no page number was specified, it was part of the patterns + patterns = (pageNumber.trim() + " " + patterns).trim(); } - - } - - - // Cannot allow pages less than 1: - if ( page < 1 ) { - page = 1; - } - - ChatDisplay display = new ChatDisplay("Placeholders Search"); - - - if ( patterns == null || patterns.trim().length() == 0 ) { - sender.sendMessage( "&7Pattern required. Placeholder results must match all pattern terms." ); - return; - } - + + } + + + // Cannot allow pages less than 1: + if ( page < 1 ) { + page = 1; + } + + ChatDisplay display = new ChatDisplay("Placeholders Search"); + + + if ( patterns == null || patterns.trim().length() == 0 ) { + sender.sendMessage( "&7Pattern required. Placeholder results must match all pattern terms." ); + return; + } + BulletedListComponent.BulletedListBuilder builder = new BulletedListComponent.BulletedListBuilder(); @@ -738,30 +501,30 @@ public void placeholdersSearchCommand(CommandSender sender, DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); builder.add( String.format( "&7 Results: &c%s &7Original patterns: &3%s", - dFmt.format(placeholders.size()), patterns )); + dFmt.format(placeholders.size()), patterns )); CommandPagedData cmdPageData = new CommandPagedData( - "/prison placeholders search", placeholders.size(), - 0, Integer.toString( page ), 20 ); + "/prison placeholders search", placeholders.size(), + 0, Integer.toString( page ), 20 ); // Need to provide more "parts" to the command that follows the page number: cmdPageData.setPageCommandSuffix( patterns ); int count = 0; - for ( String placeholder : placeholders ) { - if ( cmdPageData == null || - count++ >= cmdPageData.getPageStart() && - count <= cmdPageData.getPageEnd() ) { - - builder.add( String.format( placeholder )); - } + for ( String placeholder : placeholders ) { + if ( cmdPageData == null || + count++ >= cmdPageData.getPageStart() && + count <= cmdPageData.getPageEnd() ) { + + builder.add( String.format( placeholder )); + } } - display.addComponent(builder.build()); - - cmdPageData.generatePagedCommandFooter( display ); - - display.send(sender); + display.addComponent(builder.build()); + + cmdPageData.generatePagedCommandFooter( display ); + + display.send(sender); } @@ -771,27 +534,27 @@ public void placeholdersSearchCommand(CommandSender sender, public void placeholdersListCommand(CommandSender sender ) { - ChatDisplay display = new ChatDisplay("Placeholders List"); - - display.addText( "&a Placeholders are case insensitive, but are registered in all lowercase."); - display.addText( "&a Placeholder escape characters may be { } or % %. If one does not work, try the other."); - display.addText( "&a Placeholders that include 'rankname', 'laddername', or 'minename' should be"); - display.addText( "&a replaced with the appropriate rank names, ladder names, or mine names."); - - for ( String disabledModule : Prison.get().getModuleManager().getDisabledModules() ) { - display.addText( "&a &cDisabled Module: &7%s&a. Related placeholders maybe listed but are non-functional. ", - disabledModule ); - } - - List placeholders = new ArrayList<>(); - Prison.get().getIntegrationManager().getPlaceholderTemplateList( placeholders ); - - - for ( DisplayComponent placeholder : placeholders ) { - display.addComponent( placeholder ); - } - - display.send(sender); + ChatDisplay display = new ChatDisplay("Placeholders List"); + + display.addText( "&a Placeholders are case insensitive, but are registered in all lowercase."); + display.addText( "&a Placeholder escape characters may be { } or % %. If one does not work, try the other."); + display.addText( "&a Placeholders that include 'rankname', 'laddername', or 'minename' should be"); + display.addText( "&a replaced with the appropriate rank names, ladder names, or mine names."); + + for ( String disabledModule : Prison.get().getModuleManager().getDisabledModules() ) { + display.addText( "&a &cDisabled Module: &7%s&a. Related placeholders maybe listed but are non-functional. ", + disabledModule ); + } + + List placeholders = new ArrayList<>(); + Prison.get().getIntegrationManager().getPlaceholderTemplateList( placeholders ); + + + for ( DisplayComponent placeholder : placeholders ) { + display.addComponent( placeholder ); + } + + display.send(sender); } @@ -807,43 +570,45 @@ public void placeholdersStatsCommand(CommandSender sender, def = "." ) String options ) { - ChatDisplay display = new ChatDisplay("Placeholders List"); - - if ( options != null && !".".equals(options) ) { - boolean resetCache = "resetCache".equalsIgnoreCase( options ); - boolean removeErrors = "removeErrors".equalsIgnoreCase( options ); - - PlaceholdersStats.getInstance().clearCache( resetCache, removeErrors ); - } - - ArrayList stats = PlaceholdersStats.getInstance().generatePlaceholderReport(); - - for (String stat : stats) { - display.addText( stat.replace( "%", "%%") ); - } - - - display.send(sender); + ChatDisplay display = new ChatDisplay("Placeholders List"); + + if ( options != null && !".".equals(options) ) { + boolean resetCache = "resetCache".equalsIgnoreCase( options ); + boolean removeErrors = "removeErrors".equalsIgnoreCase( options ); + + PlaceholdersStats.getInstance().clearCache( resetCache, removeErrors ); + } + + ArrayList stats = PlaceholdersStats.getInstance().generatePlaceholderReport(); + + for (String stat : stats) { + display.addText( stat.replace( "%", "%%") ); + } + + + display.send(sender); } - @Command(identifier = "prison reload placeholders", - description = "Placeholder reload: Regenerates all placeholders and reregisters them.", - onlyPlayers = false, permissions = "prison.placeholder") - public void placeholdersReloadCommandAlias(CommandSender sender ) { - placeholdersReloadCommand( sender ); - } @Command(identifier = "prison placeholders reload", - description = "Placeholder reload: Regenerates all placeholders and reregisters them.", - onlyPlayers = false, permissions = "prison.placeholder") + description = "Placeholder reload: Regenerates all placeholders and reregisters them. " + + "&dThis also forces the config.yml properties to be reloaded too, but be warned, " + + "it will not force anything that uses config.yml to be reloaded and you may " + + "still have to restart the server.", + onlyPlayers = false, + permissions = "prison.placeholder", + aliases = { + "prison reload configyml", + "prison reload placeholders" + } ) public void placeholdersReloadCommand(CommandSender sender ) { - Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); - - String message = "Placeholder reload was attempted. " + - "No guarentees that it worked 100%. Restart server if any doubts."; - - sender.sendMessage( message ); + Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); + + String message = "Placeholder and config.yml reload was attempted. " + + "No guarentees that it worked 100%. Restart server if any doubts."; + + sender.sendMessage( message ); } @@ -853,14 +618,14 @@ public void placeholdersReloadCommand(CommandSender sender ) { onlyPlayers = false, permissions = "prison.reload") public void localesReloadCommand(CommandSender sender ) { - for ( LocaleManager LocalManager : LocaleManager.getRegisteredInstances() ) { - LocalManager.reload(); - } - - String message = "Locales reload was attempted. " + - "No guarentees that it worked 100%. Restart server if any doubts."; - - sender.sendMessage( message ); + for ( LocaleManager LocalManager : LocaleManager.getRegisteredInstances() ) { + LocalManager.reload(); + } + + String message = "Locales reload was attempted. " + + "No guarentees that it worked 100%. Restart server if any doubts."; + + sender.sendMessage( message ); } @@ -868,37 +633,21 @@ public void localesReloadCommand(CommandSender sender ) { description = "AutoFeatures reload: Reloads the auto features settings. The current " + "settings will be discarded before reloading the configuration file.", onlyPlayers = false, permissions = "prison.autofeatures") - public void reloadAutoFeatures(CommandSender sender ) { - - AutoFeaturesWrapper.getInstance().reloadConfigs(); - - String message = "&7AutoFeatures were reloaded. The new settings are now in effect. "; - sender.sendMessage( message ); - - try { - String filePath = AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig() - .getConfigFile().getCanonicalPath(); - sender.sendMessage( filePath ); - } - catch ( IOException e ) { - // Ignore - } -// 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 -// } + public void reloadAutoFeatures(CommandSender sender ) { + + AutoFeaturesWrapper.getInstance().reloadConfigs(); + + String message = "&7AutoFeatures were reloaded. The new settings are now in effect. "; + sender.sendMessage( message ); + + try { + String filePath = AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig() + .getConfigFile().getCanonicalPath(); + sender.sendMessage( filePath ); + } + catch ( IOException e ) { + // Ignore + } } @@ -908,26 +657,26 @@ public void reloadAutoFeatures(CommandSender sender ) { onlyPlayers = false, permissions = "prison.autofeatures") public void reloadBlockConverters(CommandSender sender ) { - if ( AutoFeaturesWrapper.getBlockConvertersInstance() != null ) { - - 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 - } - - } + if ( AutoFeaturesWrapper.getBlockConvertersInstance() != null ) { + + 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 + } + + } } @@ -953,169 +702,205 @@ public void reloadBlockConverters(CommandSender sender ) { // "prison.autofeatures.block" }) public void autoFeaturesInformation(CommandSender sender) { - ChatDisplay display = new ChatDisplay("Auto Features Information"); - - display.addText( "&a Prison auto features provide the following options:"); - display.addText( "&7 Auto pickup - &aUpon block break, items are placed directly in to player inventory."); - display.addText( "&a - Features for enabling XP, Durability, and Fortune are within the config file."); - display.addText( "&7 Auto smelt - &aItems that can be smelted will be smelted automatically."); - display.addText( "&7 Auto block - &aConverts ores to blocks."); - display.addText( "&7 Tool lore starts with: Pickup, Smelt, or Block. Only one per line." ); - display.addText( "&7 Tool lore names can be customize in config file, but color codes could be an issue." ); - display.addText( "&7 Tool lore 100 percent with just name. Can have value 0.001 to 100.0 percent." ); - display.addText( "&7 Tool lore examples: Pickup, Pickup 7.13, Smelt 55, Block 75.123" ); - - display.addText( "&a To configure modify plugin/Prison/autoFeaturesConfig.yml"); - display.addText( "&a Or better yet, you can use the &7/prison gui"); - - display.addText( "&a"); - display.addText( "&aPrison supports TokenEnchant's explosion based enchants. Please see our online " + - "documentation related to WorldGuard and LuckPerms with protecting mines (its near the bottom). " + - "TE's configurations may not be obvious without reading the document."); - display.addText( "&a"); - display.addText( "&aPrison also supports Crazy Enchant's explosion based enchantments too. "); - - - List afs = AutoFeatures.permissions.getChildren(); - StringBuilder sb = new StringBuilder(); - for ( AutoFeatures af : afs ) { - if ( sb.length() > 0 ) { - sb.append( " " ); + ChatDisplay display = new ChatDisplay("Auto Features Information"); + + display.addText( "&a Prison auto features provide the following options:"); + display.addText( "&7 Auto pickup - &aUpon block break, items are placed directly in to player inventory."); + display.addText( "&a - Features for enabling XP, Durability, and Fortune are within the config file."); + display.addText( "&7 Auto smelt - &aItems that can be smelted will be smelted automatically."); + display.addText( "&7 Auto block - &aConverts ores to blocks."); + display.addText( "&7 Tool lore starts with: Pickup, Smelt, or Block. Only one per line." ); + display.addText( "&7 Tool lore names can be customize in config file, but color codes could be an issue." ); + display.addText( "&7 Tool lore 100 percent with just name. Can have value 0.001 to 100.0 percent." ); + display.addText( "&7 Tool lore examples: Pickup, Pickup 7.13, Smelt 55, Block 75.123" ); + + display.addText( "&a To configure modify plugin/Prison/autoFeaturesConfig.yml"); + display.addText( "&a Or better yet, you can use the &7/prison gui"); + + display.addText( "&a"); + display.addText( "&aPrison supports TokenEnchant's explosion based enchants. Please see our online " + + "documentation related to WorldGuard and LuckPerms with protecting mines (its near the bottom). " + + "TE's configurations may not be obvious without reading the document."); + display.addText( "&a"); + display.addText( "&aPrison also supports Crazy Enchant's explosion based enchantments too. "); + + + List afs = AutoFeatures.permissions.getChildren(); + StringBuilder sb = new StringBuilder(); + for ( AutoFeatures af : afs ) { + if ( sb.length() > 0 ) { + sb.append( " " ); + } + sb.append( af.getMessage() ); } - sb.append( af.getMessage() ); - } - display.addText( "&3Permissions:" ); - display.addText( "&b %s", sb.toString() ); - display.addText( "&7 NOTE: Permissions enables that feature even if disabled for mines." ); - display.addText( " " ); - - - - AutoFeaturesWrapper afw = AutoFeaturesWrapper.getInstance(); - - display.addText( "&3Selected Settings from &bplugins/Prison/autoFeaturesConfigs.yml&3:" ); - display.addText( "&b " ); - display.addText( "&b options.general.isAutoManagerEnabled %s", - afw.isBoolean( AutoFeatures.isAutoManagerEnabled )); - - - if ( afw.isBoolean( AutoFeatures.isAutoManagerEnabled ) ) { - - - display.addText( "&b " ); - display.addText( "&b options.blockBreakEvents.applyBlockBreaksThroughSyncTask: %s", - afw.getMessage( AutoFeatures.applyBlockBreaksThroughSyncTask ) ); - - display.addText( "&b options.blockBreakEvents.cancelAllBlockBreakEvents: %s", - afw.getMessage( AutoFeatures.cancelAllBlockBreakEvents ) ); - - display.addText( "&b options.blockBreakEvents.cancelAllBlockEventBlockDrops: %s", - afw.getMessage( AutoFeatures.cancelAllBlockEventBlockDrops ) ); - - - display.addText( "&b options.blockBreakEvents.TokenEnchantBlockExplodeEventPriority: %s", - afw.getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ) ); - - display.addText( "&b options.blockBreakEvents.CrazyEnchantsBlastUseEventPriority: %s", - afw.getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ) ); - - display.addText( "&b options.blockBreakEvents.RevEnchantsExplosiveEventPriority: %s", - afw.getMessage( AutoFeatures.RevEnchantsExplosiveEventPriority ) ); - - display.addText( "&b options.blockBreakEvents.RevEnchantsJackHammerEventPriority: %s", - afw.getMessage( AutoFeatures.RevEnchantsJackHammerEventPriority ) ); - - display.addText( "&b options.blockBreakEvents.ZenchantmentsBlockShredEventPriority: %s", - afw.getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ) ); - - display.addText( "&b options.blockBreakEvents.PrisonEnchantsExplosiveEventPriority: %s", - afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ) ); - - display.addText( "&b options.blockBreakEvents.ProcessPrisons_ExplosiveBlockBreakEventsPriority: %s", - afw.getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ) ); - - - - display.addText( "&b " ); - display.addText( "&b Normal Drops (if auto pickup is off):" ); - display.addText( "&b options.normalDrop.isProcessNormalDropsEvents: %s", - afw.isBoolean( AutoFeatures.handleNormalDropsEvents ) ); - - display.addText( "&b " ); - display.addText( "&7 NOTE: If this is enabled, then lore and perms will override the settings for " ); - display.addText( "&7 pickup, smelt, and block when they are turned off." ); - - - display.addText( "&b " ); - - - display.addText( "&b options.autoPickup.autoPickupEnabled %s", - afw.isBoolean( AutoFeatures.autoPickupEnabled )); - - display.addText( "&b options.autoSmelt.autoSmeltEnabled %s", - afw.isBoolean( AutoFeatures.autoSmeltEnabled )); - display.addText( "&b options.autoBlock.autoBlockEnabled %s", - afw.isBoolean( AutoFeatures.autoBlockEnabled )); - - - display.addText( "&b " ); - display.addText( "&b options.normalDrop.handleNormalDropsEvents %s", - afw.isBoolean( AutoFeatures.handleNormalDropsEvents )); - display.addText( "&b options.normalDrop.normalDropSmelt %s", - afw.isBoolean( AutoFeatures.normalDropSmelt )); - display.addText( "&b options.normalDrop.normalDropSmelt %s", - afw.isBoolean( AutoFeatures.normalDropSmelt )); - display.addText( "&b options.normalDrop.normalDropCheckForFullInventory %s", - afw.isBoolean( AutoFeatures.normalDropCheckForFullInventory )); - - - - display.addText( "&b " ); - display.addText( "&b options.general.isCalculateDurabilityEnabled %s", - afw.isBoolean( AutoFeatures.isCalculateDurabilityEnabled )); - display.addText( "&b options.general.isCalculateFortuneEnabled %s", - afw.isBoolean( AutoFeatures.isCalculateFortuneEnabled )); - display.addText( "&b options.general.isCalculateAltFortuneOnAllBlocksEnabled %s", - afw.isBoolean( AutoFeatures.isCalculateAltFortuneOnAllBlocksEnabled )); - display.addText( "&b options.general.isCalculateXPEnabled %s", - afw.isBoolean( AutoFeatures.isCalculateXPEnabled )); - display.addText( "&b options.general.givePlayerXPAsOrbDrops %s", - afw.isBoolean( AutoFeatures.givePlayerXPAsOrbDrops )); - display.addText( "&b options.general.fortuneMultiplierGlobal %s", - afw.getMessage( AutoFeatures.fortuneMultiplierGlobal )); - display.addText( "&b options.general.fortuneMultiplierMax %s", - afw.getMessage( AutoFeatures.fortuneMultiplierMax )); - - display.addText( "&b " ); - display.addText( "&b options.isProcessMcMMOBlockBreakEvents %s", - afw.isBoolean( AutoFeatures.isProcessMcMMOBlockBreakEvents )); - display.addText( "&b options.isProcessEZBlocksBlockBreakEvents %s", - afw.isBoolean( AutoFeatures.isProcessEZBlocksBlockBreakEvents )); - display.addText( "&b options.isProcessQuestsBlockBreakEvents %s", - afw.isBoolean( AutoFeatures.isProcessQuestsBlockBreakEvents )); - display.addText( "&b " ); - - - display.addText( "&b " ); - display.addText( "&b options.lore.isLoreEnabled %s", - afw.isBoolean( AutoFeatures.isLoreEnabled )); - display.addText( "&b options.lore.loreTrackBlockBreakCount %s", - afw.isBoolean( AutoFeatures.loreTrackBlockBreakCount )); - display.addText( "&b options.lore.loreBlockBreakCountName %s", - afw.getMessage( AutoFeatures.loreBlockBreakCountName )); - - display.addText( "&b options.lore.loreBlockExplosionCountName %s", - afw.getMessage( AutoFeatures.loreBlockExplosionCountName )); - display.addText( "&b options.lore.loreDurabiltyResistance %s", - afw.isBoolean( AutoFeatures.loreDurabiltyResistance )); - display.addText( "&b options.lore.loreDurabiltyResistanceName %s", - afw.getMessage( AutoFeatures.loreDurabiltyResistanceName )); - display.addText( "&b " ); - } - - - - display.send(sender); + display.addText( "&3Permissions:" ); + display.addText( "&b %s", sb.toString() ); + display.addText( "&7 NOTE: Permissions enables that feature even if disabled for mines." ); + display.addText( " " ); + + + + AutoFeaturesWrapper afw = AutoFeaturesWrapper.getInstance(); + + display.addText( "&3Selected Settings from &bplugins/Prison/autoFeaturesConfigs.yml&3:" ); + display.addText( "&b " ); + display.addText( "&b options.general.isAutoManagerEnabled %s", + afw.isBoolean( AutoFeatures.isAutoManagerEnabled )); + + + if ( afw.isBoolean( AutoFeatures.isAutoManagerEnabled ) ) { + + + display.addText( "&b " ); + display.addText( "&b options.blockBreakEvents.applyBlockBreaksThroughSyncTask: %s", + afw.getMessage( AutoFeatures.applyBlockBreaksThroughSyncTask ) ); + + display.addText( "&b options.blockBreakEvents.cancelAllBlockBreakEvents: %s", + afw.getMessage( AutoFeatures.cancelAllBlockBreakEvents ) ); + + display.addText( "&b options.blockBreakEvents.cancelAllBlockEventBlockDrops: %s", + afw.getMessage( AutoFeatures.cancelAllBlockEventBlockDrops ) ); + + + display.addText( "&b options.blockBreakEvents.TokenEnchantBlockExplodeEventPriority: %s", + afw.getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ) ); + + display.addText( "&b options.blockBreakEvents.CrazyEnchantsBlastUseEventPriority: %s", + afw.getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ) ); + + display.addText( "&b options.blockBreakEvents.RevEnchantsExplosiveEventPriority: %s", + afw.getMessage( AutoFeatures.RevEnchantsExplosiveEventPriority ) ); + + display.addText( "&b options.blockBreakEvents.RevEnchantsJackHammerEventPriority: %s", + afw.getMessage( AutoFeatures.RevEnchantsJackHammerEventPriority ) ); + + display.addText( "&b options.blockBreakEvents.ZenchantmentsBlockShredEventPriority: %s", + afw.getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ) ); + + display.addText( "&b options.blockBreakEvents.PrisonEnchantsExplosiveEventPriority: %s", + afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ) ); + + display.addText( "&b options.blockBreakEvents.ProcessPrisons_ExplosiveBlockBreakEventsPriority: %s", + afw.getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ) ); + + + + display.addText( "&b " ); + display.addText( "&b Normal Drops (if auto pickup is off):" ); + display.addText( "&b options.normalDrop.isProcessNormalDropsEvents: %s", + afw.isBoolean( AutoFeatures.handleNormalDropsEvents ) ); + + display.addText( "&b " ); + display.addText( "&7 NOTE: If this is enabled, then lore and perms will override the settings for " ); + display.addText( "&7 pickup, smelt, and block when they are turned off." ); + + + display.addText( "&b " ); + + + display.addText( "&b options.autoPickup.autoPickupEnabled %s", + afw.isBoolean( AutoFeatures.autoPickupEnabled )); + + display.addText( "&b options.autoSmelt.autoSmeltEnabled %s", + afw.isBoolean( AutoFeatures.autoSmeltEnabled )); + display.addText( "&b options.autoBlock.autoBlockEnabled %s", + afw.isBoolean( AutoFeatures.autoBlockEnabled )); + + + display.addText( "&b " ); + display.addText( "&b options.normalDrop.handleNormalDropsEvents %s", + afw.isBoolean( AutoFeatures.handleNormalDropsEvents )); + display.addText( "&b options.normalDrop.normalDropSmelt %s", + afw.isBoolean( AutoFeatures.normalDropSmelt )); + display.addText( "&b options.normalDrop.normalDropSmelt %s", + afw.isBoolean( AutoFeatures.normalDropSmelt )); + display.addText( "&b options.normalDrop.normalDropCheckForFullInventory %s", + afw.isBoolean( AutoFeatures.normalDropCheckForFullInventory )); + + + + display.addText( "&b " ); + display.addText( "&b options.lore.isLoreEnabled %s", + afw.isBoolean( AutoFeatures.isLoreEnabled )); + display.addText( "&b options.lore.lorePickupValue %s", + afw.isBoolean( AutoFeatures.lorePickupValue )); + display.addText( "&b options.lore.loreSmeltValue %s", + afw.isBoolean( AutoFeatures.loreSmeltValue )); + display.addText( "&b options.lore.loreBlockValue %s", + afw.isBoolean( AutoFeatures.loreBlockValue )); + + + + + display.addText( "&b " ); + display.addText( "&b options.customEnchants.isCustomEnchantsEnabled %s", + afw.isBoolean( AutoFeatures.isCustomEnchantsEnabled )); + display.addText( "&b options.customEnchants.customEnchantsAutoPickup %s", + afw.isBoolean( AutoFeatures.customEnchantsAutoPickup )); + display.addText( "&b options.customEnchants.customEnchantsAutoSmelt %s", + afw.isBoolean( AutoFeatures.customEnchantsAutoSmelt )); + display.addText( "&b options.customEnchants.customEnchantsAutoBlock %s", + afw.isBoolean( AutoFeatures.customEnchantsAutoBlock )); + + + + + display.addText( "&b " ); + display.addText( "&b options.inventory.includePlayerInventoryWhenSmelting %s", + afw.isBoolean( AutoFeatures.includePlayerInventoryWhenSmelting )); + display.addText( "&b options.inventory.includePlayerInventoryWhenBlocking %s", + afw.isBoolean( AutoFeatures.includePlayerInventoryWhenBlocking )); + + + + + display.addText( "&b " ); + display.addText( "&b options.general.isCalculateDurabilityEnabled %s", + afw.isBoolean( AutoFeatures.isCalculateDurabilityEnabled )); + display.addText( "&b options.general.isCalculateFortuneEnabled %s", + afw.isBoolean( AutoFeatures.isCalculateFortuneEnabled )); + display.addText( "&b options.general.isCalculateAltFortuneOnAllBlocksEnabled %s", + afw.isBoolean( AutoFeatures.isCalculateAltFortuneOnAllBlocksEnabled )); + display.addText( "&b options.general.isCalculateXPEnabled %s", + afw.isBoolean( AutoFeatures.isCalculateXPEnabled )); + display.addText( "&b options.general.givePlayerXPAsOrbDrops %s", + afw.isBoolean( AutoFeatures.givePlayerXPAsOrbDrops )); + display.addText( "&b options.general.fortuneMultiplierGlobal %s", + afw.getMessage( AutoFeatures.fortuneMultiplierGlobal )); + display.addText( "&b options.general.fortuneMultiplierMax %s", + afw.getMessage( AutoFeatures.fortuneMultiplierMax )); + + + display.addText( "&b " ); + display.addText( "&b options.isProcessMcMMOBlockBreakEvents %s", + afw.isBoolean( AutoFeatures.isProcessMcMMOBlockBreakEvents )); + display.addText( "&b options.isProcessEZBlocksBlockBreakEvents %s", + afw.isBoolean( AutoFeatures.isProcessEZBlocksBlockBreakEvents )); + display.addText( "&b options.isProcessQuestsBlockBreakEvents %s", + afw.isBoolean( AutoFeatures.isProcessQuestsBlockBreakEvents )); + display.addText( "&b " ); + + + display.addText( "&b " ); + display.addText( "&b options.lore.isLoreEnabled %s", + afw.isBoolean( AutoFeatures.isLoreEnabled )); + display.addText( "&b options.lore.loreTrackBlockBreakCount %s", + afw.isBoolean( AutoFeatures.loreTrackBlockBreakCount )); + display.addText( "&b options.lore.loreBlockBreakCountName %s", + afw.getMessage( AutoFeatures.loreBlockBreakCountName )); + + display.addText( "&b options.lore.loreBlockExplosionCountName %s", + afw.getMessage( AutoFeatures.loreBlockExplosionCountName )); + display.addText( "&b options.lore.loreDurabiltyResistance %s", + afw.isBoolean( AutoFeatures.loreDurabiltyResistance )); + display.addText( "&b options.lore.loreDurabiltyResistanceName %s", + afw.getMessage( AutoFeatures.loreDurabiltyResistanceName )); + display.addText( "&b " ); + } + + + + display.send(sender); // altPermissions are now a part of this command. // // After displaying the help information above, rerun the same command for the player @@ -1150,7 +935,7 @@ public void toggleDebug(CommandSender sender, "5 debug messages for that player, then debug mode will be disabled. " ) String targets ) { - String playerName = null; + String playerName = null; String playerStr = extractParameter("player=", targets); if ( playerStr != null ) { @@ -1170,66 +955,66 @@ public void toggleDebug(CommandSender sender, } } - if ( targets != null && "jarScan".equalsIgnoreCase( targets ) ) { - - PrisonJarReporter pjr = new PrisonJarReporter(); - pjr.scanForJars(); - pjr.dumpJarDetails(); - - return; - } - - - if ( targets != null && "testLocale".equalsIgnoreCase( targets ) ) { - - coreDebugTestLocaleseMsg( sender ); - - return; - } - - if ( targets != null && "testPlayerUtil".equalsIgnoreCase( targets ) ) { - - Player player = getPlayer( sender, "RoyalBlueRanger" ); - Prison.get().getPlatform().testPlayerUtil( player.getUUID() ); - - return; - } - - // Applies normal and selective targets: - Output.get().applyDebugTargets( targets ); - - String message = "&7Global Debug Logging is " + (Output.get().isDebug() ? "&3enabled" : "&cdisabled"); - sender.sendMessage( message ); - - Set activeDebugTargets = Output.get().getActiveDebugTargets(); - - if ( activeDebugTargets.size() > 0 ) { - message = ". Note: Active Debug Targets:"; - sender.sendMessage( message ); - - for ( DebugTarget target : activeDebugTargets ) - { - message = String.format( ". . Target: %s", target.name() ); - sender.sendMessage( message ); - } - } - - Set selectiveDebugTargets = Output.get().getSelectiveDebugTargets(); - - if ( selectiveDebugTargets.size() > 0 ) { - message = ". Selective Debug Targets:"; - sender.sendMessage( message ); - - for ( DebugTarget target : selectiveDebugTargets ) - { - message = String.format( ". . Target: %s", target.name() ); - sender.sendMessage( message ); - } - } - - String validTargets = Output.get().getDebugTargetsString(); - message = String.format( ". Valid Targets: %s", validTargets ); - sender.sendMessage( message ); + if ( targets != null && "jarScan".equalsIgnoreCase( targets ) ) { + + PrisonJarReporter pjr = new PrisonJarReporter(); + pjr.scanForJars(); + pjr.dumpJarDetails(); + + return; + } + + + if ( targets != null && "testLocale".equalsIgnoreCase( targets ) ) { + + coreDebugTestLocaleseMsg( sender ); + + return; + } + + if ( targets != null && "testPlayerUtil".equalsIgnoreCase( targets ) ) { + + Player player = getPlayer( sender, "RoyalBlueRanger" ); + Prison.get().getPlatform().testPlayerUtil( player.getUUID() ); + + return; + } + + // Applies normal and selective targets: + Output.get().applyDebugTargets( targets ); + + String message = "&7Global Debug Logging is " + (Output.get().isDebug() ? "&3enabled" : "&cdisabled"); + sender.sendMessage( message ); + + Set activeDebugTargets = Output.get().getActiveDebugTargets(); + + if ( activeDebugTargets.size() > 0 ) { + message = ". Note: Active Debug Targets:"; + sender.sendMessage( message ); + + for ( DebugTarget target : activeDebugTargets ) + { + message = String.format( ". . Target: %s", target.name() ); + sender.sendMessage( message ); + } + } + + Set selectiveDebugTargets = Output.get().getSelectiveDebugTargets(); + + if ( selectiveDebugTargets.size() > 0 ) { + message = ". Selective Debug Targets:"; + sender.sendMessage( message ); + + for ( DebugTarget target : selectiveDebugTargets ) + { + message = String.format( ". . Target: %s", target.name() ); + sender.sendMessage( message ); + } + } + + String validTargets = Output.get().getDebugTargetsString(); + message = String.format( ". Valid Targets: %s", validTargets ); + sender.sendMessage( message ); } @@ -1267,10 +1052,10 @@ public void findCommand(CommandSender sender, @Arg(name = "command", description = "The command to search for" ) String command ) { - String registered = Prison.get().getCommandHandler().findRegisteredCommand( command ); - - Output.get().logInfo( "&7Prison Find Registered Command: original= &3%s &7registered= &3%s", - command, registered ); + String registered = Prison.get().getCommandHandler().findRegisteredCommand( command ); + + Output.get().logInfo( "&7Prison Find Registered Command: original= &3%s &7registered= &3%s", + command, registered ); } @@ -1280,10 +1065,10 @@ public void findCommand(CommandSender sender, onlyPlayers = false, permissions = "prison.debug" ) public void statsCommand(CommandSender sender ) { - List cmds = getCommandStats(); - for (String cmd : cmds) { - - Output.get().logInfo( cmd ); + List cmds = getCommandStats(); + for (String cmd : cmds) { + + Output.get().logInfo( cmd ); } } @@ -1293,43 +1078,47 @@ private List getCommandStats() { 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(); - } + 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%7s&r &a&n%-11s&r", + " Commands ", " Usage "," Alias ", " Avg ms ") ); + + int count = 0; + int totals = 0; + int totalsAlias = 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%7s &2%11s", + cmd.getCompleteLabel(), + iFmt.format( cmd.getUsageCount() ), + iFmt.format( cmd.getUsageCountAlias() ), + dFmt.format( duration ) + ) ); + count++; + totals += cmd.getUsageCount(); + totalsAlias += cmd.getUsageCountAlias(); + 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. " ); - - + 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 )) ); + results.add( Output.stringFormat(" &3Total Prison Command Alias Usage: &7%9s", iFmt.format( totalsAlias )) ); + + 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; } @@ -1351,20 +1140,20 @@ public void runCommand(CommandSender sender, ) { - if ( playerName == null || playerName.isEmpty() ) { - - coreRunCommandNameRequiredMsg(sender); - - return; - } - - if ( command == null || command.trim().length() == 0 ) { - coreRunCommandCommandRequiredMsg(sender); - } - - Player player = getPlayer( playerName ); - - PrisonAPI.dispatchCommand( player, command ); + if ( playerName == null || playerName.isEmpty() ) { + + coreRunCommandNameRequiredMsg(sender); + + return; + } + + if ( command == null || command.trim().length() == 0 ) { + coreRunCommandCommandRequiredMsg(sender); + } + + Player player = getPlayer( playerName ); + + PrisonAPI.dispatchCommand( player, command ); } @@ -1381,15 +1170,15 @@ public void supportSetName(CommandSender sender, String supportName ) { - if ( supportName == null || supportName.trim().isEmpty() ) { - sender.sendMessage( "A value for supportName is required." ); - return; - } - - setSupportName( supportName ); - - sender.sendMessage( String.format( "The support name has been set to: %s", getSupportName() ) ); - sender.sendMessage( "You can now use the support submit options." ); + if ( supportName == null || supportName.trim().isEmpty() ) { + sender.sendMessage( "A value for supportName is required." ); + return; + } + + setSupportName( supportName ); + + sender.sendMessage( String.format( "The support name has been set to: %s", getSupportName() ) ); + sender.sendMessage( "You can now use the support submit options." ); } @@ -1408,54 +1197,54 @@ public void supportSaveToFile(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; - } - - - 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." ); - } + 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 saved 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." ); + } } @@ -1465,9 +1254,9 @@ public void supportSaveToFile(CommandSender sender, public void supportColorTest(CommandSender sender ) { - StringBuilder sb = Prison.get().getPrisonStatsUtil().getColorTest(); - - for (String line : sb.toString().split("\n")) { + StringBuilder sb = Prison.get().getPrisonStatsUtil().getColorTest(); + + for (String line : sb.toString().split("\n")) { Output.get().logInfo(line); } } @@ -1479,158 +1268,94 @@ public void supportColorTest(CommandSender sender public void supportSubmitVersion(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 = 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 ) { - // Convert `{br}` to `\n`: - text.replace(idx, idx+4, "\n"); - - idx = text.indexOf("{br}"); - } + + 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 = 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 ) { + // Convert `{br}` to `\n`: + text.replace(idx, idx+4, "\n"); + + idx = text.indexOf("{br}"); + } // Add all of the listeners details: - text.append( "\n\n" ); - text.append( - Prison.get().getPrisonStatsUtil().getSupportSubmitListenersData( "all" ) - ); - - // Include the command stats: - text.append( Prison.get().getPrisonStatsUtil().getCommandStatsDetailData() ); -// text.append( "\n\n" ); -// List cmdStats = getCommandStats(); -// for (String cmd : cmdStats) { -// text.append( cmd ).append( "\n" ); -// } + text.append( "\n\n" ); + text.append( + Prison.get().getPrisonStatsUtil().getSupportSubmitListenersData( "all" ) + ); + + // Include the command stats: + text.append( Prison.get().getPrisonStatsUtil().getCommandStatsDetailData() ); - // Include Prison backup logs: - 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" ); -// } + // Include Prison backup logs: + text.append( Prison.get().getPrisonStatsUtil().getPrisonBackupLogsData() ); - text.append( Prison.get().getPrisonStatsUtil().getSupportSubmitConfigsData() ); - - - - if ( getSupportFile() != null ) { - - getSupportFile().saveToSupportFile( text, getSupportName() ); - - sender.sendMessage(" - Support 'version' data was just added to the support output file." ); - sender.sendMessage( getSupportFile().getFileStats( text.length() ) ); - } - else { - - PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); - - String helpURL = "(Failure in running the commmand.)"; - - try { - helpURL = pasteChat.post( text.toString() ); - } - catch (Exception e) { - Output.get().logRaw( - - String.format( - "Failed to paste support info to the support server: %s " - + "raw message: [%s]", - e.getMessage(), - 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().getSupportSubmitConfigsData() ); + + + + if ( getSupportFile() != null ) { + + getSupportFile().saveToSupportFile( text, getSupportName() ); + + sender.sendMessage(" - Support 'version' data was just added to the support output file." ); + sender.sendMessage( getSupportFile().getFileStats( text.length() ) ); + } + else { + + PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); + + String helpURL = "(Failure in running the commmand.)"; + + try { + helpURL = pasteChat.post( text.toString() ); + } + catch (Exception e) { + Output.get().logRaw( + + String.format( + "Failed to paste support info to the support server: %s " + + "raw message: [%s]", + e.getMessage(), + 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 " + @@ -1641,47 +1366,47 @@ public void supportSubmitRanks(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; - } - - - // List Ladder and rank lists: - StringBuilder text = Prison.get().getPrisonStatsUtil().getSupportSubmitRanksData(); - - // List rank files: - text.append( Prison.get().getPrisonStatsUtil().getSupportSubmitRanksFileData() ); - - - if ( getSupportFile() != null ) { - - getSupportFile().saveToSupportFile( text, getSupportName() ); - - sender.sendMessage(" - Support 'ranks' 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.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." ); - } - } - + 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; + } + + + // List Ladder and rank lists: + StringBuilder text = Prison.get().getPrisonStatsUtil().getSupportSubmitRanksData(); + + // List rank files: + text.append( Prison.get().getPrisonStatsUtil().getSupportSubmitRanksFileData() ); + + + if ( getSupportFile() != null ) { + + getSupportFile().saveToSupportFile( text, getSupportName() ); + + sender.sendMessage(" - Support 'ranks' 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.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." ); + } + } + } @@ -1695,42 +1420,42 @@ public void supportSubmitMines(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().getSupportSubmitMinesData(); - - - if ( getSupportFile() != null ) { - - getSupportFile().saveToSupportFile( text, getSupportName() ); - - sender.sendMessage(" - Support 'mines' 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.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." ); - } - } + 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().getSupportSubmitMinesData(); + + + if ( getSupportFile() != null ) { + + getSupportFile().saveToSupportFile( text, getSupportName() ); + + sender.sendMessage(" - Support 'mines' 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.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." ); + } + } } @@ -1743,172 +1468,14 @@ public void supportSubmitMines(CommandSender sender onlyPlayers = false, permissions = "prison.debug" ) public void backpacksListOldCmd(CommandSender sender ) { - - BackpackConverterOldPrisonBackpacks converter = new BackpackConverterOldPrisonBackpacks(); - - converter.convertOldBackpacks(); - + + BackpackConverterOldPrisonBackpacks converter = new BackpackConverterOldPrisonBackpacks(); + + converter.convertOldBackpacks(); } - - -// -// private StringBuilder getSupportSubmitVersionData() { -// ChatDisplay display = displayVersion("ALL"); -// StringBuilder text = display.toStringBuilder(); -// return text; -// } -// -// private StringBuilder getSupportSubmitConfigsData() { -// Prison.get().getPlatform().saveResource( "plugin.yml", true ); -// -// String fileNames = "config.yml plugin.yml backups/versions.txt " + -// "autoFeaturesConfig.yml blockConvertersConfig.json " + -// "modules.yml module_conf/mines/config.json module_conf/mines/mineBombsConfig.json " + -// "SellAllConfig.yml GuiConfig.yml backpacks/backpacksconfig.yml"; -// List files = convertNamesToFiles( fileNames ); -// -// -// StringBuilder text = new StringBuilder(); -// -// for ( File file : files ) { -// -// addFileToText( file, text ); -// -// if ( file.getName().equalsIgnoreCase( "plugin.yml" ) ) { -// file.delete(); -// } -// } -// return text; -// } -// -// -// private StringBuilder getSupportSubmitRanksData() { -// 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 ) { -// -// addFileToText( file, text ); -// -// } -// return text; -// } -// -// -// private StringBuilder getSupportSubmitMinesData() { -// 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" ); -// -// // Display a list of all mines, then display the /mines info all for each: -// text.append( Prison.get().getPlatform().getMinesListString() ); -// printFooter( text ); -// -// -// -// for ( File file : files ) { -// -// addFileToText( file, text ); -// -// } -// return text; -// } - - -// private List listFiles( String path, String fileSuffix ) { -// List files = new ArrayList<>(); -// -// File dataFolder = Prison.get().getDataFolder(); -// File filePaths = new File( dataFolder, path ); -// -// for ( File file : filePaths.listFiles() ) { -// if ( file.getName().toLowerCase().endsWith( fileSuffix.toLowerCase() )) { -// files.add( file ); -// } -// } -// -// return files; -// } -// -// private void addFileToText( File file, StringBuilder sb ) -// { -// DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); -// SimpleDateFormat sdFmt = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ); -// -// 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 " : "" ) -// .append( file.canWrite() ? "WRITEABLE " : "" ) -// .append( "\n" ); -// -// sb.append( "\n" ); -// sb.append( "=== --- --- --- --- --- --- --- --- --- ===\n" ); -// sb.append( "\n" ); -// -// -// if ( file.exists() && file.canRead() ) { -// readFileToStringBulider( file, sb ); -// } -// else { -// sb.append( "Warning: The file is not readable so it cannot be included.\n" ); -// } -// -// -// printFooter( sb ); -// } - -// public static void printFooter( StringBuilder sb ) { -// -// sb.append( "\n\n\n" ); -// sb.append( "=== --- === --- === --- === --- === --- ===\n" ); -// sb.append( "=== # # ### # # # ### # # # ### # # # ### # # # ### # # ===\n" ); -// sb.append( "=== --- === --- === --- === --- === --- ===\n" ); -// sb.append( "\n\n" ); -// -// } -// -// private List convertNamesToFiles( String fileNames ) -// { -// List files = new ArrayList<>(); -// -// File dataFolder = Prison.get().getDataFolder(); -// -// for ( String fileName : fileNames.split( " " )) { -// File file = new File( dataFolder, fileName ); -// files.add( file ); -// } -// -// return files; -// } @Command(identifier = "prison support submit latestLog", description = "For Prison support: This will copy the contents of `logs/latest.log` " + @@ -1918,49 +1485,49 @@ public void supportSubmitLatestLog(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; - } - - - File latestLogFile = new File( Prison.get().getDataFolder().getParentFile().getParentFile(), - "logs/latest.log"); - - sender.sendMessage( "### log path: " + latestLogFile.getAbsolutePath() ); - - - StringBuilder logText = new StringBuilder(); - - if ( latestLogFile.exists() && latestLogFile.canRead() ) { - - readFileToStringBulider( latestLogFile, logText ); - - if ( logText != null ) { - - PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); - - String helpURL = pasteChat.post( logText.toString() ); - - getSupportURLs().put( "Submit lastlog:", 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 { - // Do nothing since if helpURL is null, then it has probably - // already sent an error message. - } - return; - } - } - - sender.sendMessage( "Unable to send log file. Unknown reason why." ); + 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; + } + + + File latestLogFile = new File( Prison.get().getDataFolder().getParentFile().getParentFile(), + "logs/latest.log"); + + sender.sendMessage( "### log path: " + latestLogFile.getAbsolutePath() ); + + + StringBuilder logText = new StringBuilder(); + + if ( latestLogFile.exists() && latestLogFile.canRead() ) { + + readFileToStringBulider( latestLogFile, logText ); + + if ( logText != null ) { + + PrisonPasteChat pasteChat = new PrisonPasteChat( getSupportName(), getSupportURLs() ); + + String helpURL = pasteChat.post( logText.toString() ); + + getSupportURLs().put( "Submit lastlog:", 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 { + // Do nothing since if helpURL is null, then it has probably + // already sent an error message. + } + return; + } + } + + sender.sendMessage( "Unable to send log file. Unknown reason why." ); } private void readFileToStringBulider( File textFile, StringBuilder text ) @@ -1995,46 +1562,6 @@ 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 listeners", description = "For Prison support: Provide a 'dump' of all event listeners.", @@ -2057,29 +1584,6 @@ public void supportListenersDump(CommandSender sender, String results = Prison.get().getPrisonStatsUtil().getSupportSubmitListenersData( listener ).toString(); -// String results = null; -// -// if ( "blockBreak".equalsIgnoreCase( listener ) ) { -// -// results = Prison.get().getPlatform().dumpEventListenersBlockBreakEvents(); -// } -// -// if ( "chat".equalsIgnoreCase( listener ) ) { -// -// results = Prison.get().getPlatform().dumpEventListenersPlayerChatEvents(); -// } -// -// if ( "traceBlockBreak".equalsIgnoreCase( listener ) ) { -// -// Prison.get().getPlatform().traceEventListenersBlockBreakEvents( sender ); -// -// return; -// } -// -// if ( "playerInteract".equalsIgnoreCase( listener ) ) { -// -// results = Prison.get().getPlatform().dumpEventListenersPlayerInteractEvents(); -// } if ( results != null ) { @@ -2096,7 +1600,9 @@ public void supportListenersDump(CommandSender sender, description = "This will make a backup of all Prison settings by creating a new " + "zip file which will be stored in the directory plugins/Prison/backups. " + "After creating the backup, this will delete all temp files, backup files, etc.. " + - "since they will be included in the backup.", + "since they will be included in the backup. This command will backup everything " + + "under 'plugins/Prison/' except for the directory 'plugins/Prison/backups/'. " + + "The backups will be placed in the directory 'plugins/Prison/backups/'.", onlyPlayers = false, permissions = "prison.debug" ) public void supportBackupPrison( CommandSender sender, @@ -2105,39 +1611,36 @@ public void supportBackupPrison( CommandSender sender, + "first 20 characters will be used.", def = "") String notes ) { - PrisonBackups prisonBackup = new PrisonBackups(); - - String message = prisonBackup.startBackup( BackupTypes.manual, notes ); - - sender.sendMessage( message ); - sender.sendMessage( "Backup finished." ); + PrisonBackups prisonBackup = new PrisonBackups(); + + String message = prisonBackup.startBackup( BackupTypes.manual, notes ); + + sender.sendMessage( message ); + sender.sendMessage( "Backup finished." ); } @Command(identifier = "prison support backup logs", description = "This will list Prison backup logs that are in the file " - + "`plugins/Prison/backup/versions.log`", + + "`plugins/Prison/backup/versions.log` The contents of the backup " + + "logs will be displayed in the console if this command is ran in the " + + "console. This command should not be ran ingame due to the amount of " + + "data and the width of the data. ", onlyPlayers = false, permissions = "prison.debug" ) public void supportBackupList( CommandSender sender ) { - ChatDisplay display = new ChatDisplay("Prison Backup Logs:"); - - List backupLogs = Prison.get().getPrisonStatsUtil().getPrisonBackupLogs(); -// List backupLogs = getPrisonBackupLogs(); - - for (String log : backupLogs) { - display.addText(log); - } - - display.send(sender); + ChatDisplay display = new ChatDisplay("Prison Backup Logs:"); + + List backupLogs = Prison.get().getPrisonStatsUtil().getPrisonBackupLogs(); + + for (String log : backupLogs) { + display.addText(log); + } + + display.send(sender); } -// private List getPrisonBackupLogs() { -// PrisonBackups prisonBackup = new PrisonBackups(); -// List backupLogs = prisonBackup.backupReport02BackupLog(); -// return backupLogs; -// } @Command(identifier = "prison tokens balance", @@ -2152,50 +1655,37 @@ public void tokensBalance(CommandSender sender, "another player.") String playerName ) { - Player player = getPlayer( sender ); - - // If player is null, then need to use the playerName, so if it's empty, we have a problem: - if ( ( player == null || !player.isOnline() ) && - ( playerName == null || playerName.isEmpty() ) ) { - - coreTokensNameRequiredMsg(sender); -// String message = "Prison Tokens: A player's name is required when used from console."; -// -// Output.get().logWarn( message ); - return; - } - else - if ( playerName != null && !playerName.isEmpty() ){ - - if ( !sender.isOp() && - !sender.hasPermission( "tokens.bal.others" ) ) { - coreTokensBalanceCannotViewOthersMsg(sender); -// String message = "Prison Tokens: You do not have permission to view other " + -// "player's balances."; -// Output.get().logWarn( message ); - return; - } - - Player tempPlayer = getPlayer( playerName ); - - if ( tempPlayer != null ) { - player = tempPlayer; - } - } - - -// player.getPlayerCache() + Player player = getPlayer( sender ); + + // If player is null, then need to use the playerName, so if it's empty, we have a problem: + if ( ( player == null || !player.isOnline() ) && + ( playerName == null || playerName.isEmpty() ) ) { + + coreTokensNameRequiredMsg(sender); + return; + } + else + if ( playerName != null && !playerName.isEmpty() ){ + + if ( !sender.isOp() && + !sender.hasPermission( "tokens.bal.others" ) ) { + coreTokensBalanceCannotViewOthersMsg(sender); + return; + } + + Player tempPlayer = getPlayer( playerName ); + + if ( tempPlayer != null ) { + player = tempPlayer; + } + } + + + + long tokens = player.getPlayerCachePlayerData().getTokens(); + + coreTokensBalanceViewMsg( sender, player.getName(), tokens ); - long tokens = player.getPlayerCachePlayerData().getTokens(); - - coreTokensBalanceViewMsg( sender, player.getName(), tokens ); - -// DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); -// String tokensMsg = dFmt.format( tokens ); -// -// String message = String.format( "&3%s has %s tokens.", player.getName(), tokensMsg ); -// -// sender.sendMessage( message ); } @Command(identifier = "prison tokens add", @@ -2220,88 +1710,75 @@ public void tokensAdd( CommandSender sender, def = "") String options ) { - boolean silent = options != null && options.toLowerCase().contains( "silent" ); - boolean forcePlayer = options != null && options.toLowerCase().contains( "forceplayer" ); - - if ( playerName == null || playerName.isEmpty() ) { - - if ( !silent ) { - coreTokensNameRequiredMsg(sender); -// String message = "Prison Tokens: A player's name is required."; -// Output.get().logWarn( message ); - } - - return; - } - -// DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - - if ( amount <= 0 ) { - - if ( !silent ) { - coreTokensAddInvalidAmountMsg( sender, amount ); -// String message = -// String.format( -// "Prison Tokens: Invalid amount: '%s'. Must be greater than zero.", -// dFmt.format( amount ) ); -// Output.get().logWarn( message ); - } - - return; - } - - 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(); - - if ( forcePlayer ) { - - pCache.addTokens( amount ); - } - else { - - pCache.addTokensAdmin( amount ); - } - - if ( pCache.getTokens() != tokenBal + amount && Output.get().isDebug() ) { - Output.get().logError( - String.format( - "AddTokens failure: player: %s Tokens: %d Should have been: %d", - player.getName(), pCache.getTokens(), tokenBal + amount )); - } - - if ( !silent ) { - - String message = coreTokensAddedAmountMsg( player.getName(), - pCache.getTokens(), amount ); - -// String tokens = dFmt.format( player.getPlayerCachePlayerData().getTokens() ); -// -// String message = String.format( "&3%s now has &7%s &3tokens after adding &7%s&3.", -// player.getName(), tokens, dFmt.format( amount ) ); - - // The person adding the tokens, or console: - sender.sendMessage( message ); - - // The player getting the tokens, if they are online: - if ( player.isOnline() && !player.getName().equalsIgnoreCase( sender.getName() ) ) { - - player.sendMessage( message ); - } - } + boolean silent = options != null && options.toLowerCase().contains( "silent" ); + boolean forcePlayer = options != null && options.toLowerCase().contains( "forceplayer" ); + + if ( playerName == null || playerName.isEmpty() ) { + + if ( !silent ) { + coreTokensNameRequiredMsg(sender); + } + + return; + } + + + if ( amount <= 0 ) { + + if ( !silent ) { + coreTokensAddInvalidAmountMsg( sender, amount ); + } + + return; + } + + 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(); + + if ( forcePlayer ) { + + pCache.addTokens( amount ); + } + else { + + pCache.addTokensAdmin( amount ); + } + + if ( pCache.getTokens() != tokenBal + amount && Output.get().isDebug() ) { + Output.get().logError( + String.format( + "AddTokens failure: player: %s Tokens: %d Should have been: %d", + player.getName(), pCache.getTokens(), tokenBal + amount )); + } + + if ( !silent ) { + + String message = coreTokensAddedAmountMsg( player.getName(), + pCache.getTokens(), amount ); + + // The person adding the tokens, or console: + sender.sendMessage( message ); + + // The player getting the tokens, if they are online: + if ( player.isOnline() && !player.getName().equalsIgnoreCase( sender.getName() ) ) { + + player.sendMessage( message ); + } + } } @@ -2330,78 +1807,66 @@ public void tokensRemove( CommandSender sender, def = "") String options ) { - boolean silent = options != null && options.toLowerCase().contains( "silent" ); - boolean forcePlayer = options != null && options.toLowerCase().contains( "forceplayer" ); - - if ( playerName == null || playerName.isEmpty() ) { - - if ( !silent ) { - coreTokensNameRequiredMsg(sender); -// String message = "Prison Tokens: A player's name is required."; -// Output.get().logWarn( message ); - } - - return; - } - -// DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - - if ( amount <= 0 ) { - - if ( !silent ) { - coreTokensAddInvalidAmountMsg( sender, amount ); -// String message = -// String.format( -// "Prison Tokens: Invalid amount: '%s'. Must be greater than zero.", -// dFmt.format( amount ) ); -// Output.get().logWarn( message ); - } - - return; - } - - 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 ); - } - else { - - player.getPlayerCachePlayerData().removeTokensAdmin( amount ); - } - - - if ( !silent ) { - - String message = coreTokensRemovedAmountMsg( player.getName(), - player.getPlayerCachePlayerData().getTokens(), amount ); -// String tokens = dFmt.format( player.getPlayerCachePlayerData().getTokens() ); -// -// String message = String.format( "&3%s now has &7%s &3tokens after removing &7%s&3.", -// player.getName(), tokens, dFmt.format( amount ) ); - - // The person adding the tokens, or console: - sender.sendMessage( message ); - - // The player getting the tokens, if they are online: - if ( player.isOnline() && !player.getName().equalsIgnoreCase( sender.getName() ) ) { - - player.sendMessage( message ); - } - } + boolean silent = options != null && options.toLowerCase().contains( "silent" ); + boolean forcePlayer = options != null && options.toLowerCase().contains( "forceplayer" ); + + if ( playerName == null || playerName.isEmpty() ) { + + if ( !silent ) { + coreTokensNameRequiredMsg(sender); + } + + return; + } + + + if ( amount <= 0 ) { + + if ( !silent ) { + coreTokensAddInvalidAmountMsg( sender, amount ); + } + + return; + } + + 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 ); + } + else { + + player.getPlayerCachePlayerData().removeTokensAdmin( amount ); + } + + + if ( !silent ) { + + String message = coreTokensRemovedAmountMsg( player.getName(), + player.getPlayerCachePlayerData().getTokens(), amount ); + + // The person adding the tokens, or console: + sender.sendMessage( message ); + + // The player getting the tokens, if they are online: + if ( player.isOnline() && !player.getName().equalsIgnoreCase( sender.getName() ) ) { + + player.sendMessage( message ); + } + } } @Command(identifier = "prison tokens set", @@ -2430,67 +1895,57 @@ public void tokensSet( CommandSender sender, def = "") String options ) { - boolean silent = options != null && options.toLowerCase().contains( "silent" ); - boolean forcePlayer = options != null && options.toLowerCase().contains( "forceplayer" ); - - if ( playerName == null || playerName.isEmpty() ) { - - if ( !silent ) { - coreTokensNameRequiredMsg(sender); -// String message = "Prison Tokens: A player's name is required."; -// Output.get().logWarn( message ); - } - - return; - } - -// 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(); -// player.getPlayerCachePlayerData().removeTokensAdmin( totalTokens ); - - if ( forcePlayer ) { - - player.getPlayerCachePlayerData().setTokens( amount ); - } - else { - - player.getPlayerCachePlayerData().setTokensAdmin( amount ); - } - - if ( !silent ) { - - String message = coreTokensSetAmountMsg( player.getName(), - player.getPlayerCachePlayerData().getTokens() ); - -// String tokens = dFmt.format( player.getPlayerCachePlayerData().getTokens() ); -// -// String message = String.format( "&3%s now has &7%s &3tokens.", -// player.getName(), tokens ); - - // The person adding the tokens, or console: - sender.sendMessage( message ); - - // The player getting the tokens, if they are online: - if ( player.isOnline() && !player.getName().equalsIgnoreCase( sender.getName() ) ) { - - player.sendMessage( message ); - } - } + boolean silent = options != null && options.toLowerCase().contains( "silent" ); + boolean forcePlayer = options != null && options.toLowerCase().contains( "forceplayer" ); + + if ( playerName == null || playerName.isEmpty() ) { + + if ( !silent ) { + coreTokensNameRequiredMsg(sender); + } + + return; + } + + + Player player = getPlayer( playerName ); + + + if ( player == null ) { + if ( !silent ) { + sender.sendMessage( + String.format( + "Prison Tokens set: Player name not found. [%s] (hardCodedMessag)", + playerName )); + } + return; + } + + + if ( forcePlayer ) { + + player.getPlayerCachePlayerData().setTokens( amount ); + } + else { + + player.getPlayerCachePlayerData().setTokensAdmin( amount ); + } + + if ( !silent ) { + + String message = coreTokensSetAmountMsg( player.getName(), + player.getPlayerCachePlayerData().getTokens() ); + + + // The person adding the tokens, or console: + sender.sendMessage( message ); + + // The player getting the tokens, if they are online: + if ( player.isOnline() && !player.getName().equalsIgnoreCase( sender.getName() ) ) { + + player.sendMessage( message ); + } + } } @@ -2512,7 +1967,7 @@ private Player getPlayer( String playerName ) { } if ( player == null ) { - player = Prison.get().getPlatform().getOfflinePlayer( playerName ).orElse( null ); + player = Prison.get().getPlatform().getRankPlayer( null, playerName ); } return player; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommandMessages.java b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommandMessages.java index cc6ebeae2..7b6322b6d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/PrisonCommandMessages.java +++ b/prison-core/src/main/java/tech/mcprison/prison/PrisonCommandMessages.java @@ -87,10 +87,10 @@ protected String coreTokensRemovedAmountMsg( String amountMsg = dFmt.format( amount ); return Prison.get().getLocaleManager() - .getLocalizable( "core_tokens__removed_amount" ) - .setFailSilently() - .withReplacements( name, tokensMsg, amountMsg ) - .localize(); + .getLocalizable( "core_tokens__removed_amount" ) + .setFailSilently() + .withReplacements( name, tokensMsg, amountMsg ) + .localize(); } protected String coreTokensSetAmountMsg( @@ -118,9 +118,9 @@ protected void coreRunCommandNameRequiredMsg( CommandSender sender ) { protected void coreRunCommandCommandRequiredMsg( CommandSender sender ) { Prison.get().getLocaleManager() - .getLocalizable( "core_runCmd__command_required" ) - .setFailSilently() - .sendTo( sender ); + .getLocalizable( "core_runCmd__command_required" ) + .setFailSilently() + .sendTo( sender ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/alerts/AlertCommands.java b/prison-core/src/main/java/tech/mcprison/prison/alerts/AlertCommands.java index 004fac60d..0c44ddc99 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/alerts/AlertCommands.java +++ b/prison-core/src/main/java/tech/mcprison/prison/alerts/AlertCommands.java @@ -23,38 +23,33 @@ public AlertCommands() { @Command(identifier = "prison alerts", description = "Lists your alerts.", permissions = "prison.alerts", onlyPlayers = false ) public void prisonAlertsCommand(CommandSender sender) { -// if (!(sender instanceof Player)) { -// Prison.get().getLocaleManager().getLocalizable("cantAsConsole") -// .sendTo(sender, LogLevel.ERROR); -// return; -// } - List alerts = new ArrayList<>(); - - ChatDisplay display = new ChatDisplay("Alerts"); - - BulletedListComponent.BulletedListBuilder builder = - new BulletedListComponent.BulletedListBuilder(); + List alerts = new ArrayList<>(); + + ChatDisplay display = new ChatDisplay("Alerts"); + + BulletedListComponent.BulletedListBuilder builder = + new BulletedListComponent.BulletedListBuilder(); if ((sender instanceof Player)) { - Player player = (Player) sender; - - alerts = Alerts.getInstance().getAlertsFor(player.getUUID()); + Player player = (Player) sender; + + alerts = Alerts.getInstance().getAlertsFor(player.getUUID()); } alerts.forEach(alert -> builder.add(alert.message)); display.addComponent(builder.build()); if (alerts.size() == 0) { - Output.get().sendInfo(sender, "There are no alerts."); + Output.get().sendInfo(sender, "There are no alerts."); } else { - display.addText("&8Type /prison alerts clear to clear your alerts."); - display.addText("&8Type /prison alerts clearall to clear everyone's alerts."); - - display.send(sender); + display.addText("&8Type /prison alerts clear to clear your alerts."); + display.addText("&8Type /prison alerts clearall to clear everyone's alerts."); + + display.send(sender); } } @@ -63,11 +58,9 @@ public void prisonAlertsCommand(CommandSender sender) { public void prisonAlertsClearCommand(CommandSender sender) { if (!(sender instanceof Player)) { - // If console, then clear all since there is no "Player" to use: - prisonAlertsClearAllCommand( sender ); -// Prison.get().getLocaleManager().getLocalizable("cantAsConsole") -// .sendTo(sender, LogLevel.ERROR); - return; + // If console, then clear all since there is no "Player" to use: + prisonAlertsClearAllCommand( sender ); + return; } Player player = (Player) sender; @@ -85,12 +78,6 @@ public void prisonAlertsClearCommand(CommandSender sender) { description = "Clears the alerts for the whole server.", permissions = "prison.alerts.clear.all", onlyPlayers = false ) public void prisonAlertsClearAllCommand(CommandSender sender) { -// if (!(sender instanceof Player)) { -// Prison.get().getLocaleManager().getLocalizable("cantAsConsole") -// .sendTo(sender, LogLevel.ERROR); -// return; -// } -// Player player = (Player) sender; Alerts.getInstance().clearAll(); Output.get().sendInfo(sender, "All alerts have been cleared."); diff --git a/prison-core/src/main/java/tech/mcprison/prison/alerts/Alerts.java b/prison-core/src/main/java/tech/mcprison/prison/alerts/Alerts.java index 223bce9bc..3236814fe 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/alerts/Alerts.java +++ b/prison-core/src/main/java/tech/mcprison/prison/alerts/Alerts.java @@ -25,17 +25,10 @@ public class Alerts { public static final long DURATION_ONE_HOUR = DURATION_ONE_MINUTE * 60; - /* - * Variables & Constants - */ - private static Alerts instance; private List alerts; - /* - * Constructor - */ - + private Alerts() { alerts = new ArrayList<>(); @@ -43,9 +36,6 @@ private Alerts() { Prison.get().getEventBus().register(this); } - /* - * Methods - */ public static Alerts getInstance() { if (instance == null) { @@ -97,9 +87,6 @@ public void clearAll() { alerts.clear(); } - /* - * Listeners - */ public void showAlerts(Player player) { int alerts = Alerts.getInstance().getAlertsFor(player.getUUID()).size(); @@ -110,9 +97,6 @@ public void showAlerts(Player player) { } } - /* - * Getters - */ @Subscribe public void onPlayerJoin(PlayerJoinEvent e) { 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 538f13608..852a6f1dd 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 @@ -109,6 +109,9 @@ public enum AutoFeatures { blockBreakEventPriority(blockBreakEvents, "LOW"), + entityExplodeEventPriority(blockBreakEvents, "DISABLED"), + + ProcessPrisons_ExplosiveBlockBreakEventsPriority(blockBreakEvents, "LOW"), @@ -135,7 +138,7 @@ public enum AutoFeatures { blockBreakEvents__ReadMe(blockBreakEvents, "Use the following event priorities with the blockBreakEvents: " + "DISABLED, LOWEST, LOW, NORMAL, HIGH, HIGHEST, BLOCKEVENTS, MONITOR, " + - "ACESS, ACCESSBLOCKEVENTS, ACCESSMONITOR"), + "ACCESS, ACCESSBLOCKEVENTS, ACCESSMONITOR"), blockBreakEvents__ReadMe2(blockBreakEvents, "MONITOR: Processed even if event is canceled. Includes block counts, " @@ -164,6 +167,8 @@ public enum AutoFeatures { isCalculateXPEnabled(general, true), givePlayerXPAsOrbDrops(general, false), + validateBlocksWerePlacedByPrison(general, true), + ifBlockIsAlreadyCountedThenCancelEvent(general, true), processMonitorEventsOnlyIfPrimaryBlockIsAIR(general, true), @@ -248,7 +253,9 @@ public enum AutoFeatures { actionBarMessageIfInventoryIsFull(inventory, true), // hologramIfInventoryIsFull(general, false), - + + includePlayerInventoryWhenSmelting(inventory, false), + includePlayerInventoryWhenBlocking(inventory, false), tokens(options), @@ -262,7 +269,7 @@ public enum AutoFeatures { permissionAutoSmelt(permissions, "prison.automanager.smelt"), permissionAutoBlock(permissions, "prison.automanager.block"), - permissionAuto__readme(permissions, "If permmissions are enabled, of which they are by default, " + + permissionAuto__readme(permissions, "If permissions are enabled, of which they are enabled by default, " + "and 'isAutoFeaturesEnabled' is enabled, then all OPs will automatically " + "enable auto pickup, auto smelt, and auto block because bukkit will always " + "test 'true' for any permmission when OP'd. There is no way around this, " + @@ -270,6 +277,24 @@ public enum AutoFeatures { "players should not be playing as OP'd. To disable these perms, then " + "use a value of 'disable'."), + + customEnchants(options), + + isCustomEnchantsEnabled(customEnchants, false), + + customEnchantsAutoPickup(customEnchants, "disable"), + customEnchantsAutoSmelt(customEnchants, "disable"), + customEnchantsAutoBlock(customEnchants, "disable"), + + customEnchants__readme(customEnchants, "If customEnchants are enabled, of which they " + + "are disabled by default, " + + "and 'isCustomEnchantsEnabled' is enabled, then Prison can use custom " + + "enchantments to trigger auto pickup, auto smelt, and auto blocking. " + + "Use '/sellall item inspect' to find out what the actual enchantment name " + + "is for easier setup of these features. A value of 'disable' will also prevent " + + "the individual enchantments from being used."), + + lore(options), isLoreEnabled(lore, true), @@ -321,6 +346,8 @@ public enum AutoFeatures { isUseTokenEnchantsFortuneLevel(fortuneFeature, false ), + isUseRevEnchantsFortuneLevel(fortuneFeature, false ), + fortuneMultiplierGlobal(fortuneFeature, 1.0 ), fortuneMultiplierMax(fortuneFeature, 0 ), @@ -427,19 +454,36 @@ public enum AutoFeatures { blockAllBlocks(blockFeature, true), + blockRawCopperBlock(blockFeature, true), + blockCopperBlock(blockFeature, true), + + blockGoldIngot(blockFeature, true), + blockRawGoldBlock(blockFeature, true), blockGoldBlock(blockFeature, true), + + blockIronIngot(blockFeature, true), + blockRawIronBlock(blockFeature, true), blockIronBlock(blockFeature, true), - blockCoalBlock(blockFeature, true), + + blockAmethystBlock(blockFeature, true), blockDiamondBlock(blockFeature, true), - blockRedstoneBlock(blockFeature, true), blockEmeraldBlock(blockFeature, true), - blockQuartzBlock(blockFeature, true), - blockPrismarineBlock(blockFeature, true), + blockRedstoneBlock(blockFeature, true), + + blockCoalBlock(blockFeature, true), blockLapisBlock(blockFeature, true), - blockSnowBlock(blockFeature, true), + blockPrismarineBlock(blockFeature, true), + blockQuartzBlock(blockFeature, true), + + blockBoneBlock(blockFeature, true), + blockDriedKelpBlock(blockFeature, true), blockGlowstone(blockFeature, true), - blockCopperBlock(blockFeature, true), - + blockHayBlock(blockFeature, true), + blockNetherWartBlock(blockFeature, true), + blockMelon(blockFeature, true), + blockPackedIceBlock(blockFeature, true), + blockSnowBlock(blockFeature, true), + blockConverters(options), @@ -452,7 +496,7 @@ public enum AutoFeatures { + "this will replace the list of hard coded blocks listed above for " + "blocking and smelting."), - isEnabledBlockConvertersEventTriggers(blockConverters, false ) + isEnabledBlockConvertersEventTriggers(blockConverters, false ), @@ -1206,12 +1250,26 @@ public TreeMap getBstatsDetails() { bStatsDetailBoolean( AutoFeatures.isLoreEnabled, tm ); if ( isFeatureBoolean( AutoFeatures.isLoreEnabled )) { + bStatsDetailBoolean( AutoFeatures.lorePickupValue, tm ); + bStatsDetailBoolean( AutoFeatures.loreSmeltValue, tm ); + bStatsDetailBoolean( AutoFeatures.loreBlockValue, tm ); + bStatsDetailBoolean( AutoFeatures.loreTrackBlockBreakCount, tm ); bStatsDetailBoolean( AutoFeatures.loreDurabiltyResistance, tm ); } + bStatsDetailBoolean( AutoFeatures.isCustomEnchantsEnabled, tm ); + if ( isFeatureBoolean( AutoFeatures.isCustomEnchantsEnabled )) { + + bStatsDetailBoolean( AutoFeatures.customEnchantsAutoPickup, tm ); + bStatsDetailBoolean( AutoFeatures.customEnchantsAutoSmelt, tm ); + bStatsDetailBoolean( AutoFeatures.customEnchantsAutoBlock, tm ); + } + + + bStatsDetailBoolean( AutoFeatures.isCalculateDurabilityEnabled, tm ); bStatsDetailBoolean( AutoFeatures.isPreventToolBreakage, tm ); bStatsDetailBoolean( AutoFeatures.preventToolBreakageThreshold, tm ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheEvents.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheEvents.java index 2b4e3a1c7..7a5691ae1 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheEvents.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheEvents.java @@ -20,8 +20,8 @@ public BackpackCacheEvents() { @Subscribe public void onPlayerJoin(PlayerJoinEvent event) { - Player player = event.getPlayer(); - BackpackCache.getInstance().submitAsyncLoadPlayer( player ); + Player player = event.getPlayer(); + BackpackCache.getInstance().submitAsyncLoadPlayer( player ); } @Subscribe @@ -34,7 +34,7 @@ public void onPlayerQuit(PlayerQuitEvent event) { @Subscribe public void onPlayerKicked(PlayerKickEvent event) { - Player player = event.getPlayer(); - BackpackCache.getInstance().submitAsyncUnloadPlayer( player ); + Player player = event.getPlayer(); + BackpackCache.getInstance().submitAsyncUnloadPlayer( player ); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheLoadPlayerTask.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheLoadPlayerTask.java index 7d1de58a2..f341b07d6 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheLoadPlayerTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheLoadPlayerTask.java @@ -17,7 +17,7 @@ public BackpackCacheLoadPlayerTask( Player player ) { public void run() { BackpackCache bCache = BackpackCache.getInstance(); - + BackpackCachePlayerData playerData = bCache.getCacheFiles().fromJson( player ); if ( playerData != null ) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCachePlayerData.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCachePlayerData.java index 28d692698..ccb299b95 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCachePlayerData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCachePlayerData.java @@ -17,13 +17,6 @@ public class BackpackCachePlayerData private transient File playerFile = null; -// /** -// * This Object lock is used to synchronized the public side of this class -// * and the protected side of this class which is the database transaction -// * side of things. -// */ -// @SuppressWarnings( "unused" ) -// private transient final Object lock = new Object(); private transient BackpackCacheRunnable task = null; diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheSaveAllPlayersTask.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheSaveAllPlayersTask.java index 6d2ba01be..5315cd4a0 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheSaveAllPlayersTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheSaveAllPlayersTask.java @@ -70,7 +70,7 @@ public void run() } } - + synchronized ( bCache.getPlayers() ) { for ( BackpackCachePlayerData playerData : purge ) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheStats.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheStats.java index d6ca4d846..2f671aa68 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheStats.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheStats.java @@ -57,7 +57,7 @@ public String displayStats() { .append( " synchronizeDatabase=" ).append( getSynchronizeBackpacks() ) ; - + return sb.toString(); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheTask.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheTask.java index 4c645d75d..972f2bc6e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheTask.java @@ -12,7 +12,7 @@ public BackpackCacheTask( BackpackCachePlayerData backpackData ) { this.backpackData = backpackData; } - + public BackpackCachePlayerData getBackpackData() { return backpackData; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheUnloadPlayerTask.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheUnloadPlayerTask.java index d97829ff7..1e71430ea 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheUnloadPlayerTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackCacheUnloadPlayerTask.java @@ -15,7 +15,7 @@ public void run() { // Remove from the player cache: BackpackCachePlayerData removed = null; - + synchronized ( bCache.getPlayers() ) { removed = bCache.removePlayerData( getBackpackData() ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackConverterOldPrisonBackpacks.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackConverterOldPrisonBackpacks.java index a0d41b08c..50b3e7812 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackConverterOldPrisonBackpacks.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackConverterOldPrisonBackpacks.java @@ -25,7 +25,6 @@ public void convertOldBackpacks() { Output.get().logInfo( " Old backpack size:", oldBackpacks.size() ); } - } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackEnums.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackEnums.java index ffccc9333..3498090bc 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackEnums.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/BackpackEnums.java @@ -6,7 +6,7 @@ public enum BackpackType { inventory, // Uses standard inventory object, up to 6 rows, 9 stacks each silo; // Up to 54 silos per backpack, which will use a chest to display } - + public enum BackpackFeatures { soulboundBackpack, // If player dies, they keep the backpack soulboundItems, // if soulboundBackpack is enabled, this will preserve items within diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/PlayerBackpack.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/PlayerBackpack.java index c31cc281d..cdb8e3e5b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backpacks/PlayerBackpack.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/PlayerBackpack.java @@ -23,7 +23,6 @@ public class PlayerBackpack { private BackpackType backpackType; private List inventory; -// private Inventory inventory; private int inventorySize; diff --git a/prison-core/src/main/java/tech/mcprison/prison/backpacks/PrisonCoreBackpackMessages.java b/prison-core/src/main/java/tech/mcprison/prison/backpacks/PrisonCoreBackpackMessages.java new file mode 100644 index 000000000..d68761149 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/backpacks/PrisonCoreBackpackMessages.java @@ -0,0 +1,317 @@ +package tech.mcprison.prison.backpacks; + +import java.text.DecimalFormat; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.integration.IntegrationCore; +import tech.mcprison.prison.integration.IntegrationType; + +public class PrisonCoreBackpackMessages + extends IntegrationCore { + + public PrisonCoreBackpackMessages() { + super( "PrisonBackpacks", "Prison", IntegrationType.BACKPACK ); + } + + protected String guiClickToDecreaseMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__click_to_decrease" ) + .localize(); + } + protected String guiClickToIncreaseMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__click_to_increase" ) + .localize(); + } + + + protected String guiClickToCancelMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__click_to_cancel" ) + .localize(); + } + protected String guiClickToCloseMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__click_to_close" ) + .localize(); + } + protected String guiClickToConfirmMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__click_to_confirm" ) + .localize(); + } + protected String guiClickToDeleteMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__click_to_delete" ) + .localize(); + } + protected String guiClickToDisableMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__click_to_disable" ) + .localize(); + } + protected String guiClickToEditMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__click_to_edit" ) + .localize(); + } + protected String guiClickToEnableMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__click_to_enable" ) + .localize(); + } + protected String guiClickToOpenMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__click_to_open" ) + .localize(); + } + + protected String guiLeftClickToConfirmMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__left_click_to_confirm" ) + .localize(); + } + protected String guiLeftClickToResetMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__left_click_to_reset" ) + .localize(); + } + protected String guiLeftClickToOpenMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__left_click_to_open" ) + .localize(); + } + protected String guiLeftClickToEditMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__left_click_to_edit" ) + .localize(); + } + + protected String guiRightClickToCancelMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__right_click_to_cancel" ) + .localize(); + } + protected String guiRightClickToDeleteMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__right_click_to_delete" ) + .localize(); + } + protected String guiRightClickToDisableMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__right_click_to_disable" ) + .localize(); + } + protected String guiRightClickToEnableMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__right_click_to_enable" ) + .localize(); + } + protected String guiRightClickToToggleMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__right_click_to_toggle" ) + .localize(); + } + + + protected String guiRightClickShiftToDeleteMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__right_click_and_shift_to_delete" ) + .localize(); + } + protected String guiRightClickShiftToDisableMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__right_click_and_shift_to_disable" ) + .localize(); + } + protected String guiRightClickShiftToToggleMsg() { + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__right_click_and_shift_to_toggle" ) + .localize(); + } + + + + protected String guiPageNextMsg() { + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__page_next" ) + .localize(); + } + protected String guiPagePriorMsg() { + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__page_prior" ) + .localize(); + } + + protected String guiPageToolsCloseMsg() { + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__page_tools_close" ) + .localize(); + } + protected String guiPageToolsGoBackMsg() { + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__page_tools_go_back" ) + .localize(); + } + private String formmatPageToolsPlaceholders( String msg, int currentPage, int maxPage ) { + + if ( maxPage < 1 ) { + maxPage = 1; + } + int priorPage = currentPage == 1 ? 1 : currentPage - 1; + int nextPage = currentPage == maxPage ? maxPage : currentPage + 1; + + msg = msg.replace("{first_page}", "1" ) + .replace("{prior_page}", Integer.toString(priorPage) ) + .replace("{current_page}", Integer.toString(currentPage)) + .replace("{next_page}", Integer.toString(nextPage)) + .replace("{last_page}", Integer.toString(maxPage)) + ; + + return msg; + } + protected String guiPageToolsCloseMsg( int currentPage, int maxPage ) { + + String msg = Prison.get().getLocaleManager() + .getLocalizable( "core_gui__page_tools_close" ) + .localize(); + + return formmatPageToolsPlaceholders( msg, currentPage, maxPage ); + } + protected String guiPageToolsFirstPageMsg( int currentPage, int maxPage ) { + + String msg = Prison.get().getLocaleManager() + .getLocalizable( "core_gui__page_tools_first_page" ) + .localize(); + + return formmatPageToolsPlaceholders( msg, currentPage, maxPage ); + } + protected String guiPageToolsPriorPageMsg( int currentPage, int maxPage ) { + + String msg = Prison.get().getLocaleManager() + .getLocalizable( "core_gui__page_tools_prior_page" ) + .localize(); + + return formmatPageToolsPlaceholders( msg, currentPage, maxPage ); + } + protected String guiPageToolsCurrentPageMsg( int currentPage, int maxPage ) { + + String msg = Prison.get().getLocaleManager() + .getLocalizable( "core_gui__page_tools_current_page" ) + .localize(); + + return formmatPageToolsPlaceholders( msg, currentPage, maxPage ); + } + protected String guiPageToolsNextPageMsg( int currentPage, int maxPage ) { + + String msg = Prison.get().getLocaleManager() + .getLocalizable( "core_gui__page_tools_next_page" ) + .localize(); + + return formmatPageToolsPlaceholders( msg, currentPage, maxPage ); + } + protected String guiPageToolsLastPageMsg( int currentPage, int maxPage ) { + + String msg = Prison.get().getLocaleManager() + .getLocalizable( "core_gui__page_tools_last_page" ) + .localize(); + + return formmatPageToolsPlaceholders( msg, currentPage, maxPage ); + } + + + + protected String guiPriceMsg( Double price ) { + + DecimalFormat dFmt = Prison.get().getDecimalFormat( "#,##0.00" ); + String value = price == null ? dFmt.format(0) : dFmt.format(price); + + return guiPriceMsg( value ); + } + protected String guiPriceMsg( Integer price ) { + + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + String value = price == null ? dFmt.format(0) : dFmt.format(price); + + return guiPriceMsg( value ); + } + protected String guiPriceMsg( String price ) { + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__price" ) + .withReplacements( price ) + .localize(); + } + + + protected String guiConfirmMsg( String prestigeName, double value ) { + + DecimalFormat dFmt = Prison.get().getDecimalFormat( "#,##0.0" ); + String valueStr = dFmt.format(value); + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__confirm" ) + .withReplacements( prestigeName, valueStr ) + .localize(); + } + + + protected String guiDelayMsg( int value ) { + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + String valueStr = dFmt.format(value); + + return guiDelayMsg( valueStr ); + } + protected String guiDelayMsg( String value ) { + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__delay" ) + .withReplacements( value ) + .localize(); + } + + protected String guiMultiplierMsg( double value ) { + + DecimalFormat dFmt = Prison.get().getDecimalFormat( "#,##0.0" ); + String valueStr = dFmt.format(value); + + return guiMultiplierMsg( valueStr ); + } + protected String guiMultiplierMsg( String value ) { + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__multiplier" ) + .withReplacements( value ) + .localize(); + } + + protected String guiValueMsg( String value ) { + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__value" ) + .withReplacements( value ) + .localize(); + } + + protected String guiPermissionMsg( String prestigeName ) { + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__permission" ) + .withReplacements( prestigeName ) + .localize(); + } + + protected String guiPrestigeNameMsg( String prestigeName ) { + + return Prison.get().getLocaleManager() + .getLocalizable( "core_gui__prestige_name" ) + .withReplacements( prestigeName ) + .localize(); + } + + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/backups/PrisonBackups.java b/prison-core/src/main/java/tech/mcprison/prison/backups/PrisonBackups.java index 45678bd39..4a806d03b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/backups/PrisonBackups.java +++ b/prison-core/src/main/java/tech/mcprison/prison/backups/PrisonBackups.java @@ -196,7 +196,6 @@ public String startBackup( BackupTypes backupType, String notes ) { // The files in the zip file needs to be placed in a directory: -// SimpleDateFormat sdFmt = new SimpleDateFormat( "yyyy-MM-dd_kk-mm" ); String zipFilePrefix = "backup_" + sdFmt.format( backupStartDate ); this.zipFilePrefix = zipFilePrefix; @@ -264,14 +263,9 @@ public String startBackup( BackupTypes backupType, String notes ) { public String backupReport01() { -// DecimalFormat dFmt = Prison.get().getDecimalFormatDouble(); long stop = System.nanoTime(); double runTimeMs = ( stop - getStartTimeNanos() ) / 1000000.0d; -// long size = zipFile.length(); -// double sizeKb = size / 1024.0; - - String msg1 = String.format( "Prison backup:\n" + @@ -491,8 +485,6 @@ public File getNewBackupFile( BackupTypes backupType, String fileNameNotes ) { String prisonVersion = Prison.get().getPlatform().getPluginVersion(); -// SimpleDateFormat sdFmt = new SimpleDateFormat( "yyyy-MM-dd_hh-mm" ); - String fileName = "prison_" + sdFmt.format( new Date() ) + "_v" + prisonVersion + ( backupType == null ? "" : "_" + backupType.name()) + diff --git a/prison-core/src/main/java/tech/mcprison/prison/backups/PrisonSystemSettings.java b/prison-core/src/main/java/tech/mcprison/prison/backups/PrisonSystemSettings.java new file mode 100644 index 000000000..6b98903ac --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/backups/PrisonSystemSettings.java @@ -0,0 +1,30 @@ +package tech.mcprison.prison.backups; + +import tech.mcprison.prison.file.FileIOData; + +/** + *

This class serves as a way for prison to track major events and + * configuration settings. Such as changes in settings that cannot be + * determined by looking at other files. This is also an internal + * prison settings file that the users should never touch. + *

+ * + *

For the friendly file names, the primary logic is located within + * the Ranks module since it has everything to do with ranks. + * The source code can be found in this class: + * '/prison-ranks/src/main/java/tech/mcprison/prison/ranks/tasks/PlayerNewFileNameCheckAsyncTask.java' + *

+ */ +public class PrisonSystemSettings + implements FileIOData { + public static final String PRISON_SYSTEM_FILENAME = "prison-system-settings.json"; + + public static final String PRISON_SYSTEM_SETTING_FRIENDLY_PLAYER_FILE_NAMES = "prison-ranks.use-friendly-user-file-names"; + + public enum SystemSettingsKey { + PlayerFileNameUpdate + + ; + } + + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/GeometricShapes.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/GeometricShapes.java similarity index 87% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/GeometricShapes.java rename to prison-core/src/main/java/tech/mcprison/prison/bombs/GeometricShapes.java index c19bf203f..e40ea2c38 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bombs/GeometricShapes.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/GeometricShapes.java @@ -1,7 +1,8 @@ -package tech.mcprison.prison.spigot.bombs; +package tech.mcprison.prison.bombs; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.util.Vector; /** *

These functions were basically copied from the following post. They have @@ -35,7 +36,6 @@ public static void drawCircle( PrisonBlock block, World world, int xi, int yi, i if ( (int) (getDistance( x, z, xi, zi )) == r ) { world.setBlock( block, x, yi, z ); -// world.setBlock( x, yi, z, Block.stone.blockID ); } } } @@ -51,7 +51,6 @@ public static void drawFilledCircle( PrisonBlock block, World world, int xi, int if ( (int) (getDistance( x, z, xi, zi )) <= r ) { world.setBlock( block, x, yi, z ); -// world.setBlock( x, yi, z, Block.stone.blockID ); } } } @@ -68,7 +67,6 @@ public static void drawDisk( PrisonBlock block, World world, int xi, int yi, int if ( dist < outerRadius && dist >= innerRadius ) { world.setBlock( block, x, yi, z ); -// world.setBlock( x, yi, z, Block.stone.blockID ); } } } @@ -159,10 +157,6 @@ public static void wireFrameCube( PrisonBlock block, World world, int xi, int yi world.setBlock( block, i, yi, zi + depth - 1 ); world.setBlock( block, i, yi + height - 1, zi + depth - 1 ); -// world.setBlock( i, yi, zi, id ); -// world.setBlock( i, yi + height - 1, zi, id ); -// world.setBlock( i, yi, zi + depth - 1, id ); -// world.setBlock( i, yi + height - 1, zi + depth - 1, id ); } for ( int i = yi; i < yi + height; i++ ) { @@ -171,10 +165,6 @@ public static void wireFrameCube( PrisonBlock block, World world, int xi, int yi world.setBlock( block, xi, i, zi + depth - 1 ); world.setBlock( block, xi + width - 1, i, zi + depth - 1 ); -// world.setBlock( xi, i, zi, id ); -// world.setBlock( xi + width - 1, i, zi, id ); -// world.setBlock( xi, i, zi + depth - 1, id ); -// world.setBlock( xi + width - 1, i, zi + depth - 1, id ); } for ( int i = zi; i < zi + depth; i++ ) { @@ -183,10 +173,6 @@ public static void wireFrameCube( PrisonBlock block, World world, int xi, int yi world.setBlock( block, xi + width - 1, yi, i ); world.setBlock( block, xi + width - 1, yi + height - 1, i ); -// world.setBlock( xi, yi, i, id ); -// world.setBlock( xi, yi + height - 1, i, id ); -// world.setBlock( xi + width - 1, yi, i, id ); -// world.setBlock( xi + width - 1, yi + height - 1, i, id ); } } @@ -231,6 +217,50 @@ public static void drawTorus( PrisonBlock block, World world, int xi, int yi, in } } + + + /** + * This will calculate a new Vector based upon the degrees (angle), and the + * radius (distance from the center); + * + * Incrementing the degrees, with keeping the same value for radius, should + * draw a circle on the plane X-Z. + * + * @param degrees + * @param radius + * @return + */ + public static Vector getPointsOnCircleXZ( double degrees, double radius ) { + Vector results = null; + + final double angle = Math.toRadians( degrees ); + + double x = (Math.cos(angle) * radius); + double y = 0d; + double z = (Math.sin(angle) * radius); + + results = new Vector( x, y, z ); + + return results; + + +// final int NUM_POINTS = 1000; +// final double RADIUS = 100d; +// +// final Point[] points = new Point[NUM_POINTS]; +// +// for (int i = 0; i < NUM_POINTS; ++i) +// { +// final double angle = Math.toRadians(((double) i / NUM_POINTS) * 360d); +// +// points[i] = new Point( +// Math.cos(angle) * RADIUS, +// Math.sin(angle) * RADIUS +// ); +// } + + } + // public void someMethod() // { // { diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombCooldownException.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombCooldownException.java new file mode 100644 index 000000000..360b4d62b --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombCooldownException.java @@ -0,0 +1,36 @@ +package tech.mcprison.prison.bombs; + +import tech.mcprison.prison.Prison; + +public class MineBombCooldownException + extends Exception { + + private static final long serialVersionUID = 1L; + + private int cooldownTicks; + + public MineBombCooldownException( int cooldownTicks ) { + super( MineBombMessages.mineBombsCoolDownMsg( cooldownTicks ) + ); + + this.cooldownTicks = cooldownTicks; + } + + public String getCooldownSecondsFormatted() { + String results = ""; + + double seconds = getCooldownTicks() / 20.0d; + + results = Prison.getDecimalFormatStaticDouble().format( seconds ); + + return results; + } + + public int getCooldownTicks() { + return cooldownTicks; + } + public void setCooldownTicks(int cooldownTicks) { + this.cooldownTicks = cooldownTicks; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombCooldownTask.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombCooldownTask.java new file mode 100644 index 000000000..68b8a079a --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombCooldownTask.java @@ -0,0 +1,115 @@ +package tech.mcprison.prison.bombs; + +import java.util.Map; +import java.util.TreeMap; + +import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.tasks.PrisonRunnable; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; + +public class MineBombCooldownTask + implements PrisonRunnable { + + public static int DELAY_TICKS = 1; + + private static final Map playerCooldowns = new TreeMap<>(); + + private String playerUUID; + + private int taskId = -1; + + public MineBombCooldownTask( String playerUUID ) { + super(); + + this.playerUUID = playerUUID; + } + + public static boolean addPlayerCooldown( Player player, int ticks ) { + boolean results = false; + + int cooldown = checkPlayerCooldown( player ); + if ( cooldown <= 0 ) { + submitCooldownTask( player, ticks ); + results = true; + } + + return results; + } + + + private static int submitCooldownTask( Player player, int ticks ) { + int results = -1; + + if ( player != null ) { + String playerUUID = player.getUUID().toString(); + + playerCooldowns.put( playerUUID, ticks ); + + MineBombCooldownTask task = new MineBombCooldownTask( playerUUID ); + + int taskId = PrisonTaskSubmitter.runTaskTimer( task, DELAY_TICKS, DELAY_TICKS); + + task.setTaskId( taskId ); + } + + return results; + } + + /** + * Since this runs every 5 ticks, it removes 5 from the cooldown ticks. + * When it reaches a value of zero, then the cooldown is over. + */ + @Override + public void run() { + + Integer cooldownTicks = playerCooldowns.get( getPlayerUUID() ); + + int ticksRemaining = cooldownTicks == null ? 0 : cooldownTicks - DELAY_TICKS; + + if ( ticksRemaining <= 0 ) + { + playerCooldowns.remove( getPlayerUUID() ); + + PrisonTaskSubmitter.cancelTask( getTaskId() ); + } + else + { + playerCooldowns.put( getPlayerUUID(), ticksRemaining ); + } + } + + + + public static int checkPlayerCooldown( Player player ) + { + int results = 0; + + if ( player != null ) { + + String playerUUID = player.getUUID().toString(); + + if ( playerCooldowns.containsKey( playerUUID ) ) + { + results = playerCooldowns.get( playerUUID ); + } + } + + return results; + } + + + public String getPlayerUUID() { + return playerUUID; + } + public void setPlayerUUID(String playerUUID) { + this.playerUUID = playerUUID; + } + + public int getTaskId() { + return taskId; + } + public void setTaskId(int taskId) { + this.taskId = taskId; + } + +} 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 b31b7169f..92bce3549 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 @@ -4,10 +4,18 @@ import java.util.List; import java.util.TreeSet; +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.bombs.MineBombEffectsData.EffectType; +import tech.mcprison.prison.bombs.MineBombs.AnimationArmorStandItemLocation; +import tech.mcprison.prison.bombs.MineBombs.AnimationPattern; import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.util.Location; -public class MineBombData { +public class MineBombData + implements Comparable +{ public static final String MINE_BOMB_DEFAULT_ITEM_NAME = "&c-= &7{name}&c =-"; @@ -16,12 +24,6 @@ public class MineBombData { private String description; -// /** -// *

The 'bombItemId' is first line of the bomb's item lore, and -// * it really needs to be unique and not match any other bomb's id. -// *

-// */ -// private String loreBombItemId; private List lore; @@ -111,7 +113,7 @@ public class MineBombData { * of the mine too. *

*/ - private int placementAdjustmentY = -1; + private int placementAdjustmentY = 0; /** *

The chance of complete removal. So if the explosion includes @@ -153,6 +155,28 @@ public class MineBombData { private int itemRemovalDelayTicks = 5; // 0.25 seconds + /** + *

This setting controls the animation while the bomb counts down. + *

+ */ + private AnimationPattern animationPattern = AnimationPattern.infinity; + + private double animationOffset = 0; + + private double animationSpeed = 5; + + private double animationRadius = 1.0; + private double animationRadiusDelta = 0.0; + private boolean animationAlternateDirections = false; + private float animationSpinSpeed = -35; + + private AnimationArmorStandItemLocation animationArmorStandItemLocation; + + + private double throwVelocityLow = 1.5; + private double throwVelocityHigh = 3; + + /** *

On spigot versions that support it, the bomb, when placed, will glow. * Was introduced with Minecraft 1.9. Applies only to Entities, of which @@ -204,11 +228,29 @@ public class MineBombData { /** - * + * This feature will allow the player to add all the exploded blocks to + * their block counts. If set to false, then this will not add bomb + * related block breaks to the player's block counts, which will help + * keep the payer's counts focused on actual blocks broken. */ private boolean applyToPlayersBlockCount = true; + /** + * If small is set to true, then the armor stand that will be generated + * will be a smaller version of the standard size. This maybe about 1 + * block high, instead of the normal 2 blocks high. + * + * Since the armor stand will be reduced in size by half, so will the item + * that it is holding, it too will be reduced in size. + * + * This feature is dependent upon how bukkit handles this setting, + * therefore it may or may not work, or it may behave differently than + * what is described here. + */ + private boolean small = false; + + /** *

Internal just to indicated if a mine bomb is activated or not. * This has not purpose if used in a save file. @@ -222,9 +264,39 @@ public class MineBombData { private TreeSet visualEffects; - private Block placedBombBlock; + + /** + * This is a block that is "closest" to the location where the animation center + * point should be. But note, since the location is not exact, and there is rounding, + * this block may not be the block that was actually clicked, or where the item + * landed. For precise location, use placedBombLocation if it is not null. + * this should be used as a back for the location for the animation center point. + */ + private transient Block placedBombBlock; + + /** + * If not null, then this should be the animation target's center point. + */ + private transient Location placedBombLocation; + + + private transient int taskId = -1; + private BombStatus bombStatus; + + public enum BombStatus { + unprocessed, + event_ignored, + event_not_enabled, + canceled, + no_access, + failed_validation, + monitor_successful, + successful + ; + } + public MineBombData() { super(); @@ -234,6 +306,7 @@ public MineBombData() { this.allowedMines = new ArrayList<>(); this.preventedMines = new ArrayList<>(); + } @@ -251,7 +324,6 @@ public MineBombData( String name, String itemType, String explosionShape, this.explosionShape = explosionShape; this.radius = radius; -// this.loreBombItemId = "PrisonMineBomb: " + name; this.lore = new ArrayList<>(); @@ -274,15 +346,41 @@ public MineBombData( String name, String itemType, String explosionShape, this.itemRemovalDelayTicks = 5; + this.animationPattern = AnimationPattern.infinity; + + this.animationSpeed = 5.0; + + this.animationOffset = 0.0; + + this.animationRadius = 1.0; + this.animationRadiusDelta = 0.0; + this.animationAlternateDirections = false; + this.animationSpinSpeed = -35; + + this.animationArmorStandItemLocation = AnimationArmorStandItemLocation.hand; + + + this.throwVelocityLow = 1.5; + this.throwVelocityHigh = 3; + + this.animationSpeed = 10.0; + + this.glowing = false; this.gravity = true; this.autosell = false; this.customModelData = 0; + this.small = false; + this.applyToPlayersBlockCount = true; + this.placedBombBlock = null; + this.placedBombLocation = null; + + this.bombStatus = BombStatus.unprocessed; } @@ -290,7 +388,6 @@ public MineBombData clone() { MineBombData cloned = new MineBombData( getName(), getItemType(), getExplosionShape(), getRadius() ); -// cloned.setLoreBombItemId( getLoreBombItemId() ); cloned.setDescription( getDescription() ); @@ -315,6 +412,20 @@ public MineBombData clone() { cloned.setGlowing( isGlowing() ); cloned.setGravity( isGravity() ); + cloned.setAnimationPattern( getAnimationPattern() ); + cloned.setAnimationOffset( getAnimationOffset() ); + cloned.setAnimationSpeed( getAnimationSpeed() ); + cloned.setAnimationRadius( getAnimationRadius() ); + cloned.setAnimationRadiusDelta( getAnimationRadiusDelta() ); + cloned.setAnimationAlternateDirections( isAnimationAlternateDirections() ); + cloned.setAnimationSpinSpeed( getAnimationSpinSpeed() ); + cloned.setAnimationArmorStandItemLocation( getAnimationArmorStandItemLocation() ); + + + cloned.setThrowVelocityLow( getThrowVelocityLow() ); + cloned.setThrowVelocityHigh( getThrowVelocityHigh() ); + + cloned.setItemRemovalDelayTicks( getItemRemovalDelayTicks() ); cloned.setAutosell( isAutosell() ); @@ -322,6 +433,11 @@ public MineBombData clone() { cloned.setCustomModelData( getCustomModelData() ); + cloned.setSmall( isSmall() ); + + cloned.setPlacedBombBlock( getPlacedBombBlock() ); + cloned.setPlacedBombLocation( getPlacedBombLocation() ); + for ( String l : getLore() ) { cloned.getLore().add( l ); @@ -349,8 +465,80 @@ public MineBombData clone() { } + cloned.setBombStatus( getBombStatus() ); + return cloned; } + + + + @Override + public int compareTo(MineBombData o) { + int results = 0; + + if ( o == null ) { + results = -1; + } + + results = getName().compareTo( o.getName() ); + + // This is basically used in unit testing and with JSON conversions. + // conversions of numeric values shouldn't be an issue, so do not + // add to this compareTo. + + + if ( results == 0 ) { + + results = getNameTag().compareTo( o.getNameTag() ); + if ( results == 0 ) { + + results = getDescription().compareTo( o.getDescription() ); + if ( results == 0 ) { + + results = getAnimationPattern().compareTo( o.getAnimationPattern() ); + if ( results == 0 ) { + + results = Integer.compare( getSoundEffects().size(), o.getSoundEffects().size() ); + if ( results == 0 ) { + + results = Integer.compare( getVisualEffects().size(), o.getVisualEffects().size()); + if ( results == 0 ) { + + results = getExplosionShape().compareTo( o.getExplosionShape() ); + } + } + } + } + } + } + + return results; + } + + + /** + *

This function calculates the throw velocity based upon a randomly generated + * value between the 'throwValueVelocityLow' and 'throwVelocityHeigh'. + *

+ * + * @return + */ + public double getThrowVelocity() { + double results = getThrowVelocityLow(); + + if ( getThrowVelocityLow() != getThrowVelocityHigh() ) { + + double range = getThrowVelocityLow() < getThrowVelocityHigh() ? + getThrowVelocityHigh() - getThrowVelocityLow() : + getThrowVelocityLow() - getThrowVelocityHigh(); + double rnd = Math.random() * range; + + results += rnd; + } + + return results; + } + public String getName() { return name; @@ -373,13 +561,6 @@ public void setDescription( String description ) { this.description = description; } -// public String getLoreBombItemId() { -// return loreBombItemId; -// } -// public void setLoreBombItemId( String loreBombItemId ) { -// this.loreBombItemId = loreBombItemId; -// } - public List getLore() { return lore; } @@ -516,6 +697,103 @@ public void setItemRemovalDelayTicks( int itemRemovalDelayTicks ) { this.itemRemovalDelayTicks = itemRemovalDelayTicks; } + + /** + * If the animationPatternString is null, this will default to the + * infinity pattern. + * + * AnimationPattern should never be null, so it will fall back to it's default + * value which is infinity. + * + * @return + */ + public AnimationPattern getAnimationPattern() { + if ( animationPattern == null ) { + // Note: if animationPatternString is null it will return 'infinity' which + // is the default value. + animationPattern = AnimationPattern.infinity; + } + return animationPattern; + } + public void setAnimationPattern(AnimationPattern animationPattern) { + + this.animationPattern = + animationPattern == null ? + AnimationPattern.infinity : + animationPattern; + } + + public double getAnimationOffset() { + return animationOffset; + } + public void setAnimationOffset(double animationOffset) { + this.animationOffset = animationOffset; + } + + public double getAnimationSpeed() { + return animationSpeed; + } + public void setAnimationSpeed(double animationSpeed) { + this.animationSpeed = animationSpeed; + } + + public double getAnimationRadius() { + return animationRadius; + } + public void setAnimationRadius(double animationRadius) { + this.animationRadius = animationRadius; + } + + public double getAnimationRadiusDelta() { + return animationRadiusDelta; + } + public void setAnimationRadiusDelta(double animationRadiusDelta) { + this.animationRadiusDelta = animationRadiusDelta; + } + + public boolean isAnimationAlternateDirections() { + return animationAlternateDirections; + } + public void setAnimationAlternateDirections(boolean animationAlternateDirections) { + this.animationAlternateDirections = animationAlternateDirections; + } + + public float getAnimationSpinSpeed() { + return animationSpinSpeed; + } + public void setAnimationSpinSpeed(float animationSpinSpeed) { + this.animationSpinSpeed = animationSpinSpeed; + } + + public AnimationArmorStandItemLocation getAnimationArmorStandItemLocation() { + if ( animationArmorStandItemLocation == null ) { + animationArmorStandItemLocation = AnimationArmorStandItemLocation.hand; + } + return animationArmorStandItemLocation; + } + public void setAnimationArmorStandItemLocation(AnimationArmorStandItemLocation animationItemLocation) { + this.animationArmorStandItemLocation = animationItemLocation == null ? + AnimationArmorStandItemLocation.hand : animationItemLocation; + } + + public int getTaskId() { + return taskId; + } + + public double getThrowVelocityLow() { + return throwVelocityLow; + } + public void setThrowVelocityLow(double throwVelocityLow) { + this.throwVelocityLow = throwVelocityLow; + } + + public double getThrowVelocityHigh() { + return throwVelocityHigh; + } + public void setThrowVelocityHigh(double throwVelocityHigh) { + this.throwVelocityHigh = throwVelocityHigh; + } + public boolean isAutosell() { return autosell; } @@ -558,6 +836,40 @@ public void setApplyToPlayersBlockCount(boolean applyToPlayersBlockCount) { this.applyToPlayersBlockCount = applyToPlayersBlockCount; } + public boolean isSmall() { + return small; + } + public void setSmall(boolean small) { + this.small = small; + } + + public boolean addSoundEffects( MineBombEffectsData effect ) { + return addSoundEffects( effect, true ); + } + public boolean addSoundEffects( MineBombEffectsData effect, boolean showWarnings ) { + boolean results = false; + + effect.setEffectType( EffectType.sounds ); + + Prison.get().getPlatform().validateMineBombEffect( effect ); + + if ( effect.isValid() ) { + getSoundEffects().add(effect); + } + else if ( showWarnings ) { + String msg = String.format( + "MineBombData.addSoundEffects: Invalid effect. " + + "This effect is not valid for the version of Spigot that you're " + + "running and will be excluded. This is not an error. " + + "MineBomb: %s Effect: [[%s]] ", + getName(), + effect.toString() + ); + Output.get().logInfo( msg ); + results = true; + } + return results; + } public TreeSet getSoundEffects() { return soundEffects; } @@ -565,6 +877,33 @@ public void setSoundEffects( TreeSet soundEffects ) { this.soundEffects = soundEffects; } + public boolean addVisualEffects( MineBombEffectsData effect ) { + return addVisualEffects( effect, true ); + } + public boolean addVisualEffects( MineBombEffectsData effect, boolean showWarnings ) { + boolean results = false; + + effect.setEffectType( EffectType.visuals ); + + Prison.get().getPlatform().validateMineBombEffect( effect ); + + if ( effect.isValid() ) { + getVisualEffects().add(effect); + } + else if ( showWarnings ) { + String msg = String.format( + "MineBombData.addVisualEffects: Invalid effect. " + + "This effect is not valid for the version of Spigot that you're " + + "running and will be excluded. This is not an error. " + + "MineBomb: %s Effect: [[%s]] ", + getName(), + effect.toString() + ); + Output.get().logInfo( msg ); + results = true; + } + return results; + } public TreeSet getVisualEffects() { return visualEffects; } @@ -579,5 +918,27 @@ public void setPlacedBombBlock( Block placedBombBlock ) { this.placedBombBlock = placedBombBlock; } + public Location getPlacedBombLocation() { + return placedBombLocation; + } + public void setPlacedBombLocation(Location placedBombLocation) { + this.placedBombLocation = placedBombLocation; + } + + + public int getTask() { + return taskId; + } + public void setTaskId(int taskId ) { + this.taskId = taskId; + } + + + public BombStatus getBombStatus() { + return bombStatus; + } + public void setBombStatus(BombStatus bombStatus) { + this.bombStatus = bombStatus; + } } 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 ef03e2c9b..0edaf20b6 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 @@ -1,16 +1,19 @@ package tech.mcprison.prison.bombs; import tech.mcprison.prison.bombs.MineBombEffectsData.EffectState; +import tech.mcprison.prison.bombs.MineBombs.AnimationArmorStandItemLocation; +import tech.mcprison.prison.bombs.MineBombs.AnimationPattern; import tech.mcprison.prison.bombs.MineBombs.ExplosionShape; import tech.mcprison.prison.output.Output; public class MineBombDefaultConfigSettings { - @SuppressWarnings( "unused" ) public void setupDefaultMineBombData(MineBombs mineBombs) { if ( mineBombs.getConfigData().getBombs().size() == 0 ) { + + boolean showWarnings = false; // XMaterial.WOODEN_PICKAXE; // XMaterial.STONE_PICKAXE; @@ -50,59 +53,64 @@ public void setupDefaultMineBombData(MineBombs mineBombs) { MineBombData mbd = new MineBombData( - "SmallBomb", "brewing_stand", ExplosionShape.sphere.name(), 2, "&dSmall &6Mine &eBomb &3(lore line 1)" ); + "SmallBomb", "brewing_stand", ExplosionShape.sphere.name(), 2, + "&dSmall &6Mine &eBomb &3(lore line 1)&r" ); - mbd.setNameTag( "&6&kABC&r&c-= &7{name}&c =-&6&kCBA" ); + mbd.setNameTag( "&6&kABC&r&c-= &7{name}&c =-&6&kCBA&r" ); mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); mbd.setToolInHandName( "DIAMOND_PICKAXE" ); mbd.setToolInHandFortuneLevel( 0 ); - mbd.setDescription("A small mine bomb made with some chemicals and a brewing stand."); + mbd.setDescription("A small mine bomb made with some chemicals and a brewing stand.&r"); - mbd.getLore().add( "&4Lore line 2" ); - mbd.getLore().add( "&aLore line &73" ); + mbd.getLore().add( "&4Lore line 2&r" ); + mbd.getLore().add( "&aLore line &73&r" ); - mbd.getSoundEffects().add( mbeSound01.clone() ); - mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); - mbd.getSoundEffects().add( mbeSound03.clone() ); + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone(), showWarnings ); - mbd.getVisualEffects().add( mbeExplode04.clone() ); - mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 30 ) ); + mbd.addVisualEffects( mbeExplode04.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode03.clone().setOffsetTicks( 30 ), showWarnings ); - mbd.getVisualEffects().add( mbeExplode06a.clone() ); - mbd.getVisualEffects().add( mbeExplode10.clone() ); - mbd.getVisualEffects().add( mbeExplode06.clone() ); + mbd.addVisualEffects( mbeExplode06a.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode10.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode06.clone(), showWarnings ); mbd.setCooldownTicks( 10 ); + mbd.setAnimationPattern( AnimationPattern.infinity ); + mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } { MineBombData mbd = new MineBombData( - "MediumBomb", "firework_rocket", ExplosionShape.sphere.name(), 5, "Medium Mine Bomb" ); - mbd.setDescription("A medium mine bomb made from leftover fireworks, " + - "but supercharged with a strange green glowing liquid."); + "MediumBomb", "firework_rocket", ExplosionShape.sphere.name(), 5, "Medium Mine Bomb&r" ); + mbd.setDescription("A medium mine bomb made from leftover fireworks, &r" + + "but supercharged with a strange green glowing liquid.&r"); - mbd.setNameTag( "&6&k1 23 456&r&a-=- &7{name}&a -=-&6&k654 32 1" ); + mbd.setNameTag( "&6&k1 23 456&r&a-=- &7{name}&a -=-&6&k654 32 1&r" ); mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); mbd.setToolInHandName( "DIAMOND_PICKAXE" ); mbd.setToolInHandFortuneLevel( 3 ); - mbd.getSoundEffects().add( mbeSound01.clone() ); - mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); - mbd.getSoundEffects().add( mbeSound03.clone() ); + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone(), showWarnings ); - mbd.getVisualEffects().add( mbeExplode04.clone() ); - mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 30 ) ); + mbd.addVisualEffects( mbeExplode04.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode03.clone().setOffsetTicks( 30 ), showWarnings ); - mbd.getVisualEffects().add( mbeExplode10.clone() ); - mbd.getVisualEffects().add( mbeExplode06.clone() ); + mbd.addVisualEffects( mbeExplode10.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode06.clone(), showWarnings ); mbd.setCooldownTicks( 60 ); + + mbd.setAnimationPattern( AnimationPattern.infinity ); mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); @@ -112,77 +120,79 @@ public void setupDefaultMineBombData(MineBombs mineBombs) MineBombData mbd = new MineBombData( "LargeBomb", "tnt", ExplosionShape.sphereHollow.name(), 12, "Large Mine Bomb" ); - mbd.setNameTag( "&a-=- &7{name}&a -=--" ); + mbd.setNameTag( "&a-=- &7{name}&a -=--&r" ); mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); mbd.setRadiusInner( 3 ); mbd.setDescription("A large mine bomb made from TNT with some strange parts " + - "that maybe be described as alien technology."); + "that maybe be described as alien technology.&r"); mbd.setToolInHandName( "DIAMOND_PICKAXE" ); mbd.setToolInHandFortuneLevel( 3 ); - mbd.getSoundEffects().add( mbeSound01.clone() ); - mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); - mbd.getSoundEffects().add( mbeSound03.clone().setVolumne( 2.0f ) ); + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone().setVolumne( 2.0f ), showWarnings ); - mbd.getVisualEffects().add( mbeExplode04.clone() ); - mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 30 ) ); + mbd.addVisualEffects( mbeExplode04.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode03.clone().setOffsetTicks( 30 ), showWarnings ); - mbd.getVisualEffects().add( mbeExplode10.clone() ); - mbd.getVisualEffects().add( mbeExplode06.clone() ); - mbd.getVisualEffects().add( mbeExplode06a.clone() ); + mbd.addVisualEffects( mbeExplode10.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode06.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode06a.clone(), showWarnings ); mbd.setCooldownTicks( 60 ); + + mbd.setAnimationPattern( AnimationPattern.infinity ); mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } { MineBombData mbd = new MineBombData( - "OofBomb", "tnt_minecart", ExplosionShape.sphereHollow.name(), 21, "Oof Mine Bomb" ); + "OofBomb", "tnt_minecart", ExplosionShape.sphereHollow.name(), 21, "Oof Mine Bomb&r" ); mbd.setRadiusInner( 3 ); - mbd.setNameTag( "&c&k1&6&k23&e&k456&r&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&e&k654&6&k32&c&k1" ); + mbd.setNameTag( "&c&k1&6&k23&e&k456&r&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&e&k654&6&k32&c&k1&r" ); mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); mbd.setDescription("An oof-ably large mine bomb made with a minecart heaping with TNT. " + - "Unlike the large mine bomb, this one obviously is built with alien technology."); + "Unlike the large mine bomb, this one obviously is built with alien technology.&r"); mbd.setToolInHandName( "GOLDEN_PICKAXE" ); mbd.setToolInHandFortuneLevel( 13 ); - mbd.getSoundEffects().add( mbeSound01.clone() ); - mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 10 ).setVolumne( 0.25f ).setPitch( 0.25f ) ); - mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 20 ).setVolumne( 0.5f ).setPitch( 0.5f ) ); - mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ).setVolumne( 1.0f ).setPitch( 0.75f ) ); - mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 40 ).setVolumne( 2.0f ).setPitch( 1.5f ) ); - mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 50 ).setVolumne( 5.0f ).setPitch( 2.5f ) ); - - mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 0 ).setVolumne( 3.0f ) ); - mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 5 ).setVolumne( 1.5f ) ); - mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 10 ).setVolumne( 2.5f ) ); - mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 15 ).setVolumne( 1.0f ) ); - mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 20 ).setVolumne( 2.0f ) ); - mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 25 ).setVolumne( 0.75f ) ); - mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 30 ).setVolumne( 1.5f ) ); - mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 35 ).setVolumne( 0.55f ) ); - mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 40 ).setVolumne( 1.0f ) ); - mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 45 ).setVolumne( 0.25f ) ); - mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 50 ).setVolumne( 0.5f ) ); - mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 55 ).setVolumne( 0.15f ) ); - - - mbd.getVisualEffects().add( mbeExplode06.clone() ); - mbd.getVisualEffects().add( mbeExplode06a.clone() ); - mbd.getVisualEffects().add( mbeExplode03.clone() ); - mbd.getVisualEffects().add( mbeExplode12.clone() ); - mbd.getVisualEffects().add( mbeExplode12.clone().setOffsetTicks( 30 ) ); - mbd.getVisualEffects().add( mbeExplode12.clone().setOffsetTicks( 60 ) ); - mbd.getVisualEffects().add( mbeExplode07.clone().setOffsetTicks( 60 ) ); - mbd.getVisualEffects().add( mbeExplode08.clone().setOffsetTicks( 90 ) ); - - mbd.getVisualEffects().add( mbeExplode10.clone() ); - mbd.getVisualEffects().add( mbeExplode06.clone().setOffsetTicks( 20 ) ); + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 10 ).setVolumne( 0.25f ).setPitch( 0.25f ), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 20 ).setVolumne( 0.5f ).setPitch( 0.5f ), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ).setVolumne( 1.0f ).setPitch( 0.75f ), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 40 ).setVolumne( 2.0f ).setPitch( 1.5f ), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 50 ).setVolumne( 5.0f ).setPitch( 2.5f ), showWarnings ); + + mbd.addSoundEffects( mbeSound03.clone().setOffsetTicks( 0 ).setVolumne( 3.0f ), showWarnings ); + mbd.addSoundEffects( mbeSound04.clone().setOffsetTicks( 5 ).setVolumne( 1.5f ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone().setOffsetTicks( 10 ).setVolumne( 2.5f ), showWarnings ); + mbd.addSoundEffects( mbeSound04.clone().setOffsetTicks( 15 ).setVolumne( 1.0f ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone().setOffsetTicks( 20 ).setVolumne( 2.0f ), showWarnings ); + mbd.addSoundEffects( mbeSound04.clone().setOffsetTicks( 25 ).setVolumne( 0.75f ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone().setOffsetTicks( 30 ).setVolumne( 1.5f ), showWarnings ); + mbd.addSoundEffects( mbeSound04.clone().setOffsetTicks( 35 ).setVolumne( 0.55f ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone().setOffsetTicks( 40 ).setVolumne( 1.0f ), showWarnings ); + mbd.addSoundEffects( mbeSound04.clone().setOffsetTicks( 45 ).setVolumne( 0.25f ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone().setOffsetTicks( 50 ).setVolumne( 0.5f ), showWarnings ); + mbd.addSoundEffects( mbeSound04.clone().setOffsetTicks( 55 ).setVolumne( 0.15f ), showWarnings ); + + + mbd.addVisualEffects( mbeExplode06.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode06a.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode03.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode12.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode12.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addVisualEffects( mbeExplode12.clone().setOffsetTicks( 60 ), showWarnings ); + mbd.addVisualEffects( mbeExplode07.clone().setOffsetTicks( 60 ), showWarnings ); + mbd.addVisualEffects( mbeExplode08.clone().setOffsetTicks( 90 ), showWarnings ); + + mbd.addVisualEffects( mbeExplode10.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode06.clone().setOffsetTicks( 20 ), showWarnings ); mbd.setAutosell( true ); mbd.setGlowing( true ); @@ -190,34 +200,36 @@ public void setupDefaultMineBombData(MineBombs mineBombs) mbd.setCooldownTicks( 60 ); mbd.setFuseDelayTicks( 13 * 20 ); // 13 seconds + + mbd.setAnimationPattern( AnimationPattern.infinity ); mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } { MineBombData mbd = new MineBombData( - "WimpyBomb", "GUNPOWDER", ExplosionShape.sphere.name(), 5, - "A Wimpy Mine Bomb" ); + "WimpyBomb", "GUNPOWDER", ExplosionShape.sphere.name(), 2, + "A Wimpy Mine Bomb&r" ); // mbd.setLoreBombItemId( "&7A &2Wimpy &cBomb &9...&02A3F" ); - mbd.setNameTag( "&7A &2Wimpy &cBomb" ); + mbd.setNameTag( "&7A &2Wimpy &cBomb&r" ); mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); - mbd.setRadiusInner( 2 ); + mbd.setRadiusInner( 1 ); mbd.setDescription("A whimpy bomb made with gunpowder and packs the punch of a " + - "dull wooden pickaxe. For some reason, it only has a 40% chance of removing " + - "a block."); + "dull wooden pickaxe. For some reason, it only has a 30 percent chance " + + "of removing a block.&r"); - mbd.getLore().add( "" ); - mbd.getLore().add( "A whimpy bomb made with gunpowder and packs the punch " ); - mbd.getLore().add( "of a dull wooden pickaxe. For some reason, it only " ); - mbd.getLore().add( "has a 40% chance of removing a block." ); - mbd.getLore().add( "" ); - mbd.getLore().add( "Not labeled for retail sale." ); + mbd.getLore().add( "&r" ); + mbd.getLore().add( "A whimpy bomb made with gunpowder and packs the punch &r" ); + mbd.getLore().add( "of a dull wooden pickaxe. For some reason, it only &r" ); + mbd.getLore().add( "has a 40% chance of removing a block.&r" ); + mbd.getLore().add( "&r" ); + mbd.getLore().add( "Not labeled for retail sale.&r" ); mbd.setToolInHandName( "WOODEN_PICKAXE" ); mbd.setToolInHandFortuneLevel( 0 ); - mbd.setRemovalChance( 40.0d ); + mbd.setRemovalChance( 30.0d ); mbd.getAllowedMines().add( "a" ); mbd.getAllowedMines().add( "b" ); @@ -226,61 +238,255 @@ public void setupDefaultMineBombData(MineBombs mineBombs) 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() ); + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone(), showWarnings ); - mbd.getVisualEffects().add( mbeExplode01.clone() ); - mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); - mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 10 ) ); - mbd.getVisualEffects().add( mbeExplode04.clone() ); + mbd.addVisualEffects( mbeExplode01.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addVisualEffects( mbeExplode03.clone().setOffsetTicks( 10 ), showWarnings ); + mbd.addVisualEffects( mbeExplode04.clone(), showWarnings ); - mbd.getVisualEffects().add( mbeExplode10.clone() ); - mbd.getVisualEffects().add( mbeExplode06.clone() ); - mbd.getVisualEffects().add( mbeExplode06a.clone() ); - mbd.getVisualEffects().add( mbeExplode11.clone().setOffsetTicks( 05 ) ); + mbd.addVisualEffects( mbeExplode10.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode06.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode06a.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode11.clone().setOffsetTicks( 05 ), showWarnings ); mbd.setCooldownTicks( 3 * 20 ); // 3 seconds - mbd.setFuseDelayTicks( 2 * 20 ); // 2 seconds + mbd.setFuseDelayTicks( 15 * 20 ); // 15 seconds + mbd.setThrowVelocityLow( 0.25 ); + mbd.setThrowVelocityHigh( 1.25 ); + mbd.setGlowing( true ); mbd.setGravity( false ); mbd.setCooldownTicks( 5 ); + mbd.setAnimationPattern( AnimationPattern.infinityEight ); + mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } { MineBombData mbd = new MineBombData( - "CubeBomb", "SLIME_BLOCK", ExplosionShape.cube.name(), 2, - "A Cubic Bomb" ); + "CubeBomb", "SLIME_BALL", ExplosionShape.cube.name(), 2, + "A Cubic Bomb&r" ); mbd.setDescription("The most anti-round bomb you will ever be able to find. " + - "It's totally cubic."); + "It's totally cubic.&r"); - mbd.setNameTag( "&a-=- &7{name}&a -=--" ); + mbd.setNameTag( "&a-=- &7{name}&a -=--&r" ); mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); mbd.setToolInHandName( "DIAMOND_PICKAXE" ); mbd.setToolInHandFortuneLevel( 7 ); mbd.setRemovalChance( 100.0d ); - mbd.getSoundEffects().add( mbeSound01.clone() ); - mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); - mbd.getSoundEffects().add( mbeSound03.clone() ); + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone(), showWarnings ); - mbd.getVisualEffects().add( mbeExplode04.clone() ); - mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); + mbd.addVisualEffects( mbeExplode04.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode02.clone().setOffsetTicks( 30 ), showWarnings ); mbd.setGlowing( true ); - mbd.setCooldownTicks( 60 ); + mbd.setCooldownTicks( 20 ); + mbd.setFuseDelayTicks( 15 * 20 ); // 15 seconds + + mbd.setAnimationPattern( AnimationPattern.orbital ); + mbd.setAnimationArmorStandItemLocation( AnimationArmorStandItemLocation.head ); mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); } + + { + MineBombData mbd = new MineBombData( + "NoneBomb", "COAL", ExplosionShape.sphere.name(), 2, + "This is a bomb?&r" ); + mbd.setDescription("This old bomb is a dud.&r"); + + mbd.setNameTag( "&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&r" ); + mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); + + mbd.setToolInHandName( "STONE_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 1 ); + mbd.setRemovalChance( 25.0d ); + + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone(), showWarnings ); + + mbd.addVisualEffects( mbeExplode04.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode02.clone().setOffsetTicks( 30 ), showWarnings ); + + mbd.setCooldownTicks( 20 ); + mbd.setFuseDelayTicks( 15 * 20 ); // 15 seconds + + mbd.setThrowVelocityLow( 0.25 ); + mbd.setThrowVelocityHigh( 3.5 ); + + + mbd.setAnimationPattern( AnimationPattern.none ); + + mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + } + + + + { + MineBombData mbd = new MineBombData( + "BounceBomb", "IRON_INGOT", ExplosionShape.sphere.name(), 2, + "This is a bomb?&r" ); + mbd.setDescription("This old bomb is a dud.&r"); + + mbd.setNameTag( "&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&r" ); + mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); + + mbd.setToolInHandName( "STONE_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 1 ); + mbd.setRemovalChance( 50.0d ); + + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone(), showWarnings ); + + mbd.addVisualEffects( mbeExplode04.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode02.clone().setOffsetTicks( 30 ), showWarnings ); + + mbd.setCooldownTicks( 20 ); + mbd.setFuseDelayTicks( 15 * 20 ); // 15 seconds + + mbd.setThrowVelocityLow( 0.25 ); + mbd.setThrowVelocityHigh( 1.5 ); + + + mbd.setAnimationPattern( AnimationPattern.bounce ); + + mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + } + + + + { + MineBombData mbd = new MineBombData( + "OrbitalBomb", "GOLD_INGOT", ExplosionShape.sphere.name(), 2, + "This is a bomb?&r" ); + mbd.setDescription("This old bomb is a dud.&r"); + + mbd.setNameTag( "&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&r" ); + mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); + + mbd.setToolInHandName( "STONE_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 1 ); + mbd.setRemovalChance( 50.0d ); + + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone(), showWarnings ); + + mbd.addVisualEffects( mbeExplode04.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode02.clone().setOffsetTicks( 30 ), showWarnings ); + + mbd.setCooldownTicks( 20 ); + mbd.setFuseDelayTicks( 15 * 20 ); // 15 seconds + + mbd.setThrowVelocityLow( 0.25 ); + mbd.setThrowVelocityHigh( 1.5 ); + + + mbd.setAnimationPattern( AnimationPattern.orbital ); + mbd.setAnimationArmorStandItemLocation( AnimationArmorStandItemLocation.head ); + + mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + } + + + + { + MineBombData mbd = new MineBombData( + "Orbital8Bomb", "DIAMOND", ExplosionShape.sphere.name(), 2, + "This is a bomb?&r" ); + mbd.setDescription("This old bomb is a dud.&r"); + + mbd.setNameTag( "&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&r" ); + mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); + + mbd.getLore().add( "&7Hex Colors: &#e81416Red&#ffa500Orange&#faeb36Yellow" + + "Oc314Greenǧde7Blueb369dIndigo𑋡dViolet" ); + + mbd.setToolInHandName( "STONE_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 1 ); + mbd.setRemovalChance( 50.0d ); + + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone(), showWarnings ); + + mbd.addVisualEffects( mbeExplode04.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode02.clone().setOffsetTicks( 30 ), showWarnings ); + + mbd.setCooldownTicks( 20 ); + mbd.setFuseDelayTicks( 15 * 20 ); // 15 seconds + + mbd.setThrowVelocityLow( 0.25 ); + mbd.setThrowVelocityHigh( 1.5 ); + + + mbd.setAnimationPattern( AnimationPattern.orbitalEight ); + mbd.setAnimationArmorStandItemLocation( AnimationArmorStandItemLocation.head ); + + mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + } + + + + { + MineBombData mbd = new MineBombData( + "starburstBomb", "WHEAT", ExplosionShape.sphere.name(), 2, + "This is a bomb?&r" ); + mbd.setDescription("This old bomb is a star!r"); + + mbd.setNameTag( "&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&r" ); + mbd.setItemName( MineBombData.MINE_BOMB_DEFAULT_ITEM_NAME ); + + mbd.getLore().add( "&7Hex Colors: &#e81416Red&#ffa500Orange&#faeb36Yellow" + + "Oc314Greenǧde7Blueb369dIndigo𑋡dViolet" ); + + mbd.setToolInHandName( "STONE_PICKAXE" ); + mbd.setToolInHandFortuneLevel( 1 ); + mbd.setRemovalChance( 50.0d ); + + mbd.addSoundEffects( mbeSound01.clone(), showWarnings ); + mbd.addSoundEffects( mbeSound02.clone().setOffsetTicks( 30 ), showWarnings ); + mbd.addSoundEffects( mbeSound03.clone(), showWarnings ); + + mbd.addVisualEffects( mbeExplode04.clone(), showWarnings ); + mbd.addVisualEffects( mbeExplode02.clone().setOffsetTicks( 30 ), showWarnings ); + + mbd.setCooldownTicks( 20 ); + mbd.setFuseDelayTicks( 15 * 20 ); // 15 seconds + + mbd.setThrowVelocityLow( 0.25 ); + mbd.setThrowVelocityHigh( 1.5 ); + + + mbd.setAnimationPattern( AnimationPattern.starburst ); + mbd.setAnimationRadius( 1.5 ); + mbd.setAnimationRadiusDelta( .75 ); + mbd.setAnimationAlternateDirections( true ); + mbd.setAnimationSpeed( 9.0 ); + + + mineBombs.getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); + } + + + + mineBombs.saveConfigJson(); Output.get().logInfo( "Mine bombs: setup default values." ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombDetonateTask.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombDetonateTask.java new file mode 100644 index 000000000..ffc748c10 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombDetonateTask.java @@ -0,0 +1,7 @@ +package tech.mcprison.prison.bombs; + +public interface MineBombDetonateTask { + + public void runDetonation(); + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombEffectsData.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombEffectsData.java index 21e9a5b44..28debab78 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombEffectsData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombEffectsData.java @@ -23,6 +23,8 @@ public class MineBombEffectsData Comparable { + private EffectType effectType = EffectType.unknown; + private String effectName; private EffectState effectState; @@ -32,6 +34,15 @@ public class MineBombEffectsData private float volumne; private float pitch; + private transient boolean valid; + + + public enum EffectType { + unknown, + sounds, + visuals; + } + public enum EffectState { placed, explode, @@ -40,22 +51,30 @@ public enum EffectState { protected MineBombEffectsData() { super(); + + this.valid = true; } - public MineBombEffectsData( String effectName, EffectState effectState, + public MineBombEffectsData( + String effectName, EffectState effectState, int offsetTicks ) { super(); + this.effectType = EffectType.unknown; + this.effectName = effectName; this.effectState = effectState; this.offsetTicks = offsetTicks; this.volumne = 1.0f; this.pitch = 1.0f; + + this.valid = true; } - public MineBombEffectsData( String effectName, EffectState effectState, + public MineBombEffectsData( + String effectName, EffectState effectState, int offsetTicks, float volume, float pitch ) { this( effectName, effectState, offsetTicks ); @@ -65,30 +84,42 @@ public MineBombEffectsData( String effectName, EffectState effectState, public MineBombEffectsData clone() { - return new MineBombEffectsData( getEffectName(), getEffectState(), getOffsetTicks(), + MineBombEffectsData cloned = new MineBombEffectsData( + getEffectName(), getEffectState(), getOffsetTicks(), getVolumne(), getPitch() ); + + cloned.setEffectType( getEffectType() ); + cloned.setValid( isValid() ); + + return cloned; } @Override public String toString() { - return getEffectName() + " (state: " + getEffectState().name() + " offset: " + getOffsetTicks() + + return getEffectName() + " (" + getEffectType().name() + + " state: " + getEffectState().name() + " offset: " + getOffsetTicks() + " ticks v: " + getVolumne() + " p: " + getPitch() + ")"; } public String toStringShort() { - return getEffectName() + " (state: " + getEffectState().name() + " offset: " + getOffsetTicks() + + return getEffectName() + " (" + getEffectType().name() + + " state: " + getEffectState().name() + " offset: " + getOffsetTicks() + " ticks)"; } @Override public int compare( MineBombEffectsData o1, MineBombEffectsData o2 ) { - int results = o1.getEffectState().compareTo( o2.getEffectState() ); + int results = o1.getEffectType().compareTo( o2.getEffectType() ); if ( results == 0 ) { - results = Integer.compare( o1.getOffsetTicks(), o2.getOffsetTicks() ); + results = o1.getEffectState().compareTo( o2.getEffectState() ); if ( results == 0 ) { - results = o1.getEffectName().compareTo( o2.getEffectName() ); + results = Integer.compare( o1.getOffsetTicks(), o2.getOffsetTicks() ); + + if ( results == 0 ) { + results = o1.getEffectName().compareTo( o2.getEffectName() ); + } } } return results; @@ -101,6 +132,13 @@ public int compareTo( MineBombEffectsData o ) } + public EffectType getEffectType() { + return effectType; + } + public void setEffectType(EffectType effectType) { + this.effectType = effectType; + } + public String getEffectName() { return effectName; } @@ -144,4 +182,11 @@ public MineBombEffectsData setPitch( float pitch ) { return this; } + public boolean isValid() { + return valid; + } + public void setValid(boolean valid) { + this.valid = valid; + } + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombMessages.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombMessages.java new file mode 100644 index 000000000..58451dd75 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/MineBombMessages.java @@ -0,0 +1,20 @@ +package tech.mcprison.prison.bombs; + +import java.text.DecimalFormat; + +import tech.mcprison.prison.Prison; + +public class MineBombMessages { + + static public String mineBombsCoolDownMsg( int cooldownTicks ) { + + double cooldownSeconds = cooldownTicks / 20.0f; + DecimalFormat dFmt = Prison.get().getDecimalFormat( "0.0" ); + + return Prison.get().getLocaleManager() + .getLocalizable( "core_minebombs__cooldown_delay" ) + .withReplacements( + dFmt.format(cooldownSeconds) ) + .localize(); + } +} 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 0a1c2e592..b794ed91d 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 @@ -7,22 +7,32 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.file.JsonFileIO; +import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.modules.Module; +import tech.mcprison.prison.modules.ModuleElementType; import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.util.Location; import tech.mcprison.prison.util.Text; public class MineBombs + implements Comparable { + public static final String MINE_BOMBS_NBT_KEY = "MineBombNbtKey"; + public static final String MINE_BOMBS_NBT_THROWER_UUID = "MineBombNbtThrowerUUID"; + public static final String MINE_BOMBS_NBT_OWNER_UUID = "MineBombNbtOwnerUUID"; + public static final String MINE_BOMBS_FILE_NAME = "mineBombsConfig.json"; public static final String MINE_BOMBS_PATH_NAME = "module_conf/mines"; - public static final String MINE_BOMBS_NBT_BOMB_KEY = "PrisonMineBombNbtKey"; +// public static final String MINE_BOMBS_NBT_BOMB_KEY = "PrisonMineBombNbtKey"; private static MineBombs instance; + + private MineBombsConfigData configData; @@ -77,10 +87,92 @@ public enum ExplosionOrientation { y_axis, z_axis, - full + full; + + public static List asList() + { + List results = new ArrayList<>(); + + for ( ExplosionOrientation orientation : values() ) + { + results.add( orientation.name() ); + } + + return results; + } + } + + + public enum AnimationPattern { + none, + infinity, + infinityEight, + bounce, + orbital, + orbitalEight, + starburst + + ; + + public static final AnimationPattern fromString( String animationPattern ) { + AnimationPattern results = AnimationPattern.infinity; + + if ( animationPattern != null ) { + + for (AnimationPattern ap : values() ) { + if ( ap.name().equalsIgnoreCase( animationPattern) ) { + results = ap; + break; + } + } + } + + return results; + } + + public static List asList() + { + List results = new ArrayList<>(); + + for ( AnimationPattern animation : values() ) + { + results.add( animation.name() ); + } + + return results; + } } - private MineBombs() { + public enum AnimationArmorStandItemLocation { + hand, + head; + + public static final AnimationArmorStandItemLocation fromString( String animationItemLocation ) { + AnimationArmorStandItemLocation results = AnimationArmorStandItemLocation.hand; + + if ( animationItemLocation != null ) { + + for (AnimationArmorStandItemLocation ail : values() ) { + if ( ail.name().equalsIgnoreCase( animationItemLocation) ) { + results = ail; + break; + } + } + } + + return results; + } + + } + + + /** + * DO NOT USE! + * This has been set to protected only to be used by + * junit tests! + * DO NOT USE this constructor! + */ + protected MineBombs() { super(); this.configData = new MineBombsConfigData(); @@ -101,28 +193,134 @@ public static MineBombs getInstance() { } return instance; } + + + @Override + public int compareTo(MineBombs o) { + + int results = 0; + + if ( o == null ) { + results = -1; + } + + if ( results == 0 ) { + + MineBombsConfigData cData = getConfigData(); + MineBombsConfigData cDataO = o.getConfigData(); + + results = cData.compareTo( cDataO ); + } + + return results; + } + + public static int checkPlayerCooldown( Player player ) { + + int cooldownTicks = MineBombCooldownTask.checkPlayerCooldown( player ); + return cooldownTicks; + } + + public static boolean addPlayerCooldown( Player player, int ticks ) { + + boolean results = MineBombCooldownTask.addPlayerCooldown( player, ticks ); + return results; + } + + + public MineBombData findBombByName( Player player, String bombName ) + throws MineBombCooldownException + { + return findBombByName( player, bombName, true ); + } /** - *

This finds a bomb with the given name, and returns a clone. The clone is - * important since individual instances will set the isActivated() variable to - * true if the bomb is active. If it's activated, then that indicates the - * bomb will be used and the bomb was removed from the player's inventory. + *

This finds a bomb based upon a bombName which may include formatting. + * All formatting is removed from the search name, and the bomb names prior to + * making any comparisons. The bomb's key is also checked too for a match. + *

+ * + *

When a mine bomb is found, it is cloned since some bomb values will + * change during the detonation sequence, so cloning prevents altering the + * original source. *

* + * @param player * @param bombName + * @param enableCooldown If true, then will force a cooldown on finding minebombs * @return */ - public MineBombData findBomb( String bombName ) { - MineBombData bombOriginal = null; + public MineBombData findBombByName( Player player, String bombName, + boolean enableCooldown ) + throws MineBombCooldownException + { + MineBombData results = null; + + StringBuilder dbug = new StringBuilder(); + + String cleanedBombName = Text.stripColor( bombName.toLowerCase() ); - if ( bombName != null ) { + dbug.append( "&3## findBombByName: [&a" ).append( cleanedBombName ).append( "&3] "); + + if ( cleanedBombName != null && !cleanedBombName.isEmpty() ) { + for ( String bombKey : getConfigData().getBombs().keySet() ) + { + MineBombData bomb = getConfigData().getBombs().get( bombKey ); + + if ( bomb != null ) { + String cBombName = Text.stripColor( bomb.getName().toLowerCase() ); + + if ( cBombName != null && + (cBombName.equalsIgnoreCase( cleanedBombName ) || + cleanedBombName.equalsIgnoreCase( bombKey )) ) { + + dbug.append( " &aMatch! &3" ); + + results = bomb; + } + } + + + } + } + + if ( results != null && enableCooldown ) { + + int ticks = results.getCooldownTicks(); + int cooldownTicks = MineBombCooldownTask.checkPlayerCooldown( player ); - bombOriginal = getConfigData().getBombs().get( bombName.toLowerCase() ); + if ( cooldownTicks <= 0 ) { + // Submit another cooldown: + MineBombCooldownTask.addPlayerCooldown( player, ticks ); + + dbug.append( "&3 StartCoolDown: " ).append( ticks ).append( " ticks" ); + } + else { + // The player is still in a cooldown using minebombs, so + // return a null instead of the bomb. + + dbug.append( "&3 CoolDownIsInEffect: " ) + .append( cooldownTicks ).append( " ticks remaining" ).append(" &aRejected! &3 " ); + + MineBombCooldownException cooldownException = new MineBombCooldownException( cooldownTicks ); + + throw cooldownException; + + } } - return bombOriginal.clone(); + dbug.append( " &3Results: ").append( results == null ? "&cFail-NoBomb" : "&aSuccess" ); + + if ( Output.get().isDebug() ) { + Output.get().logInfo( dbug.toString() ); + } + + return results == null ? null : results.clone(); } + + + public void saveConfigJson() { JsonFileIO fio = new JsonFileIO( null, null ); @@ -136,6 +334,22 @@ public void saveConfigJson() { } + public String toJson() { + JsonFileIO fio = new JsonFileIO( null, null ); + + String json = fio.toString( this ); + + return json; + } + + public static MineBombs fromJson( String json ) { + JsonFileIO fio = new JsonFileIO(); + + MineBombs mBombs = fio.fromString( json, MineBombs.class ); + + return mBombs; + } + public File getConfigFile( JsonFileIO jsonFileIO ) { File path = new File( jsonFileIO.getProjectRootDiretory(), MINE_BOMBS_PATH_NAME ); @@ -153,9 +367,16 @@ public void loadConfigJson() { boolean configExists = configFile.exists(); if ( !configExists ) { + + + // The save file does not exist so regenerate the default bombs listing: + getConfigData().getBombs().clear(); + MineBombDefaultConfigSettings defaultConfigs = new MineBombDefaultConfigSettings(); + defaultConfigs.setupDefaultMineBombData( this ); + } else { @@ -164,9 +385,13 @@ public void loadConfigJson() { (MineBombsConfigData) fio.readJsonFile( configFile, getConfigData() ); if ( configs != null ) { + + boolean dirty = configs.validateMineBombEffects( true ); + setConfigData( configs ); - if ( configs.getDataFormatVersion() < + if ( dirty || + configs.getDataFormatVersion() < MineBombsConfigData.MINE_BOMB_DATA_FORMAT_VERSION ) { // Need to update the format version then save a new copy of the configs. @@ -181,7 +406,7 @@ public void loadConfigJson() { boolean renamed = configFile.renameTo( backupFile ); - if ( renamed ) { + if ( renamed || dirty ) { configs.setDataFormatVersion( MineBombsConfigData.MINE_BOMB_DATA_FORMAT_VERSION ); fio.saveJsonFile( configFile, configs ); @@ -263,6 +488,16 @@ public void validateMineBombs() MineBombsConfigData config = getConfigData(); + + Module moduleMines = Prison.get().getModuleManager() == null ? + null : Prison.get().getModuleManager().getModule( ModuleElementType.MINE.name() ); + boolean hasMines = moduleMines == null ? + false : moduleMines.isEnabled() && moduleMines.getElementCount() > 0; + +// Module moduleRanks = Prison.get().getModuleManager().getModule( ModuleElementType.RANK.name() ); +// boolean hasRanks = moduleRanks.isEnabled() && moduleRanks.getElementCount() > 0; + + if ( config.getDataFormatVersion() > MineBombsConfigData.MINE_BOMB_DATA_FORMAT_VERSION || config.getDataFormatVersion() < 0 ) { config.setDataFormatVersion( MineBombsConfigData.MINE_BOMB_DATA_FORMAT_VERSION ); @@ -277,24 +512,11 @@ public void validateMineBombs() { MineBombData bomb = config.getBombs().get( key ); - // bombItemId is the first line of the lore and should id the bomb: -// String cleanBombItemId = Text.stripColor( bomb.getBombItemId().replace( " ", "" )); -// if ( !cleanBombItemId.equalsIgnoreCase( bomb.getBombItemId() ) ) { -// -// errors.add( String.format( -// "Invalid bombItemId: was: [%s] fixed: [%s].", -// bomb.getBombItemId(), -// cleanBombItemId ) ); -// bomb.setBombItemId( cleanBombItemId ); -// isDirty = true; -// } - // Bomb names can contain color codes now, but not spaces, since that will // mess up commands related to bombs, since the commands would require the bomb names // to not have a space. String cleanName = bomb.getName().replace( " ", "_" ); -// String cleanName = Text.stripColor( bomb.getName().replace( " ", "_" )); if ( !cleanName.equalsIgnoreCase( bomb.getName() ) ) { errors.add( String.format( @@ -392,7 +614,10 @@ public void validateMineBombs() cleaned = true; } - if ( !Prison.get().getPlatform().isMineNameValid(cleanedMineName) ) { + // Only purge mines if the mines module is enabled and there are more than one mines. + // If enabled and no mines, then could be that its clean startup and mines have not yet + // been added, so do not purge any mines. + if ( hasMines && !Prison.get().getPlatform().isMineNameValid(cleanedMineName) ) { Output.get().log( "MineBomb %s: invalid mine name for allowedMines: %s Removed.", LogLevel.WARNING, bomb.getName(), cleanedMineName ); @@ -422,7 +647,10 @@ public void validateMineBombs() cleaned = true; } - if ( !Prison.get().getPlatform().isMineNameValid(cleanedMineName) ) { + // Only purge mines if the mines module is enabled and there are more than one mines. + // If enabled and no mines, then could be that its clean startup and mines have not yet + // been added, so do not purge any mines. + if ( hasMines && !Prison.get().getPlatform().isMineNameValid(cleanedMineName) ) { Output.get().log( "MineBomb %s: invalid mine name for prevented-Mines: %s Removed.", LogLevel.WARNING, bomb.getName(), cleanedMineName ); @@ -596,274 +824,6 @@ public List calculateCube( Location loc1, Location loc2 ) { -// -// @SuppressWarnings( "unused" ) -// public void setupDefaultMineBombData() -// { -// if ( getConfigData().getBombs().size() == 0 ) { -// -//// XMaterial.WOODEN_PICKAXE; -//// XMaterial.STONE_PICKAXE; -//// XMaterial.IRON_PICKAXE; -//// XMaterial.GOLDEN_PICKAXE; -//// XMaterial.DIAMOND_PICKAXE; -//// XMaterial.NETHERITE_PICKAXE; -// -// MineBombEffectsData mbeSound01 = new MineBombEffectsData( "ENTITY_CREEPER_PRIMED", EffectState.placed, 0 ); -// MineBombEffectsData mbeSound02 = new MineBombEffectsData( "CAT_HISS", EffectState.placed, 0 ); -// -// MineBombEffectsData mbeSound03 = new MineBombEffectsData( "ENTITY_GENERIC_EXPLODE", EffectState.explode, 0 ); -// MineBombEffectsData mbeSound04 = new MineBombEffectsData( "ENTITY_DRAGON_FIREBALL_EXPLODE", EffectState.explode, 0 ); -// -// // Does not work with spigot 1.8.x: -// MineBombEffectsData mbeExplode01 = new MineBombEffectsData( "FIREWORKS_SPARK", EffectState.placed, 0 ); -// // Does not work with spigot 1.8.x: -// MineBombEffectsData mbeExplode02 = new MineBombEffectsData( "BUBBLE_COLUMN_UP", EffectState.placed, 0 ); -// MineBombEffectsData mbeExplode03 = new MineBombEffectsData( "ENCHANTMENT_TABLE", EffectState.placed, 0 ); -// -//// MineBombEffectsData mbeExplode05 = new MineBombEffectsData( "END_ROD", EffectState.placed, 0 ); -// MineBombEffectsData mbeExplode04 = new MineBombEffectsData( "FLAME", EffectState.placed, 0 ); -// // Does not work with spigot 1.8.x: -// MineBombEffectsData mbeExplode08 = new MineBombEffectsData( "DRAGON_BREATH", EffectState.placed, 0 ); -// -// MineBombEffectsData mbeExplode06a = new MineBombEffectsData( "SMOKE", EffectState.placed, 0 ); -// // Does not work with spigot 1.8.x: -// MineBombEffectsData mbeExplode06 = new MineBombEffectsData( "SMOKE_NORMAL", EffectState.placed, 0 ); -// // Does not work with spigot 1.8.x: -// MineBombEffectsData mbeExplode07 = new MineBombEffectsData( "SMOKE_LARGE", EffectState.placed, 0 ); -// -// MineBombEffectsData mbeExplode10 = new MineBombEffectsData( "EXPLOSION_NORMAL", EffectState.explode, 0 ); -// MineBombEffectsData mbeExplode11 = new MineBombEffectsData( "EXPLOSION_LARGE", EffectState.explode, 0 ); -// // Does not work with spigot 1.8.x: -// MineBombEffectsData mbeExplode12 = new MineBombEffectsData( "EXPLOSION_HUGE", EffectState.explode, 0 ); -// -// -// { -// MineBombData mbd = new MineBombData( -// "SmallBomb", "brewing_stand", ExplosionShape.sphere.name(), 2, "&dSmall &6Mine &eBomb &3(lore line 1)" ); -// -// mbd.setNameTag( "&6&kABC&r&c-= &7{name}&c =-&6&kCBA" ); -// -// mbd.setToolInHandName( "DIAMOND_PICKAXE" ); -// mbd.setToolInHandFortuneLevel( 0 ); -// mbd.setDescription("A small mine bomb made with some chemicals and a brewing stand."); -// -// mbd.getLore().add( "&4Lore line 2" ); -// mbd.getLore().add( "&aLore line &73" ); -// -// mbd.getSoundEffects().add( mbeSound01.clone() ); -// mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); -// mbd.getSoundEffects().add( mbeSound03.clone() ); -// -// mbd.getVisualEffects().add( mbeExplode04.clone() ); -// mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 30 ) ); -// -// mbd.getVisualEffects().add( mbeExplode06a.clone() ); -// mbd.getVisualEffects().add( mbeExplode10.clone() ); -// mbd.getVisualEffects().add( mbeExplode06.clone() ); -// -// mbd.setCooldownTicks( 10 ); -// -// getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); -// -// } -// -// { -// MineBombData mbd = new MineBombData( -// "MediumBomb", "firework_rocket", ExplosionShape.sphere.name(), 5, "Medium Mine Bomb" ); -// mbd.setDescription("A medium mine bomb made from leftover fireworks, " + -// "but supercharged with a strange green glowing liquid."); -// -// mbd.setNameTag( "&6&k1 23 456&r&a-=- &7{name}&a -=-&6&k654 32 1" ); -// -// mbd.setToolInHandName( "DIAMOND_PICKAXE" ); -// mbd.setToolInHandFortuneLevel( 3 ); -// -// mbd.getSoundEffects().add( mbeSound01.clone() ); -// mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); -// mbd.getSoundEffects().add( mbeSound03.clone() ); -// -// mbd.getVisualEffects().add( mbeExplode04.clone() ); -// mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 30 ) ); -// -// mbd.getVisualEffects().add( mbeExplode10.clone() ); -// mbd.getVisualEffects().add( mbeExplode06.clone() ); -// -// mbd.setCooldownTicks( 60 ); -// -// getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); -// -// } -// -// { -// MineBombData mbd = new MineBombData( -// "LargeBomb", "tnt", ExplosionShape.sphereHollow.name(), 12, "Large Mine Bomb" ); -// mbd.setRadiusInner( 3 ); -// mbd.setDescription("A large mine bomb made from TNT with some strange parts " + -// "that maybe be described as alien technology."); -// mbd.setToolInHandName( "DIAMOND_PICKAXE" ); -// mbd.setToolInHandFortuneLevel( 3 ); -// -// mbd.getSoundEffects().add( mbeSound01.clone() ); -// mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); -// mbd.getSoundEffects().add( mbeSound03.clone().setVolumne( 2.0f ) ); -// -// mbd.getVisualEffects().add( mbeExplode04.clone() ); -// mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 30 ) ); -// -// mbd.getVisualEffects().add( mbeExplode10.clone() ); -// mbd.getVisualEffects().add( mbeExplode06.clone() ); -// mbd.getVisualEffects().add( mbeExplode06a.clone() ); -// -// mbd.setCooldownTicks( 60 ); -// -// getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); -// } -// -// { -// MineBombData mbd = new MineBombData( -// "OofBomb", "tnt_minecart", ExplosionShape.sphereHollow.name(), 21, "Oof Mine Bomb" ); -// mbd.setRadiusInner( 3 ); -// -// mbd.setNameTag( "&c&k1&6&k23&e&k456&r&a-=- &4{countdown} &5-=- &7{name} &5-=- &4{countdown} &a-=-&e&k654&6&k32&c&k1" ); -// -// mbd.setDescription("An oof-ably large mine bomb made with a minecart heaping with TNT. " + -// "Unlike the large mine bomb, this one obviously is built with alien technology."); -// -// mbd.setToolInHandName( "GOLDEN_PICKAXE" ); -// mbd.setToolInHandFortuneLevel( 13 ); -// -// mbd.getSoundEffects().add( mbeSound01.clone() ); -// mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 10 ).setVolumne( 0.25f ).setPitch( 0.25f ) ); -// mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 20 ).setVolumne( 0.5f ).setPitch( 0.5f ) ); -// mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ).setVolumne( 1.0f ).setPitch( 0.75f ) ); -// mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 40 ).setVolumne( 2.0f ).setPitch( 1.5f ) ); -// mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 50 ).setVolumne( 5.0f ).setPitch( 2.5f ) ); -// -// mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 0 ).setVolumne( 3.0f ) ); -// mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 5 ).setVolumne( 1.5f ) ); -// mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 10 ).setVolumne( 2.5f ) ); -// mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 15 ).setVolumne( 1.0f ) ); -// mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 20 ).setVolumne( 2.0f ) ); -// mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 25 ).setVolumne( 0.75f ) ); -// mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 30 ).setVolumne( 1.5f ) ); -// mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 35 ).setVolumne( 0.55f ) ); -// mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 40 ).setVolumne( 1.0f ) ); -// mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 45 ).setVolumne( 0.25f ) ); -// mbd.getSoundEffects().add( mbeSound03.clone().setOffsetTicks( 50 ).setVolumne( 0.5f ) ); -// mbd.getSoundEffects().add( mbeSound04.clone().setOffsetTicks( 55 ).setVolumne( 0.15f ) ); -// -// -// mbd.getVisualEffects().add( mbeExplode06.clone() ); -// mbd.getVisualEffects().add( mbeExplode06a.clone() ); -// mbd.getVisualEffects().add( mbeExplode03.clone() ); -// mbd.getVisualEffects().add( mbeExplode12.clone() ); -// mbd.getVisualEffects().add( mbeExplode12.clone().setOffsetTicks( 30 ) ); -// mbd.getVisualEffects().add( mbeExplode12.clone().setOffsetTicks( 60 ) ); -// mbd.getVisualEffects().add( mbeExplode07.clone().setOffsetTicks( 60 ) ); -// mbd.getVisualEffects().add( mbeExplode08.clone().setOffsetTicks( 90 ) ); -// -// mbd.getVisualEffects().add( mbeExplode10.clone() ); -// mbd.getVisualEffects().add( mbeExplode06.clone().setOffsetTicks( 20 ) ); -// -// mbd.setAutosell( true ); -// mbd.setGlowing( true ); -// mbd.setAutosell( true ); -// -// mbd.setCooldownTicks( 60 ); -// mbd.setFuseDelayTicks( 13 * 20 ); // 13 seconds -// -// getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); -// } -// -// { -// MineBombData mbd = new MineBombData( -// "WimpyBomb", "GUNPOWDER", ExplosionShape.sphere.name(), 5, -// "A Wimpy Mine Bomb" ); -//// mbd.setLoreBombItemId( "&7A &2Wimpy &cBomb &9...&02A3F" ); -// -// mbd.setNameTag( "&7A &2Wimpy &cBomb" ); -// -// mbd.setRadiusInner( 2 ); -// mbd.setDescription("A whimpy bomb made with gunpowder and packs the punch of a " + -// "dull wooden pickaxe. For some reason, it only has a 40% chance of removing " + -// "a block."); -// -// mbd.getLore().add( "" ); -// mbd.getLore().add( "A whimpy bomb made with gunpowder and packs the punch " ); -// mbd.getLore().add( "of a dull wooden pickaxe. For some reason, it only " ); -// mbd.getLore().add( "has a 40% chance of removing a block." ); -// mbd.getLore().add( "" ); -// mbd.getLore().add( "Not labeled for retail sale." ); -// -// mbd.setToolInHandName( "WOODEN_PICKAXE" ); -// mbd.setToolInHandFortuneLevel( 0 ); -// mbd.setRemovalChance( 40.0d ); -// -// mbd.getSoundEffects().add( mbeSound01.clone() ); -// mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); -// mbd.getSoundEffects().add( mbeSound03.clone() ); -// -// mbd.getVisualEffects().add( mbeExplode01.clone() ); -// mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); -// mbd.getVisualEffects().add( mbeExplode03.clone().setOffsetTicks( 10 ) ); -// mbd.getVisualEffects().add( mbeExplode04.clone() ); -// -// mbd.getVisualEffects().add( mbeExplode10.clone() ); -// mbd.getVisualEffects().add( mbeExplode06.clone() ); -// mbd.getVisualEffects().add( mbeExplode06a.clone() ); -// mbd.getVisualEffects().add( mbeExplode11.clone().setOffsetTicks( 05 ) ); -// -// mbd.setCooldownTicks( 3 * 20 ); // 3 seconds -// mbd.setFuseDelayTicks( 2 * 20 ); // 2 seconds -// -// mbd.setGlowing( true ); -// mbd.setGravity( false ); -// -// mbd.setCooldownTicks( 5 ); -// -// getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); -// } -// -// -// { -// MineBombData mbd = new MineBombData( -// "CubeBomb", "SLIME_BLOCK", ExplosionShape.cube.name(), 2, -// "A Cubic Bomb" ); -// mbd.setDescription("The most anti-round bomb you will ever be able to find. " + -// "It's totally cubic."); -// -// mbd.setToolInHandName( "DIAMOND_PICKAXE" ); -// mbd.setToolInHandFortuneLevel( 7 ); -// mbd.setRemovalChance( 100.0d ); -// -// mbd.getSoundEffects().add( mbeSound01.clone() ); -// mbd.getSoundEffects().add( mbeSound02.clone().setOffsetTicks( 30 ) ); -// mbd.getSoundEffects().add( mbeSound03.clone() ); -// -// mbd.getVisualEffects().add( mbeExplode04.clone() ); -// mbd.getVisualEffects().add( mbeExplode02.clone().setOffsetTicks( 30 ) ); -// -// mbd.setGlowing( true ); -// -// mbd.setCooldownTicks( 60 ); -// -// getConfigData().getBombs().put( mbd.getName().toLowerCase(), mbd ); -// } -// -// -// saveConfigJson(); -// -// Output.get().logInfo( "Mine bombs: setup default values." ); -// } -// else { -// Output.get().logInfo( "Could not generate a mine bombs save file since at least one " + -// "mine bomb already exists." ); -// } -// -// } - - public MineBombsConfigData getConfigData() { return configData; } @@ -871,33 +831,4 @@ public void setConfigData( MineBombsConfigData configData ) { this.configData = configData; } - - public MineBombData findBombByName( String bombName ) - { - MineBombData results = null; - - String cleanedBombName = Text.stripColor( bombName ); - - if ( cleanedBombName != null && !cleanedBombName.isEmpty() ) { - for ( String bombKey : getConfigData().getBombs().keySet() ) - { - MineBombData bomb = getConfigData().getBombs().get( bombKey ); - - if ( bomb != null ) { - String cBombName = Text.stripColor( bomb.getName() ); - - if ( cBombName != null && - cBombName.equalsIgnoreCase( cleanedBombName ) ) { - - results = bomb; - } - } - - - } - } - - return results; - } - } 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 2f39f4dec..9cd28575f 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 @@ -1,12 +1,17 @@ package tech.mcprison.prison.bombs; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; +import java.util.TreeSet; import tech.mcprison.prison.file.FileIOData; public class MineBombsConfigData - implements FileIOData + implements FileIOData, + Comparable { /** *

If the format of this class, or any other variables and their @@ -17,6 +22,7 @@ public class MineBombsConfigData *

*/ public static final int MINE_BOMB_DATA_FORMAT_VERSION = 3; +// public static final int MINE_BOMB_DATA_FORMAT_VERSION = 4; private int dataFormatVersion = 0; @@ -37,10 +43,93 @@ public void setDataFormatVersion( int dataFormatVersion ) { this.dataFormatVersion = dataFormatVersion; } + protected boolean validateMineBombEffects( boolean showWarnings ) { + boolean results = false; + + Set keys = getBombs().keySet(); + for ( String key : keys ) { + MineBombData bomb = getBombs().get( key ); + + TreeSet sounds = new TreeSet<>( bomb.getSoundEffects() ); + bomb.getSoundEffects().clear(); + for ( MineBombEffectsData sound : sounds ) { + if ( bomb.addSoundEffects( sound, showWarnings ) && !results ) { + results = true; + } + } + + TreeSet visuals = new TreeSet<>( bomb.getVisualEffects() ); + bomb.getVisualEffects().clear(); + for ( MineBombEffectsData visual : visuals ) { + if ( bomb.addVisualEffects( visual, showWarnings ) && !results ) { + results = true; + } + } + + + } + + return results; + } + public Map getBombs() { return bombs; } public void setBombs( Map bombs ) { this.bombs = bombs; } + + + /** + * This compareTo function will check to see if the two + * MineBombsConfigData objects have the same number of + * bombs, and they that have the same bomb names. + * + * If the bomb names match, then it compares each bomb. + * + */ + @Override + public int compareTo(MineBombsConfigData o) { + int results = 0; + + if ( o == null ) { + results = -1; + } + + if ( results == 0 ) { + results = Integer.compare( getDataFormatVersion(), o.getDataFormatVersion() ); + + if ( results == 0 ) { + results = Integer.compare( getBombs().size(), o.getBombs().size() ); + + if ( results == 0 ) { + List keys = new ArrayList<>( getBombs().keySet() ); + List keysO = new ArrayList<>( o.getBombs().keySet() ); + + for ( int i = 0; i < keys.size(); i++ ) { + + String key = keys.get(i); + String keyO = keysO.get(i); + + results = key.compareTo(keyO); + + if ( results == 0 ) { + MineBombData mBomb = getBombs().get(key); + MineBombData mBombO = o.getBombs().get(keyO); + + mBomb.compareTo( mBombO ); + } + + if ( results != 0 ) { + break; + } + } + + } + + } + } + + return results; + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationBounce.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationBounce.java new file mode 100644 index 000000000..425f3f988 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationBounce.java @@ -0,0 +1,54 @@ +package tech.mcprison.prison.bombs.animations; + +import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.util.Location; + +public class BombAnimationBounce + extends BombAnimations { + + private double yOriginal = 0; + private double counter = 0; + + public BombAnimationBounce(MineBombData bomb, + Location location, + PrisonBlock sBombBlock, + ItemStack item, BombAnimationsTask task, + float entityYaw, float entityPitch) { + super(bomb, location, sBombBlock, item, task, entityYaw, entityPitch); + + this.yOriginal = getArmorStand().getLocation().getY(); + } + + @Override + public void stepAnimation() { + + double speed = getBomb().getAnimationSpeed() / 16d; + + counter += speed; + + if ( counter > 128d ) { + counter -= 128d; + } + + double bounce = 1.25 * Math.sin( counter ); + + Location loc = new Location( getOriginalLocation() ); + + // NOTICE!!! Have to subtract 1 from the original location so the armorstand is + // always TP'd to the same y value. Otherwise it will bounce when it + // hits the ground. This probably only affects spigot 1.8.x. + // This has something to do with the fact that the armorstand is being + // teleported. + loc.setY( loc.getY() - 1 ); + + loc.setY( yOriginal + bounce ); + + getArmorStand().teleport( loc ); + + +// getArmorStand().getLocation().setY( yOriginal + bounce ); + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationInfinity.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationInfinity.java new file mode 100644 index 000000000..4e042a71c --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationInfinity.java @@ -0,0 +1,38 @@ +package tech.mcprison.prison.bombs.animations; + +import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.internal.EulerAngle; +import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.util.Location; + +public class BombAnimationInfinity + extends BombAnimations { + + public BombAnimationInfinity( MineBombData bomb, + Location location, + PrisonBlock sBombBlock, ItemStack item, + BombAnimationsTask task, + float entityYaw, float entityPitch ) { + super( bomb, location, sBombBlock, item, task, entityYaw, entityPitch ); + + } + + + @Override + public void stepAnimation() + { + + double speed = getBomb().getAnimationSpeed() / 16d; + + setEulerAngleX( getEulerAngleX() + speed ); + setEulerAngleY( getEulerAngleY() + speed / 3); + setEulerAngleZ( getEulerAngleZ() + speed / 5 ); + + + EulerAngle arm = new EulerAngle( getEulerAngleX(), getEulerAngleY(), getEulerAngleZ() ); + + getArmorStand().setRightArmPose(arm); + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationNone.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationNone.java new file mode 100644 index 000000000..407b5f6f1 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationNone.java @@ -0,0 +1,49 @@ +package tech.mcprison.prison.bombs.animations; + +import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.util.Location; + +public class BombAnimationNone + extends BombAnimations { + + /** + * This constructor will generate an armor stand without holding an item. + * This is ideal for a holographic display that is not moving. + * + * @param bomb + * @param sBombBlock + * @param task + */ + public BombAnimationNone( MineBombData bomb, + Location location, + PrisonBlock sBombBlock, + BombAnimationsTask task ) { + super( bomb, location, sBombBlock, task ); + + } + + + public BombAnimationNone( MineBombData bomb, + Location location, + PrisonBlock sBombBlock, ItemStack item, + BombAnimationsTask task, + float entityYaw, float entityPitch ) { + super( bomb, location, sBombBlock, item, task, entityYaw, entityPitch ); + + } + + + /** + * Since this animation is "none", there is no movement to this one. + * + * This should be used for displaying the custom name. + */ + @Override + public void stepAnimation() + { + + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationOrbital.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationOrbital.java new file mode 100644 index 000000000..8dd5a5291 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationOrbital.java @@ -0,0 +1,132 @@ +package tech.mcprison.prison.bombs.animations; + +import tech.mcprison.prison.bombs.GeometricShapes; +import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.util.Location; +import tech.mcprison.prison.util.Vector; + +/* + * NOTE: The whole rotateAroundAxisY does not work. + * So for now, disable this option. + */ +public class BombAnimationOrbital extends BombAnimations { + + private double angle = 0.0; + private double radius = 1.0; + private double radiusDelta = 0; + private float spinValue = 0; + + private boolean alternateDirections = false; + + public BombAnimationOrbital(MineBombData bomb, Location location, + PrisonBlock sBombBlock, + ItemStack item, BombAnimationsTask task, + float entityYaw, float entityPitch) { + super(bomb, location, sBombBlock, item, task, entityYaw, entityPitch); + + this.angle = entityYaw; + + this.radius = bomb.getAnimationRadius(); + this.radiusDelta = bomb.getAnimationRadiusDelta(); + + this.alternateDirections = bomb.isAnimationAlternateDirections(); + + Vector vec = new Vector( + bomb.getAnimationOffset(), 0d, bomb.getAnimationOffset()); + getOriginalLocation().add( vec ); + + } + + @Override + public void stepAnimation() { + + if ( isAlternateDirections() ) { + + if ( getId() % 2 == 0 ) { + angle += getBomb().getAnimationSpeed(); + } + else { + angle -= getBomb().getAnimationSpeed(); + } + + } + else { + angle += getBomb().getAnimationSpeed(); + } + + if ( angle > 360 ) { + angle -= 360; + } + else if ( angle < -360 ) { + angle += 360; + } + + double radi = radius + + (radiusDelta == 0 ? 0 : + radiusDelta * Math.sin( angle / 2d )); + + + spinValue += getBomb().getAnimationSpinSpeed(); + if ( spinValue > 360 ) { + spinValue -= 360; + } + else if ( spinValue < -360 ) { + spinValue += 360; + } + + + + + Vector vector = GeometricShapes.getPointsOnCircleXZ( angle, radi ); + + // Location.add() creates a new instance of a Location and does not change + // the original value: + Location newLoc = getOriginalLocation().add(vector); + + // NOTICE!!! Have to subtract 1 from the original location so the armorstand is + // always TP'd to the same y value. Otherwise it will bounce when it + // hits the ground. This probably only affects spigot 1.8.x. + // This has something to do with the fact that the armorstand is being + // teleported. + newLoc.setY( newLoc.getY() - 1 ); + + // Spin the held item? + newLoc.setYaw( (float) spinValue ); +// newLoc.setDirection( spin ); + + getArmorStand().teleport( newLoc ); + + + } + + public double getAngle() { + return angle; + } + public void setAngle(double angle) { + this.angle = angle; + } + + public double getRadius() { + return radius; + } + public void setRadius(double radius) { + this.radius = radius; + } + + public double getRadiusDelta() { + return radiusDelta; + } + public void setRadiusDelta(double radiusDelta) { + this.radiusDelta = radiusDelta; + } + + public boolean isAlternateDirections() { + return alternateDirections; + } + public void setAlternateDirections(boolean alternateDirections) { + this.alternateDirections = alternateDirections; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimations.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimations.java new file mode 100644 index 000000000..c67ac8c4a --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimations.java @@ -0,0 +1,514 @@ +package tech.mcprison.prison.bombs.animations; + +import java.text.DecimalFormat; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.bombs.MineBombs; +import tech.mcprison.prison.internal.ArmorStand; +import tech.mcprison.prison.internal.EulerAngle; +import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.util.BluesSemanticVersionComparator; +import tech.mcprison.prison.util.Location; +import tech.mcprison.prison.util.Text; + +public abstract class BombAnimations { + + private int id; + + private BombAnimationsTask task; + + private MineBombData bomb; + private PrisonBlock sBlock; + private ItemStack item; + + private Location originalLocation; + + private String customName; + private boolean isDyanmicTag = false; + private String tagName; + +// long ageTicks = 0L; + long terminateOnZeroTicks = 0L; + + private ArmorStand armorStand; + + private double eulerAngleX = 1.0; + private double eulerAngleY = 0; + private double eulerAngleZ = 0; + + private double twoPI; + + private float entityYaw; + private float entityPitch; + + private DecimalFormat dFmt; + + + /* + * For none animations that will now hold an item. + * This is good for a non-animated animation that is used only as an + * holographic display of the name. + */ + public BombAnimations( MineBombData bomb, + Location location, + PrisonBlock sBombBlock, + BombAnimationsTask task ) { + this( bomb, location, sBombBlock, null, task, 0f, 0f ); + } + + public BombAnimations( MineBombData bomb, + Location location, + PrisonBlock sBombBlock, + ItemStack item, + BombAnimationsTask task, + float entityYaw, + float entityPitch ) { + super(); + + // Used for "canceling" and detonating the task: + this.task = task; + + setId( getTask().getAnimators().size() ); + + this.bomb = bomb; + this.sBlock = sBombBlock; + this.item = item; + +// Location location = +// getBomb().getPlacedBombLocation() != null ? +// getBomb().getPlacedBombLocation() : +// getsBlock().getLocation(); +// location.setY( location.getY() + 2.5 ); + + // NOTE: The direction the entity is facing is based upon yaw. + // When using org.bukkit.Location.setDirection() it's using a vector + // to set yaw and pitch so it's looking at that vector point. + // So... I guess that means an entity cannot turn their head? + // For entities, or at least armorStands, there is an Euler angle + // based getHeadPose() and setHeadPose() functions. + location.setYaw( entityYaw ); + + + // Not sure why 90 was being added. I suspect 0 is straight up? + location.setPitch( entityPitch + 90 ); + + this.originalLocation = location; + + + + +// this.ageTicks = 0; + this.terminateOnZeroTicks = getTaskLifeSpan(); + + this.isDyanmicTag = bomb.getNameTag() != null && + bomb.getNameTag().contains( "{countdown}" ); + this.tagName = ""; + + + this.entityYaw = entityYaw; + this.entityPitch = entityPitch; + + this.twoPI = Math.PI * 2; + + this.dFmt = Prison.get().getDecimalFormat( "0.0" ); + + initialize(); + } + + protected void cancel() { + task.cancel(); + } + + public void initialize() { + +// Location location = +// getBomb().getPlacedBombLocation() != null ? +// getBomb().getPlacedBombLocation() : +// getsBlock().getLocation(); +// +// location.setY( location.getY() + 2.5 ); +// +// setOriginalLocation( location ); +// + +// // NOTE: The direction the entity is facing is based upon yaw. +// // When using org.bukkit.Location.setDirection() it's using a vector +// // to set yaw and pitch so it's looking at that vector point. +// // So... I guess that means an entity cannot turn their head? +// // For entities, or at least armorStands, there is an Euler angle +// // based getHeadPose() and setHeadPose() functions. +// getOriginalLocation().setYaw( entityYaw ); +// +// +// // Not sure why 90 was being added. I suspect 0 is straight up? +// getOriginalLocation().setPitch( entityPitch + 90 ); +// +// + +// double startingAngle = ( 360d / entityYaw ) * twoPI; +// location.setDirection( startingAngle ); + + // eulerAngleX += startingAngle; + +// EulerAngle arm = new EulerAngle( +// eulerAngleX, +// eulerAngleY, +// eulerAngleZ ); + +// EulerAngle arm = new EulerAngle( +// eulerAngleX + startingAngle, +// eulerAngleY + startingAngle, +// eulerAngleZ + startingAngle ); + + + // Spawn an invisible armor stand: + // If item is null, then armorstand will not spawn with an item + // and no arms. + armorStand = getOriginalLocation().spawnArmorStand( + (getItem() == null ? null : getBomb().getItemType()), + getBomb().getAnimationArmorStandItemLocation() ); +// armorStand = getOriginalLocation().spawnArmorStand( +// null, +// (getId() == 0 ? getBomb().getName() : null) ); + + + +// armorStand = location.spawnArmorStand(); + + if ( armorStand != null ) { + +// Output.get().logInfo( "### init mine bomb 1: id: " + getId() + " " + +// armorStand.getLocation().toString() ); + + // Need to teleport the armor stand to the actual location where it + // landed or was thrown to, otherwise it will look like it's offset. + //armorStand.teleport( getOriginalLocation() ); + +// Output.get().logInfo( "### init mine bomb 2: id: " + getId() + " " + +// armorStand.getLocation().toString() ); + + // Sets visibility:false, arms:true, basePlate:false, canPickupItems:false, + // removeWhenFar:false, gravity:false, and itemInHand. + // armorStand.setupArmorStand( getBomb().getItemType() ); +// armorStand.setupArmorStand( getItem() ); + +// if ( getItem() != null ) { +// armorStand.setVisible( true ); +// +// armorStand.setArms( true ); +// +// armorStand.setItemInHand( getItem() ); +// } + + + + // Sets up the custom name on the armorstand and also configures the + // processing if it's a dynamic name: + armorStand.setCustomNameVisible( getId() == 0 && initializeCustomName() ); + + + armorStand.setNbtString( MineBombs.MINE_BOMBS_NBT_KEY, getBomb().getName() ); + +// armorStand.setNbtString( MineBombs.MINE_BOMBS_NBT_THROWER_UUID, +// playerUUID ); + + armorStand.setSmall( getBomb().isSmall() ); + + + if ( getItem() != null ) { + + EulerAngle arm = new EulerAngle( + eulerAngleX, + eulerAngleY, + eulerAngleZ ); + + armorStand.setArms( true ); + armorStand.setRightArmPose(arm); + } + +// ItemStack itemInHand = armorStand.getItemInHand(); +// +// int iihAmount = itemInHand.getAmount(); +// int iamount = getItem().getAmount(); +// +// int count = iihAmount + iamount; +// +// armorStand.setArms( true ); +// armorStand.setBasePlate( false ); +// armorStand.setCanPickupItems( false ); +// +// +// armorStand.setItemInHand( getItem() ); + +// armorStand.setRemoveWhenFarAway(false); + + if ( new BluesSemanticVersionComparator().compareMCVersionTo( "1.9.0" ) >= 0 ) { + + armorStand.setInvulnerable( true ); + + armorStand.setGlowing( getBomb().isGlowing() ); + + // setGravity is invalid for spigot 1.8.8: + armorStand.setGravity( getBomb().isGravity() ); + + armorStand.setInvulnerable( true ); + } + } + +// if ( Output.get().isDebug() ) { +// String msg = String.format( +// "### BombAnimation.initializeArmorStand : id: %s %s %s %s%s%s%s", +// Integer.toString(getId()), +// bomb.getAnimationPattern().name(), +// armorStand.getLocation().toWorldCoordinates(), +// +// (getArmorStand().isCustomNameVisible() ? " CustomName" : " -noName- "), +// (getArmorStand().hasArms() ? " hasArms" : " -noArms- " ), +// (getArmorStand().getItemInHand() != null ? +// " " + getArmorStand().getItemInHand().getName() : " -noItemInHand- " ), +// (getArmorStand().isVisible() ? " visible " : " notVisible ") +// ); +// +// Output.get().logInfo( msg ); +// } + } + + + public abstract void stepAnimation(); + + public void step() { + stepAnimation(); + + if ( eulerAngleX > twoPI ) { + eulerAngleX -= twoPI; + } + else if ( eulerAngleX < -twoPI ) { + eulerAngleX += twoPI; + } + if ( eulerAngleY > twoPI ) { + eulerAngleY -= twoPI; + } + else if ( eulerAngleY < -twoPI ) { + eulerAngleY += twoPI; + } + if ( eulerAngleZ > twoPI ) { + eulerAngleZ -= twoPI; + } + else if ( eulerAngleZ < -twoPI ) { + eulerAngleZ += twoPI; + } + + // Track the time that this has lived: + if ( --terminateOnZeroTicks == 0 || !armorStand.isValid() ) { + + armorStand.remove(); + + cancel(); + } + + if ( getId() == 0 ) { + + updateCustomName(); + } + + } + + + /** + *

This will calculate how long the placed item needs to + * exist before removal, and this task will remove itself. + * While this item is placed, this task will run every 2 + * ticks and will spin the item in 3d space. + *

+ * + *

Removal is based upon the fuseDelayTicks which will take it to + * the explosion, then scanning the final effects to find how long + * the last one will be submitted for. Then add 15 ticks. + *

+ * + *

At this time, not 100% sure if this item or armor stand + * will be used to "place" the effects. Probably not. If it's not + * needed, then this can be removed when the explosions start. + *

+ * + * @return + */ + protected long getTaskLifeSpan() + { + int removeInTicks = bomb.getFuseDelayTicks() + bomb.getItemRemovalDelayTicks(); + return removeInTicks; + } + + + protected boolean initializeCustomName() { + boolean results = false; + + String tName = null; + + if ( getBomb().getNameTag() == null || + getBomb().getNameTag().trim().isEmpty() ) { + + tName = getBomb().getName(); + } + else { + + tName = getBomb().getNameTag(); + if ( tName.contains( "{name}" ) ) { + tName = tName.replace( "{name}", getBomb().getName() ); + } + } + + if ( tName != null ) { + + tName = Text.translateAmpColorCodes( tName ); + + setTagName( tName ); + setCustomName( tName ); + armorStand.setCustomName( tName ); + + updateCustomName(); + + results = true; + } + + return results; + } + + protected void updateCustomName() + { + if ( isDyanmicTag ) { + + double countdown = (terminateOnZeroTicks / 20.0d); + String cName = getTagName().replace( "{countdown}", dFmt.format( countdown) ); + + setCustomName( cName ); + + armorStand.setCustomName( cName ); + +// setTagName( tagName ); +// armorStand.setCustomName( tagName ); + } + } + + public int getId() { + return id; + } + public void setId(int id) { + this.id = id; + } + + public BombAnimationsTask getTask() { + return task; + } + public void setTask(BombAnimationsTask task) { + this.task = task; + } + + public MineBombData getBomb() { + return bomb; + } + public void setBomb(MineBombData bomb) { + this.bomb = bomb; + } + + public PrisonBlock getsBlock() { + return sBlock; + } + public void setsBlock(PrisonBlock sBlock) { + this.sBlock = sBlock; + } + + public ItemStack getItem() { + return item; + } + public void setItem(ItemStack item) { + this.item = item; + } + + public Location getOriginalLocation() { + return originalLocation; + } + public void setOriginalLocation(Location originalLocation) { + this.originalLocation = originalLocation; + } + + public boolean isDyanmicTag() { + return isDyanmicTag; + } + public void setDyanmicTag(boolean isDyanmicTag) { + this.isDyanmicTag = isDyanmicTag; + } + + public String getCustomName() { + return customName; + } + public void setCustomName(String customName) { + this.customName = customName; + } + + public String getTagName() { + return tagName; + } + public void setTagName(String tagName) { + this.tagName = tagName; + } + + public long getTerminateOnZeroTicks() { + return terminateOnZeroTicks; + } + public void setTerminateOnZeroTicks(long terminateOnZeroTicks) { + this.terminateOnZeroTicks = terminateOnZeroTicks; + } + + public ArmorStand getArmorStand() { + return armorStand; + } + public void setArmorStand(ArmorStand armorStand) { + this.armorStand = armorStand; + } + + public double getEulerAngleX() { + return eulerAngleX; + } + public void setEulerAngleX(double eulerAngleX) { + this.eulerAngleX = eulerAngleX; + } + + public double getEulerAngleY() { + return eulerAngleY; + } + public void setEulerAngleY(double eulerAngleY) { + this.eulerAngleY = eulerAngleY; + } + + public double getEulerAngleZ() { + return eulerAngleZ; + } + public void setEulerAngleZ(double eulerAngleZ) { + this.eulerAngleZ = eulerAngleZ; + } + + public double getTwoPI() { + return twoPI; + } + public void setTwoPI(double twoPI) { + this.twoPI = twoPI; + } + + public float getEntityYaw() { + return entityYaw; + } + public void setEntityYaw(float entityYaw) { + this.entityYaw = entityYaw; + } + + public float getEntityPitch() { + return entityPitch; + } + public void setEntityPitch(float entityPitch) { + this.entityPitch = entityPitch; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationsTask.java b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationsTask.java new file mode 100644 index 000000000..c0980e13b --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/bombs/animations/BombAnimationsTask.java @@ -0,0 +1,287 @@ +package tech.mcprison.prison.bombs.animations; + +import java.util.ArrayList; +import java.util.List; + +import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.bombs.MineBombDetonateTask; +import tech.mcprison.prison.bombs.MineBombs.AnimationPattern; +import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.tasks.PrisonRunnable; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; +import tech.mcprison.prison.util.Location; + +public class BombAnimationsTask + implements PrisonRunnable { + + private int taskId; + + private List animators; + + private MineBombDetonateTask detonateBomb; + + private boolean detonated = false; + private Object detonationLock; + + public BombAnimationsTask() { + super(); + + this.detonationLock = new Object(); + + this.animators = new ArrayList<>(); + } + + + public void animatorFactory( + // AnimationPattern animation, + MineBombData bomb, PrisonBlock pBlock, + ItemStack sItem, MineBombDetonateTask detonateBomb ) { + + this.detonateBomb = detonateBomb; + + ItemStack item = new ItemStack( sItem ); + + AnimationPattern animation = bomb.getAnimationPattern(); + + + Location location = + bomb.getPlacedBombLocation() != null ? + bomb.getPlacedBombLocation() : + pBlock.getLocation(); + + // The current y adjustment is +2.5 blocks. Still using this so + // existing bomb configs are not messed up. + location.setY( Math.floor( location.getY() + 2 ) ); + + + if ( Output.get().isDebug() ) { + String msg = String.format( + "### BombAnimationsTask.animmatorFactory : AnimationPattern: %s ", + animation.name() + + ); + Output.get().logInfo( msg ); + } + + + switch ( animation ) { + + case bounce: + { + // Add BombAnimationNone for a stationary name: + BombAnimationNone baHolo = new BombAnimationNone( bomb, location, pBlock, this ); + getAnimators().add( baHolo ); + + float yaw = 0; + float pitch = 0; + + BombAnimationBounce ba = new BombAnimationBounce( bomb, + location, + pBlock, item, this, + yaw, pitch ); + + getAnimators().add( ba ); + submitTask(); + } + + break; + + case orbital: + { + // Add BombAnimationNone for a stationary name: + BombAnimationNone baHolo = new BombAnimationNone( bomb, location, pBlock, this ); + getAnimators().add( baHolo ); + + float yaw = 0; + float pitch = 0; + + BombAnimationOrbital ba = new BombAnimationOrbital( bomb, + location, + pBlock, item, this, + yaw, pitch ); + + getAnimators().add( ba ); + submitTask(); + } + + break; + + case orbitalEight: + { + // Add BombAnimationNone for a stationary name: + BombAnimationNone baHolo = new BombAnimationNone( bomb, location, pBlock, this ); + getAnimators().add( baHolo ); + + float yaw = 0; + float pitch = 0; + float yawStep = 360f / 8f; + + for ( int i = 0; i < 8; i++ ) { + BombAnimationOrbital ba = new BombAnimationOrbital( bomb, + location, + pBlock, item, this, + yaw, pitch ); + + getAnimators().add( ba ); + + yaw += yawStep; + } + + submitTask(); + } + break; + + case starburst: + { + // Add BombAnimationNone for a stationary name: + BombAnimationNone baHolo = new BombAnimationNone( bomb, location, pBlock, this ); + getAnimators().add( baHolo ); + + float yaw = 0; + float pitch = 0; + float yawStep = 360f / 16f; + + for ( int i = 0; i < 16; i++ ) { + BombAnimationOrbital ba = new BombAnimationOrbital( bomb, + location, + pBlock, item, this, + yaw, pitch ); + + ba.setAlternateDirections( true ); + ba.setRadiusDelta( 2.0 ); + + getAnimators().add( ba ); + + yaw += yawStep; + } + + submitTask(); + } + break; + + case infinity: + { + float yaw = 0; + float pitch = 0; + + BombAnimationInfinity ba = new BombAnimationInfinity( bomb, + location, + pBlock, item, this, + yaw, pitch ); + + getAnimators().add( ba ); + submitTask(); + } + + break; + + case infinityEight: + { + // Add BombAnimationNone for a stationary name: + BombAnimationNone baHolo = new BombAnimationNone( bomb, location, pBlock, this ); + getAnimators().add( baHolo ); + + float yaw = 0; + float pitch = 0; + float yawStep = 360f / 8f; + + for ( int i = 0; i < 8; i++ ) { + BombAnimationInfinity ba = new BombAnimationInfinity( bomb, location, + pBlock, item, this, + yaw, pitch ); + + getAnimators().add( ba ); + + yaw += yawStep; + } + + submitTask(); + } + + break; + + + case none: + { + float yaw = 0; + float pitch = 0; + + BombAnimationNone ba = new BombAnimationNone( bomb, location, + pBlock, item, this, + yaw, pitch ); + + getAnimators().add( ba ); + submitTask(); + } + + default: + // Do nothing... do not submit task to run. + break; + } + + + detonateBomb(); + } + + private void submitTask() { + + setTaskId( PrisonTaskSubmitter.runTaskTimer( this, 0L, 1L ) ); + + } + + protected void cancel() { + PrisonTaskSubmitter.cancelTask( getTaskId() ); + } + + private void detonateBomb() { + + // Need to use a multi-layered synchronized lock since there may be + // many animations ending at the same time, and we only want one to + // trigger the detonation. + if ( !detonated ) { + synchronized ( detonationLock ) { + if ( !detonated ) { + detonated = true; + + // Detonate the bomb using the callback: + detonateBomb.runDetonation(); + } + } + } + } + + + /** + * The animators will override this function. + */ + protected void initialize() { + } + + + @Override + public void run() { + + for ( BombAnimations animator : getAnimators() ) { + animator.step(); + } + + } + + + public int getTaskId() { + return taskId; + } + public void setTaskId(int taskId) { + this.taskId = taskId; + } + + public List getAnimators() { + return animators; + } + public void setAnimators(List animators) { + this.animators = animators; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/CoreCacheFiles.java b/prison-core/src/main/java/tech/mcprison/prison/cache/CoreCacheFiles.java index c8fd65cb1..e75b6f6ec 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/CoreCacheFiles.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/CoreCacheFiles.java @@ -1,13 +1,11 @@ package tech.mcprison.prison.cache; import java.io.File; -import java.io.FileFilter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.TreeMap; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -15,6 +13,7 @@ import com.google.gson.JsonSyntaxException; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.file.JsonFileIO; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.output.Output; @@ -24,13 +23,13 @@ public abstract class CoreCacheFiles { public static final String FILE_PREFIX_BACKUP = ".backup_"; public static final String FILE_SUFFIX_BACKUP = ".bu"; public static final String FILE_SUFFIX_TEMP = ".temp"; + public static final String FILE_SUFFIX_TXT = ".txt"; public static final String FILE_TIMESTAMP_FORMAT = "_yyyy-MM-dd_HH-mm-ss"; private final String cachePath; private File cacheDirectory = null; private Gson gson = null; - private TreeMap playerFiles; public CoreCacheFiles( String cachePath ) { @@ -84,7 +83,7 @@ protected File createTempFile(File file) { *

* */ - protected CoreCacheData fromJsonFile(File inputFile, Class classOfT ) { + protected CoreCacheData fromJsonFile(File inputFile, Class classOfT ) { CoreCacheData results = null; if ( inputFile.exists() ) { @@ -151,24 +150,17 @@ protected CoreCacheData fromJsonFile(File inputFile, Class classOfT ) { CoreCacheData results = null; -// // This is the "target" file name for the player, based upon their -// // current name. The saved cache file may not be named exactly the same, -// // and if it's not, then their existing cache file will be renamed -// // within the function getCachedFileMatch() - String playerFileName = getPlayerFileName( player ); + File playerCacheFile = JsonFileIO.fileCache(player); - File playerFile = getCachedFileMatch( playerFileName ); - - - if ( playerFile.exists() ) { + if ( playerCacheFile.exists() ) { - results = fromJsonFile( playerFile, classOfT ); + results = fromJsonFile( playerCacheFile, classOfT ); } // New player and file does not exist so create it. if ( results == null ) { - results = new PlayerCachePlayerData( player, playerFile ); + results = new PlayerCachePlayerData( player, playerCacheFile ); // Then save it: toJsonFile( results ); @@ -215,8 +207,9 @@ public void toJsonFile(CoreCacheData cacheData) { File playerFile = cacheData.getPlayerFile(); File outTemp = createTempFile( playerFile ); - if ( !getPlayerFiles().containsKey( playerFile.getName() )) { - getPlayerFiles().put( playerFile.getName(), playerFile ); + if ( outTemp.getParentFile().mkdirs() ) { + Output.get().logInfo( "CoreCacheFiles.toJsonFile(): Created missing directories: %s", + outTemp.getParentFile().getAbsolutePath() ); } boolean success = false; @@ -229,85 +222,57 @@ public void toJsonFile(CoreCacheData cacheData) { success = true; } catch ( JsonIOException | IOException e ) { - e.printStackTrace(); + + String msg = String.format( + "&3CoreCacheFiles.toJsonFile: &6Failure to write to temp file. &3This is probably an " + + "issue with the underlying OS and file system. Did you run out of file storage space? " + + "Please confirm. Tempfile: &6%s&3 OriginalFile: %s Error message: [&6%s&3]", + outTemp.getAbsolutePath(), + playerFile.getAbsolutePath(), + e.getMessage() + ); + + Output.get().logInfo( msg ); } - // If there is a significant change in file size, or the new file is smaller than the - // old, then rename it to a backup and keep it. If it is smaller, then something went wrong - // because player cache data should always increase, with the only exception being - // the player cache. - if ( playerFile.exists() ) { - long pfSize = playerFile.length(); - long tmpSize = outTemp.length(); + if ( success ) { - if ( tmpSize < pfSize ) { - - renamePlayerFileToBU( playerFile ); + // If there is a significant change in file size, or the new file is smaller than the + // old, then rename it to a backup and keep it. If it is smaller, then something went wrong + // because player cache data should always increase, with the only exception being + // the player cache. + if ( playerFile.exists() ) { + long pfSize = playerFile.length(); + long tmpSize = outTemp.length(); + + if ( tmpSize < pfSize ) { + + renamePlayerFileToBU( playerFile ); + } } - } - - if ( success && ( !playerFile.exists() || playerFile.delete()) ) { - outTemp.renameTo( playerFile ); - } - else { - boolean removed = false; - if ( outTemp.exists() ) { - removed = outTemp.delete(); + if ( success && ( !playerFile.exists() || playerFile.delete()) ) { + outTemp.renameTo( playerFile ); + } + else { + + boolean removed = false; + if ( outTemp.exists() ) { + removed = outTemp.delete(); + } + + String message = String.format( + "Unable to rename PlayerCache temp file. It was %sremoved: %s", + (removed ? "" : "not "), outTemp.getAbsolutePath() ); + + Output.get().logWarn( message ); } - - String message = String.format( - "Unable to rename PlayerCache temp file. It was %sremoved: %s", - (removed ? "" : "not "), outTemp.getAbsolutePath() ); - - Output.get().logWarn( message ); - } - } - } - - /** - *

Constructs a File object for a specific player. - *

- * - * @param playerFileName - * @return - */ - protected File getPlayerFile(String playerFileName) { - return new File( getPlayerFilePath(), playerFileName ); - } - - protected TreeMap getPlayerFiles() { - // load the player's files: - if ( playerFiles == null ) { - - playerFiles = new TreeMap<>(); - - FileFilter fileFilter = (file) -> { - - String fname = file.getName(); - boolean isTemp = fname.startsWith( FILE_PREFIX_BACKUP ) || - fname.endsWith( FILE_SUFFIX_BACKUP ) || - fname.endsWith( FILE_SUFFIX_TEMP ); - - return !file.isDirectory() && !isTemp && - fname.endsWith( FILE_SUFFIX_JSON ); - }; - - - File[] files = getPlayerFilePath().listFiles( fileFilter ); - for ( File f : files ) - { - String fileNamePrefix = getFileNamePrefix( f.getName() ); - getPlayerFiles().put( fileNamePrefix, f ); } } - - return playerFiles; } - - + /** *

This function will take the project's data folder and construct the the path * to the directory, if it does not exist, to where the player cache files are stored. @@ -325,111 +290,4 @@ public File getPlayerFilePath() { return cacheDirectory; } - /** - *

This function returns the file name which is constructed by - * using the player's UUID and their name. The player's name is not - * used in the selection of a player's file, only the UUID prefix. - *

- * - *

The UUID prefix is based upon the HEX representation of the - * the UUID, and includes the first 13 characters which includes one - * hyphen. Since the minecraft UUID is based upon random numbers - * (type 4 UUID), then odds are great that file name prefixes will - * be unique, but they don't have to be. - *

- * - *

Its a high importance that file names can be found based upon - * Player information, hence the UUID prefix. Plus it's very important - * to be able to have the files human readable so admins can find - * specific player files if they need to; hence the player name suffix. - *

- * - * @param player - * @return - */ - private String getPlayerFileName( Player player ) { - String UUIDString = player.getUUID().toString(); - String uuidFragment = getFileNamePrefix( UUIDString ); - - return uuidFragment + "_" + player.getName() + FILE_SUFFIX_JSON; - } - - /** - *

This function returns the first 13 characters of the supplied - * file name, or UUID String. The hyphen is around the 12 or 13th position, - * so it may or may not include it. - *

- * - * @param playerFileName - * @return - */ - String getFileNamePrefix( String UUIDString ) { - return UUIDString.substring( 0, 14 ); - } - - - - /** - *

Potentially there could be more than one result, but considering if a player - * changes their name, then it should only return only one entry. The reason for - * this, is that the file name should be based upon the player's UUID, which is the - * first 13 characters of the file, and the name itself, which follows, should - * never be part of the "key". - *

- * - * @param playerFile - * @param playerFileName - * @return - */ - private File getCachedFileMatch( String playerFileName ) - { - File results = null; - - String fileNamePrefix = getFileNamePrefix( playerFileName ); - - results = getPlayerFiles().get( fileNamePrefix ); - - if ( results == null ) { - - // This is the "target" file name for the player, based upon their - // current name. The saved cache file may not be named exactly the same, - // and if it's not, then their existing cache file needs to be - // renamed. - results = getPlayerFile( playerFileName ); - - // NOTE: because the file was NOT found in the directory, then we can assume - // this is a new player therefore we won't have an issue with the player's - // name changing. - getPlayerFiles().put( fileNamePrefix, results ); - } - else if ( !playerFileName.equalsIgnoreCase( results.getName() )) { - - // File name changed!!! Need to rename the file in the file system, and - // update what is in the playerFiles map!! - - File newFile = getPlayerFile( playerFileName ); - - if ( results.exists() ) { - // rename what's on the file system: - results.renameTo( newFile ); - } - - // Replace what's in the map: - getPlayerFiles().put( fileNamePrefix, newFile ); - - results = newFile; - } - -// NavigableMap files = getPlayerFiles().tailMap( fileNamePrefix, true ); -// Set keys = files.keySet(); -// for ( String key : keys ) { -// if ( !key.startsWith( fileNamePrefix ) ) { -// break; -// } -// -// results.add( files.get( key ) ); -// } - - return results; - } } 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 0875b92ad..8d07958c3 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 @@ -6,6 +6,7 @@ import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; +import java.util.TreeSet; import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.Player; @@ -125,43 +126,52 @@ private void onDisableInternal() { PrisonTaskSubmitter.cancelTask( saveAllTask.getTaskId() ); // Shutdown the timerTasks - PrisonTaskSubmitter.cancelTask( checkTimersTask.getTaskId() ); + if ( checkTimersTask != null ) { + + PrisonTaskSubmitter.cancelTask( checkTimersTask.getTaskId() ); + } // save all dirty cache items and purge cache: if ( getPlayers().size() > 0 ) { - Set keys = getPlayers().keySet(); - + Set keys = null; + synchronized ( getPlayers() ) { + keys = new TreeSet<>( getPlayers().keySet() ); + } + + + for ( String key : keys ) { + // Remove the player from the cache and get the playerData: + PlayerCachePlayerData playerData = null; + + synchronized ( getPlayers() ) { + playerData = getPlayers().remove( key ); + } - for ( String key : keys ) { - // Remove the player from the cache and get the playerData: - PlayerCachePlayerData playerData = getPlayers().remove( key ); + if ( playerData != null ) { - if ( playerData != null ) { - - // Note: Since we are logging online time, then all players that are - // in the cache are considered constantly dirty and needs to be - // saved. - - // Since the disable function has been called, we can only assume the - // server is shutting down. We need to save dirty player caches, but - // they must be done in-line so the shutdown process will wait for all - // players to be saved. - - getCacheFiles().toJsonFile( playerData ); + // Note: Since we are logging online time, then all players that are + // in the cache are considered constantly dirty and needs to be + // saved. + + // Since the disable function has been called, we can only assume the + // server is shutting down. We need to save dirty player caches, but + // they must be done in-line so the shutdown process will wait for all + // players to be saved. + + getCacheFiles().toJsonFile( playerData ); + + if ( playerData.getTask() != null ) { - if ( playerData.getTask() != null ) { + synchronized( getTasks() ) { - synchronized( getTasks() ) { - - getTasks().remove( playerData.getTask() ); - } - - PrisonTaskSubmitter.cancelTask( playerData.getTask().getTaskId() ); + getTasks().remove( playerData.getTask() ); } + + PrisonTaskSubmitter.cancelTask( playerData.getTask().getTaskId() ); } } } @@ -259,6 +269,24 @@ public PlayerCachePlayerData getOnlinePlayer( Player player ) { return playerData; } + /** + *

This function will only return a player cache object if it's + * already in the player cache. If the player is not in the cache, + * then this will return a null, and the player will not be loaded. + *

+ * + *

Any player that is not in the cache will not be loaded because of + * the usage of this function. + *

+ * + * @param player + * @return + */ + public PlayerCachePlayerData getOnlinePlayerCached( Player player ) { + PlayerCachePlayerData playerData = getPlayer( player, false ); + + return playerData; + } private PlayerCachePlayerData getPlayer( Player player ) { return getPlayer( player, true ); @@ -305,8 +333,6 @@ else if ( loadIfNotInCache ) { // Save it to the cache: addPlayerData( playerData ); -// runLoadPlayerNow( player ); -// submitAsyncLoadPlayer( player ); } if ( playerData != null ) { @@ -337,29 +363,6 @@ protected void submitAsyncLoadPlayer( Player player ) { } -// /** -// *

This loads the player cache object inline. It does not run it as a -// * task in another thread. -// *

-// * -// *

This is not used anywhere. -// *

-// * -// * @param player -// */ -// protected void runLoadPlayerNow( Player player ) { -// -// if ( player != null ) { -// -// PlayerCacheLoadPlayerTask task = new PlayerCacheLoadPlayerTask( player ); -// -// task.run(); -//// // Submit task to run right away: -//// int taskId = PrisonTaskSubmitter.runTaskLaterAsync( task, 0 ); -//// task.setTaskId( taskId ); -// } -// } - protected void submitAsyncUnloadPlayer( Player player ) { @@ -399,17 +402,7 @@ public PlayerCacheRunnable submitCacheRefresh() { 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, repeatTimeTicks ); - task.setTaskId( taskId ); + PlayerCacheRunnable task = PlayerCacheCheckTimersTask.submitPlayerStatsCacheUpdater(); return task; } @@ -425,20 +418,11 @@ public void addPlayerBlocks( Player player, String mine, PrisonBlockStatusData b } } -// public void addPlayerBlocks( Player player, String mine, PrisonBlock block, int quantity ) { -// addPlayerBlocks( player, mine, block.getBlockName(), quantity ); -// } + + private void addPlayerBlocks( Player player, String mine, String blockName, int quantity ) { PlayerCachePlayerData playerData = getPlayer( player ); -// Output.get().logInfo( "### addPlayerBlock: mine= " + (mine == null ? "null" : mine) + -// " block= " + (block == null ? "null" : block.getBlockName()) + " qty= " + quantity + " playerData= " + -// (playerData == null ? "null" : playerData.toString() )); - -// if ( playerData != null && playerData.getBlocksTotal() % 20 == 0 ) { -// Output.get().logInfo( "#### PlayerCache: " + playerData.toString() ); -// } - playerData.addBlock( mine, blockName, quantity ); if ( player.isMinecraftStatisticsEnabled() ) { @@ -556,12 +540,10 @@ public void setStats( PlayerCacheStats stats ) { this.stats = stats; } - protected void log( String message ) { Output.get().logInfo( message ); } - public long getWriteDelay() { return writeDelay; @@ -579,5 +561,4 @@ public Map getTasks() { return tasks; } - } diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java index d9dac7c3f..b4a412a8a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheCheckTimersTask.java @@ -3,6 +3,15 @@ import java.util.ConcurrentModificationException; import java.util.HashSet; import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.modules.Module; +import tech.mcprison.prison.modules.ModuleElementType; +import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; /** *

This periodically ran task will go through all cached players and update @@ -47,6 +56,40 @@ public PlayerCacheCheckTimersTask() { this.processedKeys = new HashSet<>(); } + /** + * This will submit this task to run at regular intervals only if the rank + * module is enabled. + * + * If ranks are not enabled, then this task will not be started since there will be + * no reason to use the player cache. + * + * @return + */ + public static PlayerCacheRunnable submitPlayerStatsCacheUpdater() { + + PlayerCacheCheckTimersTask task = null; + + Module ranksModule = Prison.get().getModuleManager().getModule( + ModuleElementType.RANK.name() ); + + if ( ranksModule != null && ranksModule.isEnabled() ) { + + task = new PlayerCacheCheckTimersTask(); + + int repeatTimeTicks = Prison.get().getPlatform() + .getConfigInt( PlayerCache.PLAYER_CACHE_UPDATE_PLAYER_STATS_CONFIG_NAME, + PlayerCache.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, repeatTimeTicks ); + task.setTaskId( taskId ); + } + + return task; + } + @Override public void run() { @@ -58,14 +101,26 @@ public void run() processCache(); } + + /** + * Only allow the cache to be processed if ranks is enabled. + */ private void processCache() { PlayerCache pCache = PlayerCache.getInstance(); - if ( pCache.getPlayers() != null && pCache.getPlayers().keySet().size() > 0 ) { + Module ranksModule = Prison.get().getModuleManager().getModule( + ModuleElementType.RANK.name() ); + + if ( ranksModule != null && ranksModule.isEnabled() && + pCache.getPlayers() != null && pCache.getPlayers().keySet().size() > 0 ) { try { - Set keys = pCache.getPlayers().keySet(); + Set keys = null; + + synchronized ( pCache.getPlayers() ) { + keys = new TreeSet<>( pCache.getPlayers().keySet() ); + } for ( String key : keys ) { @@ -84,11 +139,32 @@ private void processCache() { if ( playerData != null ) { + playerData.checkTimers(); // By adding a zero earnings, this will force the earnings "cache" to // progress, even if the player stopped mining. playerData.addEarnings( 0, null ); + + RankPlayer rPlayer = null; + + Player player = playerData.getPlayer(); + + if ( player != null ) { + rPlayer = player.getRankPlayer(); + } + else { + UUID uuid = UUID.fromString( key ); + + + rPlayer = Prison.get().getPlatform() + .getRankPlayer( uuid, + playerData != null ? playerData.getPlayerName() : "" ); + } + + if ( rPlayer != null ) { + rPlayer.updateTotalLastValues(playerData); + } } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheEvents.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheEvents.java index 127f9e2f4..e84977e94 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheEvents.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheEvents.java @@ -50,21 +50,23 @@ public PlayerCacheEvents() { @Subscribe public void onPlayerJoin(PlayerJoinEvent event) { - Player player = event.getPlayer(); - PlayerCache.getInstance().submitAsyncLoadPlayer( player ); + Player player = event.getPlayer(); + + + PlayerCache.getInstance().submitAsyncLoadPlayer( player ); } @Subscribe public void onPlayerQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); - PlayerCache.getInstance().submitAsyncUnloadPlayer( player ); + PlayerCache.getInstance().submitAsyncUnloadPlayer( player ); } @Subscribe public void onPlayerKicked(PlayerKickEvent event) { - Player player = event.getPlayer(); - PlayerCache.getInstance().submitAsyncUnloadPlayer( player ); + Player player = event.getPlayer(); + PlayerCache.getInstance().submitAsyncUnloadPlayer( player ); } } 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 917540f79..cae993369 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 @@ -66,7 +66,11 @@ public void run() Map syncMap = pCache.getPlayers(); - Set keys = new TreeSet<>( syncMap.keySet() ); + Set keys = null; + + synchronized ( syncMap ) { + keys = new TreeSet<>( syncMap.keySet() ); + } for ( String key : keys ) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheUnloadPlayerTask.java b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheUnloadPlayerTask.java index 79b948bb6..c7b192c03 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheUnloadPlayerTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/cache/PlayerCacheUnloadPlayerTask.java @@ -1,5 +1,11 @@ package tech.mcprison.prison.cache; +import java.util.UUID; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.ranks.data.RankPlayer; + public class PlayerCacheUnloadPlayerTask extends PlayerCacheTask { @@ -15,6 +21,7 @@ public void run() { // Remove from the player cache: PlayerCachePlayerData removed = null; + synchronized ( pCache.getPlayers() ) { @@ -23,6 +30,24 @@ public void run() { if ( removed != null ) { + UUID uuid = UUID.fromString( removed.getPlayerUuid() ); + + RankPlayer rPlayer = null; + + Player player = getPlayerData().getPlayer(); + if ( player != null ) { + rPlayer = player.getRankPlayer(); + } + else { + rPlayer = Prison.get().getPlatform() + .getRankPlayer( uuid, + removed != null ? removed.getPlayerName() : "" ); + + } + if ( rPlayer != null ) { + rPlayer.updateTotalLastValues( removed ); + } + pCache.getCacheFiles().toJsonFile( removed ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/chat/FancyMessage.java b/prison-core/src/main/java/tech/mcprison/prison/chat/FancyMessage.java index 9003b9c00..afdd006d8 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/chat/FancyMessage.java +++ b/prison-core/src/main/java/tech/mcprison/prison/chat/FancyMessage.java @@ -75,17 +75,17 @@ public FancyMessage(final FancyMessage... msgs) { } public FancyMessage(final List msgs) { - messageParts = new ArrayList<>(); - for(FancyMessage msg : msgs) { - messageParts.addAll(msg.messageParts); - } - jsonString = null; - dirty = false; + messageParts = new ArrayList<>(); + for(FancyMessage msg : msgs) { + messageParts.addAll(msg.messageParts); + } + jsonString = null; + dirty = false; } public void addFancy(FancyMessage fancyMessage) { - messageParts.addAll( fancyMessage.messageParts ); - dirty = true; + messageParts.addAll( fancyMessage.messageParts ); + dirty = true; } /** diff --git a/prison-core/src/main/java/tech/mcprison/prison/chat/MessagePart.java b/prison-core/src/main/java/tech/mcprison/prison/chat/MessagePart.java index 4d960ff7d..4e3140081 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/chat/MessagePart.java +++ b/prison-core/src/main/java/tech/mcprison/prison/chat/MessagePart.java @@ -97,7 +97,9 @@ boolean hasText() { return text != null; } - @Override @SuppressWarnings("unchecked") public MessagePart clone() + @Override + @SuppressWarnings("unchecked") + public MessagePart clone() throws CloneNotSupportedException { MessagePart obj = (MessagePart) super.clone(); obj.styles = (ArrayList) styles.clone(); diff --git a/prison-core/src/main/java/tech/mcprison/prison/chat/TextualComponent.java b/prison-core/src/main/java/tech/mcprison/prison/chat/TextualComponent.java index ebb75522f..6bccf7c0c 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/chat/TextualComponent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/chat/TextualComponent.java @@ -115,7 +115,8 @@ public static TextualComponent objectiveScore(String scoreboardObjective) { * player, or {@code null} if an error occurs during JSON serialization. */ public static TextualComponent objectiveScore(String playerName, String scoreboardObjective) { - throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE OVERLOADS documentation accordingly + throwUnsupportedSnapshot(); // Remove this line when the feature is released to + // non-snapshot versions, in addition to updating ALL THE OVERLOADS documentation accordingly return new ComplexTextTypeComponent("score", ImmutableMap.builder().put("name", playerName) @@ -134,12 +135,14 @@ public static TextualComponent objectiveScore(String playerName, String scoreboa * @return The text component representing the name of the entities captured by the selector. */ public static TextualComponent selector(String selector) { - throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE OVERLOADS documentation accordingly + throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot + // versions, in addition to updating ALL THE OVERLOADS documentation accordingly return new ArbitraryTextTypeComponent("selector", selector); } - @Override public String toString() { + @Override + public String toString() { return getReadableString(); } @@ -157,7 +160,8 @@ public static TextualComponent selector(String selector) { * Clones a textual component instance. The returned object should not reference this textual * component instance, but should maintain the same key and value. */ - @Override public abstract TextualComponent clone() throws CloneNotSupportedException; + @Override + public abstract TextualComponent clone() throws CloneNotSupportedException; /** * Writes the text data represented by this textual component to the specified JSON writer object. @@ -207,23 +211,27 @@ public void setValue(String value) { _value = value; } - @Override public TextualComponent clone() throws CloneNotSupportedException { + @Override + public TextualComponent clone() throws CloneNotSupportedException { // Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone return new ArbitraryTextTypeComponent(getKey(), getValue()); } - @Override public void writeJson(JsonWriter writer) throws IOException { + @Override + public void writeJson(JsonWriter writer) throws IOException { writer.name(getKey()).value(getValue()); } - @SuppressWarnings({ "serial", "unused" }) public Map serialize() { + @SuppressWarnings("unused") + public Map serialize() { return new HashMap() {{ put("key", getKey()); put("value", getValue()); }}; } - @Override public String getReadableString() { + @Override + public String getReadableString() { return getValue(); } } @@ -257,7 +265,8 @@ public static ComplexTextTypeComponent deserialize(Map map) { return new ComplexTextTypeComponent(key, value); } - @Override public String getKey() { + @Override + public String getKey() { return _key; } @@ -276,12 +285,14 @@ public void setValue(Map value) { _value = value; } - @Override public TextualComponent clone() throws CloneNotSupportedException { + @Override + public TextualComponent clone() throws CloneNotSupportedException { // Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone return new ComplexTextTypeComponent(getKey(), getValue()); } - @Override public void writeJson(JsonWriter writer) throws IOException { + @Override + public void writeJson(JsonWriter writer) throws IOException { writer.name(getKey()); writer.beginObject(); for (Map.Entry jsonPair : _value.entrySet()) { @@ -290,7 +301,8 @@ public void setValue(Map value) { writer.endObject(); } - @SuppressWarnings({ "serial", "unused" }) public Map serialize() { + @SuppressWarnings("unused") + public Map serialize() { return new HashMap() {{ put("key", getKey()); for (Entry valEntry : getValue().entrySet()) { @@ -299,7 +311,8 @@ public void setValue(Map value) { }}; } - @Override public String getReadableString() { + @Override + public String getReadableString() { return getKey(); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/Arg.java b/prison-core/src/main/java/tech/mcprison/prison/commands/Arg.java index f88b91747..1c6e7950a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/Arg.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/Arg.java @@ -23,7 +23,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface Arg { +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface Arg { /** * The default argument to process if the argument is not defined by the user. To make it a diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/ArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/ArgumentHandler.java index b663ebad3..0e23e3c0e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/ArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/ArgumentHandler.java @@ -153,7 +153,8 @@ public final void setMessage(String node, String def) { messageNodes.put(node, def); } - @Override public String toString() { + @Override + public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ArgumentHandler -> " + getClass().getName() + "\n"); sb.append("Set messages: \n"); diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/BaseCommands.java b/prison-core/src/main/java/tech/mcprison/prison/commands/BaseCommands.java index 48de15a3e..bfde19e4d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/BaseCommands.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/BaseCommands.java @@ -23,11 +23,6 @@ public void setCmdGroup( String cmdGroup ) { } -// public Player getPlayer( CommandSender sender ) { -// Optional player = Prison.get().getPlatform().getPlayer( sender.getName() ); -// return player.isPresent() ? player.get() : null; -// } - /** *

Gets a player by name. If the player is not online, then try to get them from * the offline player list. If not one is found, then return a null. @@ -37,37 +32,44 @@ public void setCmdGroup( String cmdGroup ) { * ensure a player is always returned, if its a valid player. *

* + *

Never should this function return a Player based upon sender. + *

+ * * @param sender * @param playerName is optional, if not supplied, then sender will be used * @return Player if found, or null. */ - public Player getPlayer( CommandSender sender, String playerName ) { - return getPlayer( sender, playerName, null ); + public Player getPlayerByName( // CommandSender sender, + String playerName ) { + return getPlayerByName( // sender, + playerName, null ); } -// public Player getPlayer( CommandSender sender ) { -// return getPlayer( sender, null, null ); -// } - public Player getPlayer( CommandSender sender, String playerName, UUID uuid ) { + + /** + *

This function should only return a Player based upon either the player's name + * or their UUID. It should never return a Player based upon sender. + *

+ * + *

Gets a player by name. If the player is not online, then try to get them from + * the offline player list. If not one is found, then return a null. + *

+ * + *

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

+ * + * + * @param sender + * @param playerName + * @param uuid + * @return + */ + public Player getPlayerByName( // CommandSender sender, + String playerName, UUID uuid ) { Player result = null; - playerName = playerName != null && !playerName.trim().isEmpty() ? - playerName : sender != null ? sender.getName() : null; - - //Output.get().logInfo("RanksCommands.getPlayer :: playerName = " + playerName ); - - if ( playerName != null ) { - Optional opt = Prison.get().getPlatform().getPlayer( playerName ); - if ( !opt.isPresent() ) { - opt = Prison.get().getPlatform().getOfflinePlayer( playerName ); - } - if ( !opt.isPresent() ) { - opt = Prison.get().getPlatform().getOfflinePlayer( uuid ); - } - if ( opt.isPresent() ) { - result = opt.get(); - } - - } + result = Prison.get().getPlatform().getRankPlayer( uuid, playerName ); + return result; } @@ -77,8 +79,6 @@ public Player getOnlinePlayer( CommandSender sender, String playerName ) { playerName = playerName != null && !playerName.trim().isEmpty() ? playerName : sender != null ? sender.getName() : null; - //Output.get().logInfo("RanksCommands.getPlayer :: playerName = " + playerName ); - if ( playerName != null ) { Optional opt = Prison.get().getPlatform().getPlayer( playerName ); @@ -90,30 +90,4 @@ public Player getOnlinePlayer( CommandSender sender, String playerName ) { return result; } - -// public double getPlayerBalance( Player player ) { -// -// EconomyIntegration economy = PrisonAPI.getIntegrationManager().getEconomy(); -// -// return economy.getBalance( player ); -// } -// -// public double getPlayerBalance( Player player, String currency ) { -// -// -// EconomyCurrencyIntegration currencyEcon = PrisonAPI.getIntegrationManager() -// .getEconomyForCurrency( currency ); -// if ( currencyEcon == null ) { -// // ERROR: currency is not supported -// Output.get().logInfo( "The currency %s is not supported. Therefore there is no blance.", -// currency ); -// return 0; -// } -// else { -// return currencyEcon.getBalance( player, currency ); -// } -// -// } - - } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/CommandArgument.java b/prison-core/src/main/java/tech/mcprison/prison/commands/CommandArgument.java index 27bafd4dc..bf5db9652 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/CommandArgument.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/CommandArgument.java @@ -52,7 +52,8 @@ public CommandArgument(String name, String description, String def, String verif this.argumentClass = argumentClass; } - @Override public Object execute(CommandSender sender, Arguments args) throws CommandError { + @Override + public Object execute(CommandSender sender, Arguments args) throws CommandError { String arg; if (!args.hasNext()) { if (def.equals(" ")) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/CommandHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/CommandHandler.java index c30b7f975..35ca3bcc1 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/CommandHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/CommandHandler.java @@ -48,14 +48,13 @@ import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.output.RowComponent; +import tech.mcprison.prison.output.Output.DebugTarget; import tech.mcprison.prison.util.ChatColor; public class CommandHandler { private String rootCommmand; private String commandFallback; -// public static final String COMMAND_PRIMARY_ROOT_COMMAND = "prison"; -// public static final String COMMAND_FALLBACK_PREFIX = "prison"; public static final String COMMAND_HELP_TEXT = "help"; @@ -70,12 +69,8 @@ public class CommandHandler { private Map rootCommands = new HashMap<>(); -// private List commands = new ArrayList<>(); - - private TabCompleaterData tabCompleaterData; -// private String helpSuffix = "help"; public CommandHandler() { this.plugin = Prison.get(); @@ -105,13 +100,9 @@ public CommandHandler() { Output.get().logInfo( "&3Root command: &7/%s &3fallback-prefix: &7%s", rootCommmand, commandFallback ); -// Output.get().logInfo( "&3Root command: &7/%s &3fallback-prefix: &7%s", -// DefaultSettings.COMMAND_PRIMARY_ROOT_COMMAND, DefaultSettings.COMMAND_FALLBACK_PREFIX ); } - - public String getRootCommmand() { return rootCommmand; } @@ -121,8 +112,6 @@ public String getCommandFallback() { } - - private PermissionHandler permissionHandler = (sender, permissions) -> { for (String perm : permissions) { if (!sender.hasPermission(perm)) { @@ -133,6 +122,7 @@ public String getCommandFallback() { }; private HelpHandler helpHandler = new HelpHandler() { + private String formatArgument(CommandArgument argument) { String def = argument.getDefault(); if (def.equals(" ")) { @@ -156,30 +146,30 @@ private String formatArgument(CommandArgument argument) { @Override public ChatDisplay getHelpMessage(CommandSender sender, RegisteredCommand command) { - if ( !hasCommandAccess(sender, command, command.getLabel(), new String[0] ) ) { - return null; - } - + if ( !hasCommandAccess(sender, command, command.getLabel(), new String[0] ) ) { + return null; + } + ChatDisplay chatDisplay = new ChatDisplay( String.format( "Cmd: &7%s", getUsageNoParameters(command)) ); if (command.isSet() && command.getDescription() != null && !command.getDescription().isEmpty()) { - chatDisplay.addText(ChatColor.DARK_AQUA + command.getDescription()); + chatDisplay.addText(ChatColor.DARK_AQUA + command.getDescription()); } chatDisplay.addText(getUsage(command)); if (command.isSet()) { for (CommandArgument argument : command.getArguments()) { - chatDisplay.addText(formatArgument(argument)); + chatDisplay.addText(formatArgument(argument)); } if (command.getWildcard() != null) { - chatDisplay.addText(formatArgument(command.getWildcard())); + chatDisplay.addText(formatArgument(command.getWildcard())); } List flags = command.getFlags(); if (flags.size() > 0) { - chatDisplay.addText(ChatColor.DARK_AQUA + "Flags:"); + chatDisplay.addText(ChatColor.DARK_AQUA + "Flags:"); for (Flag flag : flags) { StringBuilder args = new StringBuilder(); for (FlagArgument argument : flag.getArguments()) { @@ -187,88 +177,79 @@ public ChatDisplay getHelpMessage(CommandSender sender, RegisteredCommand comman } chatDisplay.addText("-" + flag.getIdentifier() + ChatColor.AQUA + args.toString()); for (FlagArgument argument : flag.getArguments()) { - chatDisplay.addText(formatArgument(argument)); + chatDisplay.addText(formatArgument(argument)); } } } if ( command.getPermissions() != null && command.getPermissions().length > 0 || command.getAltPermissions() != null && command.getAltPermissions().length > 0 ) { - StringBuilder sb = new StringBuilder(); - - if ( command.getPermissions() != null && command.getPermissions().length > 0 ) { - for ( String perm : command.getPermissions() ) { - if ( sb.length() > 0 ) { - sb.append( " " ); - } - sb.append( perm ); - } - } - if ( command.getAltPermissions() != null && command.getAltPermissions().length > 0 ) { - for ( String altPerm : command.getAltPermissions() ) { - if ( sb.length() > 0 ) { - sb.append( " " ); - } - sb.append( altPerm ); - } - } - - if ( sb.length() > 0 ) { - chatDisplay.addText(ChatColor.DARK_AQUA + "Permissions:"); - - sb.insert( 0, ChatColor.AQUA ); - sb.insert( 0, " " ); - chatDisplay.addText( sb.toString() ); - } + StringBuilder sb = new StringBuilder(); + + if ( command.getPermissions() != null && command.getPermissions().length > 0 ) { + for ( String perm : command.getPermissions() ) { + if ( sb.length() > 0 ) { + sb.append( " " ); + } + sb.append( perm ); + } + } + if ( command.getAltPermissions() != null && command.getAltPermissions().length > 0 ) { + for ( String altPerm : command.getAltPermissions() ) { + if ( sb.length() > 0 ) { + sb.append( " " ); + } + sb.append( altPerm ); + } + } + + if ( sb.length() > 0 ) { + chatDisplay.addText(ChatColor.DARK_AQUA + "Permissions:"); + + sb.insert( 0, ChatColor.AQUA ); + sb.insert( 0, " " ); + chatDisplay.addText( sb.toString() ); + } } if ( command.getAliases() != null && command.getAliases().length > 0 ) { - StringBuilder sb = new StringBuilder(); - - if ( command.getAliases() != null && command.getAliases().length > 0 ) { - for ( String perm : command.getAliases() ) { - if ( sb.length() > 0 ) { - sb.append( " " ); - } - sb.append( ChatColor.DARK_BLUE ).append( "[" ) - .append( ChatColor.AQUA ).append( perm ) - .append( ChatColor.DARK_BLUE ).append( "]" ); - } - } - - if ( sb.length() > 0 ) { - chatDisplay.addText(ChatColor.DARK_AQUA + "Aliases:"); - - sb.insert( 0, " " ); - chatDisplay.addText( sb.toString() ); - } + StringBuilder sb = new StringBuilder(); + + if ( command.getAliases() != null && command.getAliases().length > 0 ) { + for ( String perm : command.getAliases() ) { + if ( sb.length() > 0 ) { + sb.append( " " ); + } + sb.append( ChatColor.DARK_BLUE ).append( "[" ) + .append( ChatColor.AQUA ).append( perm ) + .append( ChatColor.DARK_BLUE ).append( "]" ); + } + } + + if ( sb.length() > 0 ) { + chatDisplay.addText(ChatColor.DARK_AQUA + "Aliases:"); + + sb.insert( 0, " " ); + chatDisplay.addText( sb.toString() ); + } } if ( command.getDocURLs() != null && command.getDocURLs().length > 0 ) { - chatDisplay.addText(ChatColor.DARK_AQUA + "Documentation:"); - - for ( String docURL : command.getDocURLs() ) { - RowComponent row = new RowComponent(); - - row.addTextComponent( " " ); - FancyMessage fMessage = new FancyMessage( docURL ).link( docURL ) - .tooltip( "Click to open link" ); - row.addFancy( fMessage ); - - chatDisplay.addComponent( row ); - - - -// StringBuilder sb = new StringBuilder(); -// -// sb.append( " " ).append( ChatColor.DARK_BLUE ).append( "[" ) -// .append( ChatColor.AQUA ).append( docURL ) -// .append( ChatColor.DARK_BLUE ).append( "]" ); -// -// chatDisplay.addText( sb.toString() ); - } + chatDisplay.addText(ChatColor.DARK_AQUA + "Documentation:"); + + for ( String docURL : command.getDocURLs() ) { + RowComponent row = new RowComponent(); + + row.addTextComponent( " " ); + FancyMessage fMessage = new FancyMessage( docURL ).link( docURL ) + .tooltip( "Click to open link" ); + row.addFancy( fMessage ); + + chatDisplay.addComponent( row ); + + } } } @@ -280,73 +261,65 @@ public ChatDisplay getHelpMessage(CommandSender sender, RegisteredCommand comman TreeSet subCommandSet = new TreeSet<>(); for (RegisteredCommand scommand : subcommands) { - String sLabel = scommand.getCompleteLabel(); - - if ( hasCommandAccess(sender, scommand, sLabel, new String[0] ) ) { - - String subCmd = scommand.getUsage(); - - int subCmdSubCnt = scommand.getSuffixes().size(); - String subCommands = (subCmdSubCnt == 0 ? "" : - ChatColor.DARK_AQUA + "(" + subCmdSubCnt + " Subcommands)"); - - String isAlias = scommand.isAlias() ? ChatColor.DARK_AQUA + " Alias" : ""; - - subCommandSet.add( - String.format( "%s %s %s", subCmd, subCommands, isAlias )); - } + String sLabel = scommand.getCompleteLabel(); + + if ( hasCommandAccess(sender, scommand, sLabel, new String[0] ) ) { + + String subCmd = scommand.getUsage(); + + int subCmdSubCnt = scommand.getSuffixes().size(); + String subCommands = (subCmdSubCnt == 0 ? "" : + ChatColor.DARK_AQUA + "(" + subCmdSubCnt + " Subcommands)"); + + String isAlias = scommand.isAlias() ? ChatColor.DARK_AQUA + " Alias" : ""; + + subCommandSet.add( + String.format( "%s %s %s", subCmd, subCommands, isAlias )); + } } // Only if there are entries to show, then include the header and the details if ( subCommandSet.size() > 0 ) { - chatDisplay.addText(ChatColor.DARK_AQUA + "Subcommands:"); - - for (String subCmd : subCommandSet) { - chatDisplay.addText(subCmd); - } + chatDisplay.addText(ChatColor.DARK_AQUA + "Subcommands:"); + + for (String subCmd : subCommandSet) { + chatDisplay.addText(subCmd); + } } } if ( command.getLabel().equalsIgnoreCase( getRootCommmand() ) && rootCommands.size() > 1 ) { -// if ( command.getLabel().equalsIgnoreCase( DefaultSettings.COMMAND_PRIMARY_ROOT_COMMAND ) && -// rootCommands.size() > 1 ) { - ArrayList rootCommandsMessages = buildHelpRootCommands(); - if ( rootCommandsMessages.size() > 1 ) { - for ( String rootCmd : rootCommandsMessages ) - { - chatDisplay.addText( rootCmd ); + ArrayList rootCommandsMessages = buildHelpRootCommands(); + if ( rootCommandsMessages.size() > 1 ) { + for ( String rootCmd : rootCommandsMessages ) { + chatDisplay.addText( rootCmd ); } - - } - - ArrayList aliasesMessages = buildHelpAliases(); - if ( aliasesMessages.size() > 1 ) { - for ( String alias : aliasesMessages ) - { - chatDisplay.addText( alias ); + + } + + ArrayList aliasesMessages = buildHelpAliases(); + if ( aliasesMessages.size() > 1 ) { + for ( String alias : aliasesMessages ) { + chatDisplay.addText( alias ); } - - } - - ArrayList excludedWorlds = buildExcludedWorlds(); - if ( excludedWorlds.size() > 1 ) { - for ( String excludedWorld : excludedWorlds ) - { - chatDisplay.addText( excludedWorld ); - } - - } - - + + } + + ArrayList excludedWorlds = buildExcludedWorlds(); + if ( excludedWorlds.size() > 1 ) { + for ( String excludedWorld : excludedWorlds ) { + chatDisplay.addText( excludedWorld ); + } + + } } return chatDisplay; -// return message.toArray(new String[0]); } private ArrayList buildExcludedWorlds() { @@ -392,42 +365,27 @@ private ArrayList buildHelpRootCommands() { // Force a sorting by use of a TreeSet. Collections.sort() would not work. TreeSet rootCommandSet = new TreeSet<>(); - // Try adding in all other root commands: + // Try adding in all other root commands: Set rootKeys = getRootCommands().keySet(); - for ( PluginCommand rootKey : rootKeys ) { - StringBuilder sbAliases = new StringBuilder(); - - // Do not list aliases: - if ( !(rootKey.getRegisteredCommand().isAlias() && rootKey.getRegisteredCommand().getParentOfAlias() != null) ) { -// String isAlias = rootKey.getRegisteredCommand().isAlias() ? ChatColor.DARK_AQUA + " Alias" : ""; - -// if ( rootKey.getRegisteredCommand().getRegisteredAliases().size() > 0 ) { -// for ( RegisteredCommand alias : rootKey.getRegisteredCommand().getRegisteredAliases() ) { -// -// sbAliases.append( ChatColor.DARK_BLUE ).append( "[" ).append( ChatColor.AQUA ).append( "/" ) -// .append( getRootCommandRegisteredLabel(alias) ) -// .append( ChatColor.DARK_BLUE ).append( "] " ); -// } -// sbAliases.insert( 0, -// new StringBuilder().append( ChatColor.DARK_AQUA ). -// append( "Aliases: " ).append( ChatColor.AQUA )); -// } - String rootCmd = - String.format( "%s %s", - rootKey.getUsage(), sbAliases.toString() ); + for ( PluginCommand rootKey : rootKeys ) { + StringBuilder sbAliases = new StringBuilder(); - rootCommandSet.add( rootCmd ); - } - - - } + // Do not list aliases: + if ( !(rootKey.getRegisteredCommand().isAlias() && rootKey.getRegisteredCommand().getParentOfAlias() != null) ) { + String rootCmd = + String.format( "%s %s", + rootKey.getUsage(), sbAliases.toString() ); + + rootCommandSet.add( rootCmd ); + } + } - for (String rootCmd : rootCommandSet) { - message.add(rootCmd); - } - - return message; + for (String rootCmd : rootCommandSet) { + message.add(rootCmd); + } + + return message; } /** @@ -446,20 +404,9 @@ private ArrayList buildHelpAliases() { for ( RegisteredCommand regCmd : getAllRegisteredCommands() ) { buildHelpAliasMessage( regCmd, aliasesSet ); -// plugin.logDebug( "### CommandHandler.buildHelpAliases ### test: %s ", regCmd.toString() ); } -// // Try adding in all other root commands: -// Set rootKeys = getRootCommands().keySet(); -// for ( PluginCommand rootKey : rootKeys ) { -// -// plugin.logDebug( "### CommandHandler.buildHelpAliases ### rootCommands: %s ", rootKey.toString() ); -// RegisteredCommand registeredCommand = rootKey.getRegisteredCommand(); -// -// buildHelpAliases( registeredCommand, aliasesSet ); -// } - // Sorted results, add to the List: for (String rootCmd : aliasesSet) { message.add(rootCmd); @@ -468,17 +415,6 @@ private ArrayList buildHelpAliases() { return message; } -// private void buildHelpAliases( RegisteredCommand registeredCommand, TreeSet aliasesSet ) { -// buildHelpAliasMessage( registeredCommand, aliasesSet ); -// -// plugin.logDebug( "### CommandHandler.buildHelpAliases ### : %s ", registeredCommand.toString() ); -// -// for ( RegisteredCommand suffixRegCmd : registeredCommand.getSuffixes() ) { -// -// buildHelpAliases( suffixRegCmd, aliasesSet ); -// } -// -// } private void buildHelpAliasMessage( RegisteredCommand registeredCommand, TreeSet aliasesSet ) { if ( registeredCommand.isAlias() && registeredCommand.getParentOfAlias() != null) { @@ -510,14 +446,14 @@ private void buildHelpAliasMessage( RegisteredCommand registeredCommand, TreeSet * @return */ private String getRootCommandRegisteredLabel(RegisteredCommand command ) { - String commandLabel = command.getLabel(); - if ( command instanceof RootCommand ) { - RootCommand rootCommand = (RootCommand) command; - if ( rootCommand.getBukkitCommand().getLabelRegistered() != null ) { - commandLabel = rootCommand.getBukkitCommand().getLabelRegistered(); - } - } - return commandLabel; + String commandLabel = command.getLabel(); + if ( command instanceof RootCommand ) { + RootCommand rootCommand = (RootCommand) command; + if ( rootCommand.getBukkitCommand().getLabelRegistered() != null ) { + commandLabel = rootCommand.getBukkitCommand().getLabelRegistered(); + } + } + return commandLabel; } @Override @@ -617,46 +553,43 @@ public void registerArgumentHandler(Class clazz, } public Object getRegisteredCommandClass( @SuppressWarnings( "rawtypes" ) Class commandClass ) { - Object results = null; - - String key = commandClass.getSimpleName(); - if ( key != null && getRegisteredCommands().containsKey( key ) ) { - results = getRegisteredCommands().get( key ); - } - - return results; + Object results = null; + + String key = commandClass.getSimpleName(); + if ( key != null && getRegisteredCommands().containsKey( key ) ) { + results = getRegisteredCommands().get( key ); + } + + return results; } public void registerCommands(Object methodInstance) { - // Keep a reference to the registered command object so it can be - // accessed in the future if needed for other uses. - getRegisteredCommands().put( methodInstance.getClass().getSimpleName(), methodInstance ); - - for (Method method : methodInstance.getClass().getDeclaredMethods()) { - Command commandAnno = method.getAnnotation(Command.class); - if (commandAnno == null) { - continue; - } - - RegisteredCommand mainCommand = commandRegisterConfig( method, commandAnno, methodInstance ); - - - String[] aliases = addConfigAliases( commandAnno.identifier(), commandAnno.aliases() ); - - if ( aliases.length > 0 ) { -// if ( commandAnno.aliases() != null && commandAnno.aliases().length > 0 ) { - - - for ( String alias : aliases ) -// for ( String alias : commandAnno.aliases() ) - { - RegisteredCommand aliasCommand = commandRegisterConfig( method, commandAnno, methodInstance, alias ); - - // Add the alias to the primary RegisteredCommand to track it's own aliases: - mainCommand.getRegisteredAliases().add( aliasCommand ); - aliasCommand.setParentOfAlias( mainCommand ); - } + // Keep a reference to the registered command object so it can be + // accessed in the future if needed for other uses. + getRegisteredCommands().put( methodInstance.getClass().getSimpleName(), methodInstance ); + + for (Method method : methodInstance.getClass().getDeclaredMethods()) { + Command commandAnno = method.getAnnotation(Command.class); + if (commandAnno == null) { + continue; + } + + RegisteredCommand mainCommand = commandRegisterConfig( method, commandAnno, methodInstance ); + + + String[] aliases = addConfigAliases( commandAnno.identifier(), commandAnno.aliases() ); + + if ( aliases.length > 0 ) { + + + for ( String alias : aliases ) { + RegisteredCommand aliasCommand = commandRegisterConfig( method, commandAnno, methodInstance, alias ); + + // Add the alias to the primary RegisteredCommand to track it's own aliases: + mainCommand.getRegisteredAliases().add( aliasCommand ); + aliasCommand.setParentOfAlias( mainCommand ); + } } @@ -664,7 +597,7 @@ public void registerCommands(Object methodInstance) { } private RegisteredCommand commandRegisterConfig( Method method, Command commandAnno, Object methodInstance ) { - return commandRegisterConfig( method, commandAnno, methodInstance, null ); + return commandRegisterConfig( method, commandAnno, methodInstance, null ); } private RegisteredCommand commandRegisterConfig( Method method, Command commandAnno, @@ -685,30 +618,25 @@ private RegisteredCommand commandRegisterConfig( Method method, Command commandA if ( rootPluginCommand == null ) { - String[] aliases = addConfigAliases( commandAnno.identifier(), commandAnno.aliases() ); - rootPluginCommand = new PluginCommand(label, - commandAnno.description(), - "/" + label, - aliases ); -// rootPluginCommand = new PluginCommand(label, -// commandAnno.description(), -// "/" + label, -// commandAnno.aliases() ); - plugin.getPlatform().registerCommand(rootPluginCommand); + String[] aliases = addConfigAliases( commandAnno.identifier(), commandAnno.aliases() ); + rootPluginCommand = new PluginCommand(label, + commandAnno.description(), + "/" + label, + aliases ); + plugin.getPlatform().registerCommand(rootPluginCommand); } // If getRootCommands() does not contain the rootPCommand then add it: if ( !getRootCommands().containsKey( rootPluginCommand ) ) { - RootCommand rootRegisteredCommand = new RootCommand( rootPluginCommand, this ); - rootRegisteredCommand.setAlias( alias != null ); - - // Must add all new RegisteredCommand objects to both getAllRegisteredCommands() and - // getTabCompleterData(). - getAllRegisteredCommands().add( rootRegisteredCommand ); - getTabCompleaterData().add( rootRegisteredCommand ); - - getRootCommands().put( rootPluginCommand, rootRegisteredCommand ); + RootCommand rootRegisteredCommand = new RootCommand( rootPluginCommand, this ); + rootRegisteredCommand.setAlias( alias != null ); + + // Must add all new RegisteredCommand objects to both getAllRegisteredCommands() and + getAllRegisteredCommands().add( rootRegisteredCommand ); + getTabCompleaterData().add( rootRegisteredCommand ); + + getRootCommands().put( rootPluginCommand, rootRegisteredCommand ); } RegisteredCommand mainCommand = getRootCommands().get( rootPluginCommand ); @@ -738,11 +666,11 @@ private RegisteredCommand commandRegisterConfig( Method method, Command commandA rootPluginCommand.setRegisteredCommand( mainCommand ); - // Validate that the first parameter, if it exists, is actually a CommandSender: - if ( method.getParameterCount() > 0 ) { - - // The first parameter "should" always be CommandSender or there will be difficult - // to trace failures at runtime: + // Validate that the first parameter, if it exists, is actually a CommandSender: + if ( method.getParameterCount() > 0 ) { + + // The first parameter "should" always be CommandSender or there will be difficult + // to trace failures at runtime: Class cmdSender = method.getParameterTypes()[0]; if ( !cmdSender.getSimpleName().equalsIgnoreCase( "CommandSender") ) { @@ -756,59 +684,59 @@ private RegisteredCommand commandRegisterConfig( Method method, Command commandA cmdSender.getSimpleName() )); } - - } - - mainCommand.set(methodInstance, method); + + } + + mainCommand.set(methodInstance, method); return mainCommand; } public static String remapRootCmdIdentifiers(String identifier) { - if ( identifier != null ) { - - int idx = identifier.indexOf( " " ); - String root = idx == -1 ? identifier : identifier.substring( 0, idx ); - - String key = "prisonCommandHandler.command-roots." + root; - - String newRoot = Prison.get().getPlatform().getConfigString( key ); - - if ( newRoot != null && !root.equals(newRoot) ) { - - identifier = newRoot + - (idx == -1 ? "" : identifier.substring(idx)); - } - } + if ( identifier != null ) { + + int idx = identifier.indexOf( " " ); + String root = idx == -1 ? identifier : identifier.substring( 0, idx ); + + String key = "prisonCommandHandler.command-roots." + root; + + String newRoot = Prison.get().getPlatform().getConfigString( key ); + + if ( newRoot != null && !root.equals(newRoot) ) { + + identifier = newRoot + + (idx == -1 ? "" : identifier.substring(idx)); + } + } return identifier; } public static String[] addConfigAliases( String label, String[] aliases ) { - String[] results = aliases; - - String configKey = "prisonCommandHandler.aliases." + label.replace( " ", "." ); - - List ca = Prison.get().getPlatform().getConfigStringArray( configKey ); - if ( ca != null && ca.size() > 0 && ca.get( 0 ) instanceof String ) { - - List configAliases = new ArrayList<>(); - - for ( String alias : aliases ) { - configAliases.add( alias ); - } - - for ( Object aliasObj : ca ) { - if ( aliasObj instanceof String ) { - configAliases.add( aliasObj.toString() ); + String[] results = aliases; + + String configKey = "prisonCommandHandler.aliases." + label.replace( " ", "." ); + + List ca = Prison.get().getPlatform().getConfigStringArray( configKey ); + if ( ca != null && ca.size() > 0 && ca.get( 0 ) instanceof String ) { + + List configAliases = new ArrayList<>(); + + for ( String alias : aliases ) { + configAliases.add( alias ); } - } - - results = configAliases.toArray( new String[0] ); - - } + + for ( Object aliasObj : ca ) { + if ( aliasObj instanceof String ) { + configAliases.add( aliasObj.toString() ); + } + } + + results = configAliases.toArray( new String[0] ); + + } return results; } @@ -824,73 +752,72 @@ public static String[] addConfigAliases( String label, String[] aliases ) public boolean hasCommandAccess( CommandSender sender, RegisteredCommand rootCommand, String label, String[] args ) { - CommandAccessResults results = new CommandAccessResults( sender ); + CommandAccessResults results = new CommandAccessResults( sender ); + + hasCommandAccess( sender, rootCommand, label, args, results ); + + if ( results.isAccess() ) { + results.setAccessPermitted(); + } + + if ( !results.isAccess() ) { + // Debug logging if prison is in debug mode: + results.debugAccess(); + } - hasCommandAccess( sender, rootCommand, label, args, results ); - - if ( results.isAccess() ) { - results.setAccessPermitted(); - } - - if ( !results.isAccess() ) { - // Debug logging if prison is in debug mode: - results.debugAccess(); - } - - return results.isAccess(); + return results.isAccess(); } private void hasCommandAccess( CommandSender sender, RegisteredCommand rootCommand, String label, String[] args, CommandAccessResults results ) { -// boolean results = true; - if ( !sender.isOp() ) { - - boolean hasAccess = rootCommand.testPermission(sender); - - if ( !hasAccess ) { - results.setAccess( false ); - } - else { - - String exRAKey = "prisonCommandHandler.exclude-non-ops.exclude-related-aliases"; - boolean excludeRelatedAliases = getConfigBoolean( exRAKey ); - - String sLabelAlias = !excludeRelatedAliases || rootCommand.getParentOfAlias() == null ? - null : rootCommand.getParentOfAlias().getCompleteLabel(); - - - commandAccessPermChecks( sender, rootCommand, label, results ); - - if ( results.isAccess() && sLabelAlias != null ) { - - commandAccessPermChecks( sender, rootCommand.getParentOfAlias(), sLabelAlias, results ); - } - } - - - } + if ( !sender.isOp() ) { + + boolean hasAccess = rootCommand.testPermission(sender); + + if ( !hasAccess ) { + results.setAccess( false ); + } + else { + + String exRAKey = "prisonCommandHandler.exclude-non-ops.exclude-related-aliases"; + boolean excludeRelatedAliases = getConfigBoolean( exRAKey ); + + String sLabelAlias = !excludeRelatedAliases || rootCommand.getParentOfAlias() == null ? + null : rootCommand.getParentOfAlias().getCompleteLabel(); + + + commandAccessPermChecks( sender, rootCommand, label, results ); + + if ( results.isAccess() && sLabelAlias != null ) { + + commandAccessPermChecks( sender, rootCommand.getParentOfAlias(), sLabelAlias, results ); + } + } + + + } - // If we get to this point, and the result is true (the player has access the - // specified command so far), and there are more args, we need to next - // take the args[0] and append it to the label, and then test it again. - // This needs to continue until the generated command is rejected, or - // it passes it's clean and the player has full access to the command(s). - if ( results.isAccess() && args.length > 0 ) { - String newSuffix = args[0]; - String newLabel = label + " " + newSuffix; - String[] newArgs = Arrays.copyOfRange( args, 1, args.length ); - - RegisteredCommand newSuffixCommand = rootCommand.getSuffixCommand( newSuffix ); - - if ( newSuffixCommand != null ) { - - hasCommandAccess( sender, newSuffixCommand, - newLabel, newArgs, results ); - } - } + // If we get to this point, and the result is true (the player has access the + // specified command so far), and there are more args, we need to next + // take the args[0] and append it to the label, and then test it again. + // This needs to continue until the generated command is rejected, or + // it passes it's clean and the player has full access to the command(s). + if ( results.isAccess() && args.length > 0 ) { + String newSuffix = args[0]; + String newLabel = label + " " + newSuffix; + String[] newArgs = Arrays.copyOfRange( args, 1, args.length ); + + RegisteredCommand newSuffixCommand = rootCommand.getSuffixCommand( newSuffix ); + + if ( newSuffixCommand != null ) { + + hasCommandAccess( sender, newSuffixCommand, + newLabel, newArgs, results ); + } + } } @@ -952,10 +879,10 @@ private void commandAccessPermChecks(CommandSender sender, RegisteredCommand roo } private boolean getConfigBoolean( String configKey ) { - return Prison.get().getPlatform().getConfigBooleanFalse( configKey ); + return Prison.get().getPlatform().getConfigBooleanFalse( configKey ); } private List getConfigStringArray( String configKey ) { - return Prison.get().getPlatform().getConfigStringArray( configKey ); + return Prison.get().getPlatform().getConfigStringArray( configKey ); } public boolean onCommand(CommandSender sender, PluginCommand command, String label, @@ -963,38 +890,55 @@ public boolean onCommand(CommandSender sender, PluginCommand command, String lab RootCommand rootCommand = rootCommands.get(command); if (rootCommand == null) { - Output.get().logError( "CommandHandler.onCommand(): " + command.getLabel() + - " : No root command found. " ); + Output.get().logError( "CommandHandler.onCommand(): " + command.getLabel() + + " : No root command found. " ); return false; } if (rootCommand.isOnlyPlayers() && !(sender instanceof Player)) { Prison.get().getLocaleManager().getLocalizable("cantAsConsole") .sendTo(sender, LogLevel.ERROR); + + boolean debug = Output.get().isActiveTarget( DebugTarget.commandHandler ); + if ( debug ) { + String argz = ""; + for (String arg : args) { + argz += arg + " "; + } + + String msg = String.format( + "CommandHandler.onCommand: Sender %s. Command is marked with 'onlyPlayers'. " + + "Cannot run. : [%s]", + sender.getName(), + (label + " " + argz).trim() + ); + Output.get().logInfo( msg ); + } + return true; } else if ( !hasCommandAccess( sender, rootCommand, label, args ) ) { - // The player does not have access to this command. - // Who cares! Just exit and do nothing. Never log this. - return true; + // The player does not have access to this command. + // Who cares! Just exit and do nothing. Never log this. + return true; } else { - try { - rootCommand.execute(sender, args); - } - catch ( Exception e ) { - String message = "Prison CommandHander: onCommand: " + e.getMessage() + - " [" + e.getCause() == null ? "cause not reported" : e.getCause() + "]"; - - Output.get().logError( message ); - for ( StackTraceElement ste : e.getStackTrace() ) { - Output.get().logError( ste.toString() ); - } - - } + try { + rootCommand.execute( sender, args ); + } + catch ( Exception e ) { + String message = "Prison CommandHander: onCommand: " + e.getMessage() + + " [" + e.getCause() == null ? "cause not reported" : e.getCause() + "]"; + + Output.get().logError( message ); + for ( StackTraceElement ste : e.getStackTrace() ) { + Output.get().logError( ste.toString() ); + } + + } } @@ -1045,9 +989,6 @@ public void setRootCommands( Map rootCommands ) { this.rootCommands = rootCommands; } -// private List getCommands() { -// return commands; -// } public TabCompleaterData getTabCompleaterData() { return tabCompleaterData; @@ -1092,27 +1033,27 @@ public List getRootCommandKeys() { */ public String findRegisteredCommand(String command) { - String[] patternParts = command.split( " " ); - - if ( patternParts.length > 0 ) { - String rootPattern = patternParts[0]; - - for ( RegisteredCommand cmd : allRegisteredCommands ) { - - if ( cmd.getLabel().equalsIgnoreCase( rootPattern ) ) { - - if ( cmd.isRoot() ) { - - RootCommand rootCommand = (RootCommand) cmd; - if ( rootCommand.getBukkitCommand().getLabelRegistered() != null ) { - - patternParts[0] = rootCommand.getBukkitCommand().getLabelRegistered(); - } - } - } - } - } - - return String.join( " ", patternParts ); + String[] patternParts = command.split( " " ); + + if ( patternParts.length > 0 ) { + String rootPattern = patternParts[0]; + + for ( RegisteredCommand cmd : allRegisteredCommands ) { + + if ( cmd.getLabel().equalsIgnoreCase( rootPattern ) ) { + + if ( cmd.isRoot() ) { + + RootCommand rootCommand = (RootCommand) cmd; + if ( rootCommand.getBukkitCommand().getLabelRegistered() != null ) { + + patternParts[0] = rootCommand.getBukkitCommand().getLabelRegistered(); + } + } + } + } + } + + return String.join( " ", patternParts ); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/CommandPagedData.java b/prison-core/src/main/java/tech/mcprison/prison/commands/CommandPagedData.java index f81a536e6..86ba170c4 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/CommandPagedData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/CommandPagedData.java @@ -93,11 +93,11 @@ public void generatePagedCommandFooter( ChatDisplay display, String message ) { RowComponent row = new RowComponent(); if ( getCurPage() > 1 ) { - row.addFancy( - new ButtonComponent( "&e<-- Prev Page", '-', Style.NEGATIVE) - .runCommand(pageCommand + " " + (getCurPage() - 1) + - (getPageCommandSuffix() == null ? "" : " " + getPageCommandSuffix()), - "View the prior page of search results").getFancyMessage() ); + row.addFancy( + new ButtonComponent( "&e<-- Prev Page", '-', Style.NEGATIVE) + .runCommand(pageCommand + " " + (getCurPage() - 1) + + (getPageCommandSuffix() == null ? "" : " " + getPageCommandSuffix()), + "View the prior page of search results").getFancyMessage() ); } row.addFancy( new FancyMessage(" &9< &3Page " + curPage + " of " + @@ -187,7 +187,5 @@ public int getPageEnd() { public void setPageEnd( int pageEnd ) { this.pageEnd = pageEnd; } - - } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/Flags.java b/prison-core/src/main/java/tech/mcprison/prison/commands/Flags.java index c95c78d2f..15541d0c9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/Flags.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/Flags.java @@ -23,7 +23,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Flags { +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Flags { /** * @return description of the flags (in the same order as the identifiers) diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/PluginCommand.java b/prison-core/src/main/java/tech/mcprison/prison/commands/PluginCommand.java index 69a7f7a50..fafd9c57e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/PluginCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/PluginCommand.java @@ -54,17 +54,17 @@ public PluginCommand(String label, String description, String usage, String[] al @Override public String toString() { - StringBuilder sb = new StringBuilder(); - - sb.append( getUsage() ) - .append( " alias: " ).append( getAliases().size() ) - .append( " hasRegCmd: " ).append( getRegisteredCommand() != null ); - - if ( getRegisteredCommand() != null ) { - sb.append( " (" ).append( getRegisteredCommand().getUsage() ).append( ")" ); - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + sb.append( getUsage() ) + .append( " alias: " ).append( getAliases().size() ) + .append( " hasRegCmd: " ).append( getRegisteredCommand() != null ); + + if ( getRegisteredCommand() != null ) { + sb.append( " (" ).append( getRegisteredCommand().getUsage() ).append( ")" ); + } + + return sb.toString(); } public String getLabel() { @@ -72,16 +72,15 @@ public String getLabel() { } public String getLabelRegistered() { - return labelRegistered; + return labelRegistered; } public void setLabelRegistered( String labelRegistered ) { - this.labelRegistered = labelRegistered; + this.labelRegistered = labelRegistered; } public String getDescription() { return description; } - public void setDescription(String description) { this.description = description; } @@ -89,7 +88,6 @@ public void setDescription(String description) { public String getUsage() { return getLabelRegistered() == null ? usage : "/" + getLabelRegistered(); } - public void setUsage(String usage) { this.usage = usage; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java b/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java index f8deaecf7..af21e9ce4 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/RegisteredCommand.java @@ -32,6 +32,7 @@ import tech.mcprison.prison.output.ChatDisplay; import tech.mcprison.prison.output.LogLevel; import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.output.Output.DebugTarget; public class RegisteredCommand @@ -43,6 +44,7 @@ public class RegisteredCommand private boolean alias = false; private int usageCount; + private int usageCountAlias; private long usageRunTimeNanos; private String junitTest = null; @@ -83,6 +85,7 @@ public RegisteredCommand(String label, CommandHandler handler, RegisteredCommand this.registeredAliases = new ArrayList<>(); this.usageCount = 0; + this.usageCountAlias = 0; this.usageRunTimeNanos = 0; } @@ -91,36 +94,36 @@ public RegisteredCommand(String label, CommandHandler handler, RegisteredCommand */ private RegisteredCommand( String jUnitUsage ) { - this.junitTest = jUnitUsage; - - this.label = "junitTest"; - this.handler = null; - this.parent = null; - - this.registeredAliases = new ArrayList<>(); + this.junitTest = jUnitUsage; + + this.label = "junitTest"; + this.handler = null; + this.parent = null; + + this.registeredAliases = new ArrayList<>(); } protected static RegisteredCommand junitTest( String jUnitUsage ) { - RegisteredCommand results = new RegisteredCommand( jUnitUsage ); - - return results; + RegisteredCommand results = new RegisteredCommand( jUnitUsage ); + + return results; } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - - sb.append( getUsage() ) - .append( " isRoot: " ).append( isRoot() ) - .append( " isAlias: " ).append( isAlias() ) - .append( " suffixCnt: " ).append( getSuffixes().size() ) - .append( " hasAliasParent: " ).append( getParentOfAlias() != null ); - - if ( getParentOfAlias() != null ) { - sb.append( " (" ).append( getParentOfAlias().getUsage() ).append( ")" ); - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + sb.append( getUsage() ) + .append( " isRoot: " ).append( isRoot() ) + .append( " isAlias: " ).append( isAlias() ) + .append( " suffixCnt: " ).append( getSuffixes().size() ) + .append( " hasAliasParent: " ).append( getParentOfAlias() != null ); + + if ( getParentOfAlias() != null ) { + sb.append( " (" ).append( getParentOfAlias().getUsage() ).append( ")" ); + } + + return sb.toString(); } /** @@ -145,8 +148,8 @@ boolean doesSuffixCommandExist(String suffix) { } public String getCompleteLabel() { - return (parent == null ? "" : parent.getCompleteLabel() + " " ) + - (label == null ? "-noCommandLabelDefined-" : label) ; + return (parent == null ? "" : parent.getCompleteLabel() + " " ) + + (label == null ? "-noCommandLabelDefined-" : label) ; } /** @@ -160,11 +163,47 @@ public String getCompleteLabel() { * @param args */ protected void execute(CommandSender sender, String[] args) { + execute( sender, args, true ); + } + + protected void execute(CommandSender sender, String[] args, boolean allowDebug ) { - // First ensure the player is not locked out of this command: - if ( !handler.hasCommandAccess(sender, this, getLabel(), args) ) { - return; - } + // Only enable debug mode if the selective debug target is commandHanlder. + // To enable this use ... + boolean debug = Output.get().isActiveTarget( DebugTarget.commandHandler ); + + // First ensure the player is not locked out of this command: + if ( !handler.hasCommandAccess(sender, this, getLabel(), args) ) { + + if ( debug ) { + String argz = ""; + for (String arg : args) { + argz += arg + " "; + } + + String msg = String.format( + "RegisteredCommand.execute: Player %s does not have access to a command: [%s]", + sender.getName(), + (getLabel() + " " + argz).trim() + ); + Output.get().logInfo( msg ); + } + return; + } + + if ( debug ) { + String argz = ""; + for (String arg : args) { + argz += arg + " "; + } + + String msg = String.format( + "RegisteredCommand.execute: Player %s is attempting to run command: [%s]", + sender.getName(), + (getLabel() + " " + argz).trim() + ); + Output.get().logInfo( msg ); + } if (!testPermission(sender)) { Prison.get().getLocaleManager().getLocalizable("noPermission") @@ -202,7 +241,7 @@ protected void execute(CommandSender sender, String[] args) { // Strip first arg, then recursively try again String[] nargs = new String[args.length - 1]; System.arraycopy(args, 1, nargs, 0, args.length - 1); - command.execute( sender, nargs ); + command.execute( sender, nargs, false ); } } else { @@ -247,12 +286,17 @@ private void executeMethod(CommandSender sender, String[] args ) { try { try { - // The command is ran here with the invoke... - - // Record that the command has been "ran", which does not mean it was successful: - incrementUsageCount(); - nanosStart = System.nanoTime(); - + // The command is ran here with the invoke... + + // Record that the command has been "ran", which does not mean it was successful: + incrementUsageCount(); + + if ( isAlias() && getParentOfAlias() != null ) { + getParentOfAlias().incrementUsageCountAlias(); + + } + nanosStart = System.nanoTime(); + method.invoke(getMethodInstance(), resultArgs.toArray()); nanosEnd = System.nanoTime(); @@ -263,48 +307,49 @@ private void executeMethod(CommandSender sender, String[] args ) { } catch ( IllegalArgumentException | InvocationTargetException e) { - nanosEnd = System.nanoTime(); - - long nanosDuration = nanosEnd - nanosStart; - this.usageRunTimeNanos += nanosDuration; - - if (e.getCause() instanceof CommandError) { - CommandError ce = (CommandError) e.getCause(); - Output.get().sendError(sender, ce.getColorizedMessage()); - if (ce.showUsage()) { - sender.sendMessage(getUsage()); - } - } - else { - StringBuilder sb = new StringBuilder(); - - for ( Object arg : resultArgs ) { - sb.append( "[" ); - sb.append( arg.toString() ); - sb.append( "] " ); - } - - String message = "RegisteredCommand.executeMethod(): Invoke error: [" + - e.getMessage() + "] cause: [" + - (e.getCause() == null ? "" : e.getCause().getMessage()) + "] " + - " target instance: [methodName= " + - method.getName() + " parmCnt=" + method.getParameterCount() + " methodInstance=" + - getMethodInstance().getClass().getCanonicalName() + "] " + - "command arguments: " + sb.toString() - ; - - // Warning: if the args contains a % then the following sendError will fail because - // the % will be treated as String.format() placeholders. So to be safe and - // to prevent this failure, escape all % with a double % such as %%. - message = message.replace( "%", "%%" ); - - Output.get().logError( message ); - - Output.get().sendError( sender, "An exception has occurred. Details have been " + - "logged to the server's console." ); - - // Generally these errors are major and require program fixes, so throw - // the exception so the stacklist is logged. + nanosEnd = System.nanoTime(); + + long nanosDuration = nanosEnd - nanosStart; + this.usageRunTimeNanos += nanosDuration; + + if (e.getCause() instanceof CommandError) { + + CommandError ce = (CommandError) e.getCause(); + Output.get().sendError(sender, ce.getColorizedMessage()); + if (ce.showUsage()) { + sender.sendMessage(getUsage()); + } + } + else { + StringBuilder sb = new StringBuilder(); + + for ( Object arg : resultArgs ) { + sb.append( "[" ); + sb.append( arg.toString() ); + sb.append( "] " ); + } + + String message = "RegisteredCommand.executeMethod(): Invoke error: [" + + e.getMessage() + "] cause: [" + + (e.getCause() == null ? "" : e.getCause().getMessage()) + "] " + + " target instance: [methodName= " + + method.getName() + " parmCnt=" + method.getParameterCount() + " methodInstance=" + + getMethodInstance().getClass().getCanonicalName() + "] " + + "command arguments: " + sb.toString() + ; + + // Warning: if the args contains a % then the following sendError will fail because + // the % will be treated as String.format() placeholders. So to be safe and + // to prevent this failure, escape all % with a double % such as %%. + message = message.replace( "%", "%%" ); + + Output.get().logError( message ); + + Output.get().sendError( sender, "An exception has occurred. Details have been " + + "logged to the server's console." ); + + // Generally these errors are major and require program fixes, so throw + // the exception so the stacklist is logged. throw e; } } @@ -419,20 +464,17 @@ public boolean isSet() { return set; } -// public boolean onlyPlayers() { -// return onlyPlayers; -// } - public void sendHelpMessage(CommandSender sender) { - ChatDisplay chatDisp = getHelpMessage( sender ); - - if ( chatDisp != null ) { - chatDisp.send( sender ); - } + ChatDisplay chatDisp = getHelpMessage( sender ); + + if ( chatDisp != null ) { + chatDisp.send( sender ); + } } void set(Object methodInstance, Method method) { + this.methodInstance = methodInstance; this.method = method; method.setAccessible(true); @@ -442,11 +484,9 @@ void set(Object methodInstance, Method method) { this.permissions = command.permissions(); this.altPermissions = command.altPermissions(); - String[] aliases = CommandHandler.addConfigAliases( command.identifier(), command.aliases() ); - //addConfigAliases( command.identifier(), command.aliases() ); + String[] aliases = CommandHandler.addConfigAliases( command.identifier(), command.aliases() ); this.aliases = aliases; -// this.aliases = command.aliases(); this.docURLs = command.docURLs(); this.onlyPlayers = command.onlyPlayers(); @@ -568,33 +608,6 @@ void set(Object methodInstance, Method method) { } -// private String[] addConfigAliases( String label, String[] aliases ) -// { -// String[] results = aliases; -// -// String configKey = "prisonCommandHandler.aliases." + label.replace( " ", "." ); -// -// List ca = Prison.get().getPlatform().getConfigStringArray( configKey ); -// if ( ca != null && ca.size() > 0 && ca.get( 0 ) instanceof String ) { -// -// List configAliases = new ArrayList<>(); -// -// for ( String alias : aliases ) { -// configAliases.add( alias ); -// } -// -// for ( Object aliasObj : ca ) { -// if ( aliasObj instanceof String ) { -// configAliases.add( aliasObj.toString() ); -// } -// } -// -// results = configAliases.toArray( new String[0] ); -// -// } -// return results; -// } - public boolean testPermission(CommandSender sender) { if (!set) { return true; @@ -615,11 +628,21 @@ public void incrementUsageCount() { usageCount++; } public int getUsageCount() { - return usageCount; + return usageCount; } public void setUsageCount(int usageCount) { this.usageCount = usageCount; } + + public void incrementUsageCountAlias() { + usageCountAlias++; + } + public int getUsageCountAlias() { + return usageCountAlias; + } + public void setUsageCountAlilas(int usageCountAlias) { + this.usageCountAlias = usageCountAlias; + } public long getUsageRunTimeNanos() { return usageRunTimeNanos; diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/TabCompleaterData.java b/prison-core/src/main/java/tech/mcprison/prison/commands/TabCompleaterData.java index ea32b10e2..fdb05382a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/TabCompleaterData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/TabCompleaterData.java @@ -74,11 +74,6 @@ private void addCommand( RegisteredCommand registeredCommand, String... usage ) getData().put( key, tcd ); } -// else { -// TabCompleaterData tcd = getData().get( key ); -// tcd.addCommand( registeredCommand, subArray ); -// } - TabCompleaterData tcd = getData().get( key ); tcd.addCommand( registeredCommand, subArray ); @@ -112,20 +107,6 @@ public void add( RegisteredCommand registeredCommand ) { addCommand( registeredCommand, usage ); -// if ( usage.length > 0 ) { -// String key = usage[0]; -// -// String[] subArray = Arrays.copyOfRange( usage, 1, usage.length ); -// -// if ( !getData().containsKey( key ) ) { -// TabCompleterData tcd = new TabCompleterData( key, subArray ); -// getData().put( key, tcd ); -// } -// else { -// getData().get( key ).add( subArray ); -// } -// } - } /** @@ -181,9 +162,7 @@ private List checkLabel( CommandSender commandSender, String label, Stri } } - else if ( args.length > 1 -// || args.length == 1 && getData().containsKey( args[0] ) - ) { + else if ( args.length > 1 ) { // if length is greater than 1 then that means that we need to // traverse to the next level of depth if we have a hit for diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/Wildcard.java b/prison-core/src/main/java/tech/mcprison/prison/commands/Wildcard.java index 5043aa39f..036115799 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/Wildcard.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/Wildcard.java @@ -23,7 +23,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface Wildcard { +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface Wildcard { boolean join() default true; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/BlockArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/BlockArgumentHandler.java index ef7908ea1..0ed3554ad 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/BlockArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/BlockArgumentHandler.java @@ -25,9 +25,11 @@ import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.block.PrisonBlock; -public class BlockArgumentHandler extends ArgumentHandler { +public class BlockArgumentHandler + extends ArgumentHandler { public BlockArgumentHandler() { + } @Override @@ -36,50 +38,13 @@ public PrisonBlock transform(CommandSender sender, CommandArgument argument, Str PrisonBlock b = null; if ( value != null ) { - b = new PrisonBlock( value ); - - if ( b != null ) { - return b; - } + b = new PrisonBlock( value ); + + if ( b != null ) { + return b; + } } -// // Try block legacy (numerical) ID first -// try { -// m = BlockType.getBlock(Integer.parseInt(value)); -// } catch (NumberFormatException ignored) { -// } -// -// if (m != null) { -// return m; -// } -// -// // Now try new block IDs -// -// m = BlockType.getBlock(value); -// -// if (m != null) { -// return m; -// } -// -// // Now try id:data format -// if (value.contains(":")) { -// int id; -// short data; -// try { -// id = Integer.parseInt(value.split(":")[0]); -// data = Short.parseShort(value.split(":")[1]); -// } catch (NumberFormatException ignored) { -// throw new TransformError( -// Prison.get().getLocaleManager().getLocalizable("blockParseError") -// .withReplacements(value).localizeFor(sender)); -// } -// m = BlockType.getBlockWithData(id, data); -// } -// -// if (m != null) { -// return m; -// } - // No more checks, just fail throw new TransformError(Prison.get().getLocaleManager().getLocalizable("blockParseError") diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleArgumentHandler.java index 5728a17f1..d92eb0e61 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleArgumentHandler.java @@ -23,9 +23,11 @@ import tech.mcprison.prison.commands.TransformError; import tech.mcprison.prison.internal.CommandSender; -public class DoubleArgumentHandler extends NumberArgumentHandler { +public class DoubleArgumentHandler + extends NumberArgumentHandler { public DoubleArgumentHandler() { + super(); } @Override @@ -33,9 +35,6 @@ public Double transform(CommandSender sender, CommandArgument argument, String v throws TransformError { value = value.replaceAll( "$|%", "" ); try { -// if ( value == null || value.trim().length() == 0 ) { -// return null; -// } return Double.parseDouble(value); } catch (NumberFormatException e) { throw new TransformError( diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleClassArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleClassArgumentHandler.java index 2842f043a..6034358e6 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleClassArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/DoubleClassArgumentHandler.java @@ -5,30 +5,32 @@ import tech.mcprison.prison.commands.TransformError; import tech.mcprison.prison.internal.CommandSender; -public class DoubleClassArgumentHandler extends NumberArgumentHandler { +public class DoubleClassArgumentHandler + extends NumberArgumentHandler { public DoubleClassArgumentHandler() { + super(); } @Override public Double transform(CommandSender sender, CommandArgument argument, String value) throws TransformError { - Double results = null; - - if ( value != null ) { - - value = value.replaceAll( "$|%", "" ); - if ( value.trim().length() > 0 ) { - try { - results = Double.parseDouble(value); - } catch (NumberFormatException e) { - throw new TransformError( - Prison.get().getLocaleManager().getLocalizable("numberParseError") - .withReplacements(value).localizeFor(sender)); - } - } - } - return results; + Double results = null; + + if ( value != null ) { + + value = value.replaceAll( "$|%", "" ); + if ( value.trim().length() > 0 ) { + try { + results = Double.parseDouble(value); + } catch (NumberFormatException e) { + throw new TransformError( + Prison.get().getLocaleManager().getLocalizable("numberParseError") + .withReplacements(value).localizeFor(sender)); + } + } + } + return results; } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerArgumentHandler.java index 4118d2af0..1ecc2b20a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerArgumentHandler.java @@ -27,15 +27,16 @@ public class IntegerArgumentHandler extends NumberArgumentHandler { public IntegerArgumentHandler() { + super(); } @Override public Integer transform(CommandSender sender, CommandArgument argument, String value) throws TransformError { - if ( value != null ) { - value = value.replaceAll( "$|%", "" ); - } + if ( value != null ) { + value = value.replaceAll( "$|%", "" ); + } try { return Integer.parseInt(value); diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerClassArgumentandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerClassArgumentandler.java index f7e31ac49..177eb1cd2 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerClassArgumentandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/IntegerClassArgumentandler.java @@ -8,29 +8,29 @@ public class IntegerClassArgumentandler extends NumberArgumentHandler { - public IntegerClassArgumentandler() { + super(); } - @Override public Integer transform(CommandSender sender, CommandArgument argument, String value) + @Override + public Integer transform(CommandSender sender, CommandArgument argument, String value) throws TransformError { - Integer results = null; - - if ( value != null ) { - - value = value.replaceAll( "$|%", "" ); - - //value = value.replaceAll("$|%", ""); - if ( value.trim().length() > 0 ) { - try { - results = Integer.parseInt(value); - } catch (NumberFormatException e) { - throw new TransformError( - Prison.get().getLocaleManager().getLocalizable("numberParseError") - .withReplacements(value).localizeFor(sender)); - } - } - } - return results; + Integer results = null; + + if ( value != null ) { + + value = value.replaceAll( "$|%", "" ); + + if ( value.trim().length() > 0 ) { + try { + results = Integer.parseInt(value); + } catch (NumberFormatException e) { + throw new TransformError( + Prison.get().getLocaleManager().getLocalizable("numberParseError") + .withReplacements(value).localizeFor(sender)); + } + } + } + return results; } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongArgumentHandler.java index e10fb6905..3816d18a3 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongArgumentHandler.java @@ -9,15 +9,16 @@ public class LongArgumentHandler extends NumberArgumentHandler { public LongArgumentHandler() { + super(); } @Override public Long transform(CommandSender sender, CommandArgument argument, String value) throws TransformError { - if ( value != null ) { - value = value.replaceAll( "$|%", "" ); - } + if ( value != null ) { + value = value.replaceAll( "$|%", "" ); + } try { return Long.parseLong(value); diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongClassArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongClassArgumentHandler.java index 665e24653..07e885e1a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongClassArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/LongClassArgumentHandler.java @@ -9,28 +9,28 @@ public class LongClassArgumentHandler extends NumberArgumentHandler { public LongClassArgumentHandler() { + super(); } @Override public Long transform(CommandSender sender, CommandArgument argument, String value) throws TransformError { - Long results = null; - - if ( value != null ) { - - value = value.replaceAll( "$|%", "" ); - - try { - results = Long.parseLong(value); - } catch (NumberFormatException e) { - throw new TransformError( - Prison.get().getLocaleManager().getLocalizable("numberParseError") - .withReplacements(value).localizeFor(sender)); - } - } + Long results = null; + + if ( value != null ) { + + value = value.replaceAll( "$|%", "" ); + + try { + results = Long.parseLong(value); + } catch (NumberFormatException e) { + throw new TransformError( + Prison.get().getLocaleManager().getLocalizable("numberParseError") + .withReplacements(value).localizeFor(sender)); + } + } return results; } - } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/NumberArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/NumberArgumentHandler.java index 3c8e2fa58..d56e900d9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/NumberArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/NumberArgumentHandler.java @@ -23,9 +23,12 @@ import tech.mcprison.prison.commands.VerifyError; import tech.mcprison.prison.internal.CommandSender; -public abstract class NumberArgumentHandler extends ArgumentHandler { +public abstract class NumberArgumentHandler + extends ArgumentHandler { public NumberArgumentHandler() { + super(); + addVerifier("min", new ArgumentVerifier() { @Override public void verify(CommandSender sender, CommandArgument argument, String verifyName, diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/PlayerArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/PlayerArgumentHandler.java index 7b1976313..139dee602 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/PlayerArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/PlayerArgumentHandler.java @@ -41,7 +41,8 @@ public Player var(CommandSender sender, CommandArgument argument, String varName }); } - @Override public Player transform(CommandSender sender, CommandArgument argument, String value) + @Override + public Player transform(CommandSender sender, CommandArgument argument, String value) throws TransformError { return Prison.get().getPlatform().getPlayer(value).orElseThrow(() -> new TransformError( diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/StringArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/StringArgumentHandler.java index acce7abe3..adab3b177 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/StringArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/StringArgumentHandler.java @@ -71,12 +71,13 @@ public void verify(CommandSender sender, CommandArgument argument, String verify }); } - @Override public String transform(CommandSender sender, CommandArgument argument, String value) + @Override + public String transform(CommandSender sender, CommandArgument argument, String value) throws TransformError { - if ( value != null ) { - value = value.replaceAll( "$|%", "" ); - } + if ( value != null ) { + value = value.replaceAll( "$|%", "" ); + } return value; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/WorldArgumentHandler.java b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/WorldArgumentHandler.java index ac3cec1b3..3cec63e95 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/WorldArgumentHandler.java +++ b/prison-core/src/main/java/tech/mcprison/prison/commands/handlers/WorldArgumentHandler.java @@ -42,7 +42,8 @@ public World var(CommandSender sender, CommandArgument argument, String varName) }); } - @Override public World transform(CommandSender sender, CommandArgument argument, String value) + @Override + public World transform(CommandSender sender, CommandArgument argument, String value) throws TransformError { return Prison.get().getPlatform().getWorld(value).orElseThrow(() -> new TransformError( Prison.get().getLocaleManager().getLocalizable("worldNotFound").withReplacements(value) diff --git a/prison-core/src/main/java/tech/mcprison/prison/discord/DiscordWebhook.java b/prison-core/src/main/java/tech/mcprison/prison/discord/DiscordWebhook.java index 09203dfb6..14c4ddb22 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/discord/DiscordWebhook.java +++ b/prison-core/src/main/java/tech/mcprison/prison/discord/DiscordWebhook.java @@ -14,9 +14,6 @@ import javax.net.ssl.HttpsURLConnection; -import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.output.Output.DebugTarget; - /** * * This class is based upon the github gist of k3kdude: diff --git a/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonDiscordWebhook.java b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonDiscordWebhook.java index 66b4b40ec..ad83bf78f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonDiscordWebhook.java +++ b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonDiscordWebhook.java @@ -11,7 +11,6 @@ import tech.mcprison.prison.discord.DiscordWebhook.EmbedObject; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.output.Output.DebugTarget; import tech.mcprison.prison.util.Text; /** @@ -64,6 +63,7 @@ public boolean setup() { return results; } + @SuppressWarnings("unused") public void send( CommandSender sender, String title, String message, boolean addPrisonStats ) { int totalSize = 0; @@ -76,7 +76,7 @@ public void send( CommandSender sender, String title, String message, boolean ad if ( addPrisonStats ) { - totalSize += addPrisonStats( title, webhook ); + totalSize += addPrisonStats( title, webhook ); } 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 dff4b7092..50f64e4c0 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 @@ -356,8 +356,6 @@ private String postPasteHelpchAt( String text, boolean raw ) if ( rawJson != null ) { - //Output.get().logInfo( "### rawJson : " + rawJson ); - // ### rawJson : {"key":"utozikecag"} Gson gson = new Gson(); JsonObject object = gson.fromJson( rawJson, JsonObject.class ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportFileLinkage.java b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportFileLinkage.java new file mode 100644 index 000000000..15cf2b059 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportFileLinkage.java @@ -0,0 +1,141 @@ +package tech.mcprison.prison.discord; + +import java.util.TreeMap; +import java.util.TreeSet; + +import tech.mcprison.prison.output.Output; + +public class PrisonSupportFileLinkage { + + public static final String LINKAGE_IDENTIFIER = "||"; + + private TreeMap> primaries = new TreeMap<>(); + + public enum PrimaryLinkages { + Ladder, + Rank, + Mine, + Listeners, + CommandStats, + + unknown + ; + + /** + *

This will take a raw linkage String, minus the + * pipes, and extract a PrimaryLinkages from it. + * + * + * @param linkage + * @return + */ + public static PrimaryLinkages fromString( String linkage ) { + PrimaryLinkages results = PrimaryLinkages.unknown; + + if ( linkage.contains( " " ) ) { + String[] parts = linkage.split(" "); + if ( parts != null && parts.length > 0 ) { + linkage = parts[0]; + } + } + + for ( PrimaryLinkages pl : values() ) { + if ( pl.name().equalsIgnoreCase(linkage) ) { + results = pl; + break; + } + } + + return results; + } + + + public void scanForTOCEntries( String line ) { + + if ( line != null && line.startsWith( LINKAGE_IDENTIFIER ) ) { + String[] parts = line.split(" "); + + PrimaryLinkages prime = PrimaryLinkages.fromString( parts[0] ); + if ( prime != PrimaryLinkages.unknown ) { + + } + else { + String msg = "Primary ID not setup for PrimaryLinkage: [" + line + "]"; + Output.get().logWarn(msg); + } + } + } + + } + + public enum SecondaryLinkages { + toc, + listing, + listingDetail, + detail, + config, + file; + + public static SecondaryLinkages fromString( String secondary ) { + SecondaryLinkages results = null; + + if ( secondary != null ) { + + for ( SecondaryLinkages scnd : values() ) { + if ( secondary.toLowerCase().contains( scnd.name().toLowerCase() ) ) { + results = scnd; + break; + } + } + } + + return results; + } + } + + private void addPrimaries( PrimaryLinkages pLink, String value ) { + if ( pLink != null && pLink != PrimaryLinkages.unknown && value != null ) { + + if ( !getPrimaries().containsKey(pLink) ) { + getPrimaries().put(pLink, new TreeSet<>() ); + } + + TreeSet values = getPrimaries().get( pLink ); + + if ( !values.contains( value ) ) { + values.add( value ); + } + } + } + + public void addLinkage(String line) { + + if ( line != null && line.startsWith( LINKAGE_IDENTIFIER ) ) { + + String[] rawLinks = line.split("\\|\\|"); + + for (String rawLink : rawLinks) { + + if ( rawLink != null && rawLink.length() > 0 ) { + + String[] parts = rawLink.split(" "); + + PrimaryLinkages pLink = PrimaryLinkages.fromString( parts[0] ); + + String value = parts.length >= 2 ? parts[1] : null; + + addPrimaries( pLink, value ); + } + } + } + } + + + public TreeMap> getPrimaries() { + return primaries; + } + public void setPrimaries(TreeMap> primaries) { + this.primaries = primaries; + } + +} 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 index e3bbc920b..5fb6ec2bb 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportFiles.java +++ b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportFiles.java @@ -7,6 +7,8 @@ import java.io.IOException; import java.io.StringReader; import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; import tech.mcprison.prison.Prison; @@ -23,6 +25,8 @@ public class PrisonSupportFiles { private boolean colorMapping = true; + private PrisonSupportFileLinkage linkage; + public enum ColorMaps { black( "&0", "", "" ), DarkBlue( "&1", "", "" ), @@ -81,20 +85,6 @@ public static ColorMaps match( String line ) { 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; @@ -134,21 +124,12 @@ public void saveToSupportFile( StringBuilder text, String supportName ) { } -// 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(); + linkage = new PrisonSupportFileLinkage(); + try ( BufferedWriter bw = new BufferedWriter( new FileWriter( file, false )); // create file ) { @@ -177,7 +158,6 @@ private void appendSaveSupportDataToFile( StringBuilder text ) { bw.write( "\n\n- = - = - = - = - = - = - = - = - = - = -\n\n"); writeBufferedWriter( bw, text ); -// bw.write( text.toString() ); } catch (IOException e) { @@ -208,7 +188,40 @@ private void writeBufferedWriter( BufferedWriter bw, StringBuilder text ) { } } + + + @SuppressWarnings("unused") + private List extractAllHyperlinkPlaceholders( StringBuilder text ) { + + List hlp = new ArrayList<>(); + + try ( + BufferedReader br = new BufferedReader( new StringReader( text.toString() )); + ) { + + String line = br.readLine(); + + while ( line != null ) { + + + if ( line.startsWith( "||`" ) ) { + + linkage.addLinkage( line ); + hlp.add( line ); + } + + line = br.readLine(); + } + + } + catch ( Exception e ) { + + } + + return hlp; + } + protected String convertColorCodes(String line) { StringBuilder sb = new StringBuilder(); @@ -346,13 +359,6 @@ private File createSupportFile( String name ) { 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; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportLinkageData.java b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportLinkageData.java new file mode 100644 index 000000000..348da842e --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/discord/PrisonSupportLinkageData.java @@ -0,0 +1,84 @@ +package tech.mcprison.prison.discord; + +import tech.mcprison.prison.discord.PrisonSupportFileLinkage.PrimaryLinkages; +import tech.mcprison.prison.discord.PrisonSupportFileLinkage.SecondaryLinkages; +/** + *

This may be a work in progress to provide hyperlinked help docs + * that are submitted when admins are needing help with their systems. + *

+ * + */ +public class PrisonSupportLinkageData { + + private String rawLine; + + private PrimaryLinkages primary; + + private SecondaryLinkages secondary; + + private String secondaryText; + + private PrisonSupportLinkageData otherLinkage; + + + public PrisonSupportLinkageData( String line ) { + super(); + + + String rawLine = line.replace(PrisonSupportFileLinkage.LINKAGE_IDENTIFIER, "").trim(); + + this.rawLine = rawLine; + + + PrimaryLinkages primary = PrimaryLinkages.fromString( rawLine ); + this.primary = primary; + + if ( primary != PrimaryLinkages.unknown ) { + + String seconds = rawLine.replace( primary.name(), "" ).trim(); + + SecondaryLinkages secondary = SecondaryLinkages.fromString( seconds ); + this.secondary = secondary; + + String secondaryText = secondary == null ? "" : seconds.replace( secondary.name(), "" ).trim(); + this.secondaryText = secondaryText; + + } + } + + protected String getRawLine() { + return rawLine; + } + protected void setRawLine(String rawLine) { + this.rawLine = rawLine; + } + + protected PrimaryLinkages getPrimary() { + return primary; + } + protected void setPrimary(PrimaryLinkages primary) { + this.primary = primary; + } + + protected SecondaryLinkages getSecondary() { + return secondary; + } + protected void setSecondary(SecondaryLinkages secondary) { + this.secondary = secondary; + } + + protected String getSecondaryText() { + return secondaryText; + } + protected void setSecondaryText(String secondaryText) { + this.secondaryText = secondaryText; + } + + protected PrisonSupportLinkageData getOtherLinkage() { + return otherLinkage; + } + protected void setOtherLinkage(PrisonSupportLinkageData otherLinkage) { + this.otherLinkage = otherLinkage; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileCollection.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileCollection.java index e1323e123..c357950c6 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileCollection.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileCollection.java @@ -1,6 +1,7 @@ package tech.mcprison.prison.file; import java.io.File; +import java.io.FileFilter; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -22,8 +23,8 @@ public class FileCollection private File collDir; public FileCollection(File collDir) { - // This may be within a module. If so then pass these values... - super(null, null); + // This may be within a module. If so then pass these values... + super(null, null); this.collDir = collDir; } @@ -53,66 +54,125 @@ public File getCollDir() { */ @Override public List getAll() { - List allDocs = new ArrayList<>(); - - // Each folder in the root directory is its own database. - // We'll initialize each of them here. - File[] collectionFiles = this.collDir.listFiles((dir, name) -> name.endsWith(".json")); - if (collectionFiles != null) { - for (File dbFile : collectionFiles) { - if ( isDeleted( dbFile ) ) { - String message = "FileCollection.getAll skipping logically deleted FileDocument: " + - dbFile.getAbsolutePath(); - Output.get().logInfo( message ); - } else { - Document doc = (Document) readJsonFile(dbFile, new Document()); - if ( doc != null ) - { - allDocs.add( doc ); - } - } - } - } - - return allDocs; + List allDocs = new ArrayList<>(); + + FileFilter fFilter = JsonFileIO.getPrisonFileFilter(); + + + // Each folder in the root directory is its own database. + // We'll initialize each of them here. + File[] collectionFiles = this.collDir.listFiles( fFilter ); + + if (collectionFiles != null) { + for (File dbFile : collectionFiles) { + if ( isDeleted( dbFile ) ) { + String message = "FileCollection.getAll skipping logically deleted FileDocument: " + + dbFile.getAbsolutePath(); + Output.get().logInfo( message ); + } else { + Document doc = (Document) readJsonFile(dbFile, new Document()); + if ( doc != null ) + { + allDocs.add( doc ); + } + } + } + } + + return allDocs; } @Override public Optional get(String key) { - File dbFile = new File(collDir, key + ".json"); - Document doc = (Document) readJsonFile(dbFile, new Document()); + + File dbFile = getFile(key); + Document doc = (Document) readJsonFile(dbFile, new Document()); return Optional.ofNullable(doc); } - @Override - public void save(Document document) - { - save((String)document.get("name"), document); - } - - @Override - public void save(String filename, Document document) - { - File dbFile = new File(collDir, filename + ".json"); - saveJsonFile( dbFile, document ); - } + + @Override + public void save(String filename, Document document, + String oldFilename, String fileType ) { + + File dbFile = getFile(filename); + saveJsonFile( dbFile, document ); + + if ( oldFilename != null ) { + + // Since the new file should have been saved by now... + File oldDbFile = getFile(oldFilename); + + // If both the new file and old file exists, then need to remove the old file: + if ( dbFile.exists() && dbFile.length() > 0 && oldDbFile.exists() ) { + + boolean deleted = oldDbFile.delete(); + + if ( deleted ) { + + Output.get().logInfo( + "&3%s File Converted: &7%s &3--> &7%s", + fileType, + oldFilename + FILE_SUFFIX_JSON, + filename + FILE_SUFFIX_JSON + ); + } + else { + Output.get().logInfo( + "&3The old %s file could not be removed: " + + "Old file &7%s &3. " + + "Reason unknown (check logs?). " + + "New file name &7%s. [%s]", + fileType, + oldFilename + FILE_SUFFIX_JSON, + filename + FILE_SUFFIX_JSON, + oldDbFile.getAbsolutePath() + ); + + } + } + } + } + + private File getFile(String name) + { + String suffix = name.endsWith(FILE_SUFFIX_JSON) ? "" : FILE_SUFFIX_JSON; + File dbFile = new File(collDir, name + suffix); + return dbFile; + } + + @Override + public boolean exists(String name) + { + boolean results = false; + + if ( name != null && name.trim().length() > 0 ) { + + File dbFile = getFile(name); + results = dbFile.exists(); + } + + return results; + } + @Override public boolean delete(String name) { - File dbFile = new File(collDir, name + ".json"); - return virtualDelete( dbFile ); + File dbFile = getFile(name); + return dbFile.exists() ? virtualDelete( dbFile ) : false; } @Override public File backup( String name ) { - File dbFile = new File(collDir, name + ".json"); - File backupFile = virtualBackup( dbFile ); - - return backupFile; + File dbFile = getFile(name); + File backupFile = dbFile.exists() ? virtualBackup( dbFile ) : null; + + return backupFile; } + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileDatabase.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileDatabase.java index 93485f5b4..6daa4d816 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileDatabase.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileDatabase.java @@ -39,22 +39,22 @@ public File getDbDir() { *

*/ public void refresh() { - collectionMap.clear(); - - // Each folder in the db directory is its own collection. - // We'll initialize each of them here. - File[] collectionDirs = dbDir.listFiles(File::isDirectory); - if (collectionDirs != null) { - for (File collDir : collectionDirs) { - if ( isDeleted( collDir ) ) { - String message = "FileDatabase.refresh skipping logically deleted FileCollection: " + - collDir.getAbsolutePath(); - Output.get().logInfo( message ); - } else { - collectionMap.put(collDir.getName(), new FileCollection(collDir)); - } - } - } + collectionMap.clear(); + + // Each folder in the db directory is its own collection. + // We'll initialize each of them here. + File[] collectionDirs = dbDir.listFiles(File::isDirectory); + if (collectionDirs != null) { + for (File collDir : collectionDirs) { + if ( isDeleted( collDir ) ) { + String message = "FileDatabase.refresh skipping logically deleted FileCollection: " + + collDir.getAbsolutePath(); + Output.get().logInfo( message ); + } else { + collectionMap.put(collDir.getName(), new FileCollection(collDir)); + } + } + } } @@ -67,24 +67,25 @@ public void refresh() { @Override public Optional getCollection(String name) { - Collection results = collectionMap.get(name); - - if ( results == null ) - { - // try to create the FileCollection: - createCollection(name); - results = collectionMap.get(name); - } - + Collection results = collectionMap.get(name); + + if ( results == null ) + { + // try to create the FileCollection: + createCollection(name); + results = collectionMap.get(name); + } + return Optional.ofNullable(results); } /** *

This function will create a new FileCollection on the file system (a directory). - * It will generate the new directory with the provided name. If there is already - * a directory by that name, then this function will fail and it will log a - * warning. If successful, then it will add a File entry Collection to the - * collectionMap. + * It will generate the new directory with the provided name, and all parents. + * If successful, then it will add a File entry Collection to the collectionMap. + *

+ * + *

If the directory already exists, then all is good (return true) and move on. *

* * @param name @@ -92,17 +93,17 @@ public Optional getCollection(String name) */ @Override public boolean createCollection(String name) { - boolean results = false; + boolean results = false; File collDir = new File(dbDir, name); if (!collDir.exists()) { - results = collDir.mkdir(); - collectionMap.put(name, new FileCollection(collDir)); - } else { - String message = "The attempt to create a new FileCollection named " + name + - " failed because a directory on the file system already exists by that name."; - Output.get().logWarn( message ); + results = collDir.mkdirs(); + } + else { + // the directory already exist... who cares? Let's use it: + results = true; } + collectionMap.put(name, new FileCollection(collDir)); return results; } @@ -131,24 +132,21 @@ public boolean createCollection(String name) { */ @Override public boolean deleteCollection(String name) { - boolean results = false; + boolean results = false; File collDir = new File(dbDir, name); Collection coll = collectionMap.get(name); if (collDir.exists() && coll != null) { - // Perform a logical delete on the collection so it can be manually recovered if this is an error: - virtualDelete( collDir ); - - // This dispose just removes the entries from the collection and deletes nothing from the file system: - //coll.dispose(); - //results = collDir.delete(); - collectionMap.remove(name); - results = true; + // Perform a logical delete on the collection so it can be manually recovered if this is an error: + virtualDelete( collDir ); + + collectionMap.remove(name); + results = true; } else { - String message = "The attempt to delete a FileCollection named " + name + - " failed because either the directory does not exist or it was not in the collectionMap."; - Output.get().logWarn( message ); + String message = "The attempt to delete a FileCollection named " + name + + " failed because either the directory does not exist or it was not in the collectionMap."; + Output.get().logWarn( message ); } return results; diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java index 3975f1b0c..063af2332 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileIO.java @@ -1,11 +1,13 @@ package tech.mcprison.prison.file; import java.io.File; +import java.io.FileFilter; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardOpenOption; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -13,6 +15,7 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.error.Error; import tech.mcprison.prison.error.ErrorManager; +import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.modules.ModuleStatus; import tech.mcprison.prison.output.Output; @@ -20,6 +23,17 @@ public abstract class FileIO extends FileVirtualDelete { + public static final String FILE_SUFFIX_JSON = ".json"; + public static final String FILE_PREFIX_BACKUP = ".backup_"; + public static final String FILE_SUFFIX_BACKUP = ".bu"; + public static final String FILE_SUFFIX_TEMP = ".temp"; + public static final String FILE_SUFFIX_TXT = ".txt"; + public static final String FILE_TIMESTAMP_FORMAT = "_yyyy-MM-dd_HH-mm-ss"; + + public static final String PLAYER_PATH = "data_storage/ranksDb/players/"; + public static final String CACHE_PATH = "data_storage/playerCache/"; + + private final SimpleDateFormat sdf; private final ErrorManager errorManager; @@ -83,8 +97,6 @@ protected void saveFile( File file, String data ) if ( file != null && data != null ) { File tempFile = getTempFile( file ); -// String tempFileName = file.getName() + "." + getTimestampFormat() + ".tmp"; -// File tempFile = new File(file.getParentFile(), tempFileName); boolean disableAdvancedSaves = Prison.get().getPlatform().getConfigBooleanFalse( @@ -102,8 +114,6 @@ protected void saveFile( File file, String data ) // Write as an UTF-8 stream: Files.write( tempFile.toPath(), lines, StandardCharsets.UTF_8 ); -// Files.write( tempFile.toPath(), data.getBytes() ); - // If original target exists, then delete it: if ( file.exists() ) { @@ -146,17 +156,6 @@ protected void saveFile( File file, String data ) Files.write( file.toPath(), lines, StandardCharsets.UTF_8, sooW, sooTe ); -// Files.write( tempFile.toPath(), data.getBytes() ); - - // If original target exists, then delete it: -// if ( file.exists() ) -// { -// file.delete(); -// } -// -// tempFile.renameTo( file ); - - if ( !keepTempFiles ) { tempFile.delete(); } @@ -175,7 +174,6 @@ protected void saveFile( File file, String data ) protected String readFile( File file ) { StringBuilder results = new StringBuilder(); -// String results = null; if ( file.exists() ) { @@ -186,9 +184,6 @@ protected String readFile( File file ) for ( String line : lines ) { results.append( line ).append( "\n" ); } - -// byte[] bytes = Files.readAllBytes( file.toPath() ); -// results = new String(bytes); } catch ( IOException e ) { @@ -219,6 +214,293 @@ private void logException( String description, File file, IOException e ) } } + + /** + *

This function generate a partial user file name. This is based upon + * the UUID-fragment (first and last parts of the player UUID), + * plus the player's name, and the file suffix, which is '.json'. + * This function does not add any prefix such as 'player_' or + * 'cache_'. + *

+ * + * @param player + * @return + */ + private static String getPlayerFileNameNewVersion( Player player ) { + + String uuidFragment = getFileNamePrefixNew( player ); + + return uuidFragment + "_" + player.getName() + FILE_SUFFIX_JSON; + } + + /** + *

This generates the fragment UUID that is used within file names. + * This is based upon the first 8 UUID digits, plus the hyphen. Followed + * by the last segment of the UUID, which starts at character 25. + *

+ * + *

This uses the start and end of the UUID because bedrock players + * only have zeros for the first part of the UUID, so the ending must + * be included too. + *

+ * + *

Examples: + *

+ * '22cacd8c-d0ff-4dd7-a8ba-2a6a8b46be92' + * '' + * + * @param player + * @return + */ + private static String getFileNamePrefixNew( Player player ) { + String uuid = player.getUUID().toString(); + return uuid.substring( 0, 9 ) + + uuid.substring( 25 ); + } + + /** + *

This function extracts the UUID fragment from player file names. + *

+ * + * @param filename + * @return + */ + public static String getFileNameUUIDFragment( String filename ) { + String uuid = null; + + if ( filename != null && filename.trim().length() > 0 ) { + + String uuidTmp = filename.replace("cache_", "").replace("player_", ""); + + uuid = uuidTmp.indexOf("_") > 0 ? + uuidTmp.substring(0, uuidTmp.indexOf("_")) + : uuidTmp; + } + return uuid; + } + + + public String filenamePrefix( String filename, String prefixDeliminator ) { + int idx = filename.lastIndexOf( prefixDeliminator ) + 1; + String prefix = idx > 0 ? filename.substring(0, idx) : null; + return prefix; + } + + /** + * Using the path and file name, this will check to see if any files + * preexist with the given file prefix so if the player changes their + * name, it will still load the correct file. + * + * If no file is found, then it will crate a new File object based + * upon the path and filename. + * + * If existing file are found, there should only be at most one, but + * if there is more than one, then use the first one. + * + * @param path + * @param filename + * @return + */ + public File checkFile( File path, String filename, String prefixDeliminator ) { + + String prefix = filenamePrefix( filename, prefixDeliminator ); + + List files = getFilesFromPrefix( prefix, path ); + + return files.size() > 0 ? files.get(0) : new File( path, filename ); + } + + public static File filePlayer( Player player ) { + FileIO fIO = new FileIO() {}; + return fIO.checkFiles( filenamePlayerNew( player ), filenamePlayerOld( player ), PLAYER_PATH ); + } + + public static File fileCache( Player player ) { + FileIO fIO = new FileIO() {}; + return fIO.checkFiles( filenameCacheNew( player ), filenameCacheOld( player ), CACHE_PATH ); + } + + private File checkFiles( String newFileName, String oldFileName, String pathName ) + { + File results = null; + + File path = new File( Prison.get().getDataFolder(), pathName ); + + File newPlayerFile = checkFile( path, newFileName, "_" ); + + if ( newPlayerFile.exists() ) { + results = newPlayerFile; + } + else { + File oldPlayerFile = checkFile( path, oldFileName, "." ); + + if ( oldPlayerFile.exists() ) { + results = oldPlayerFile; + } + } + + if ( results == null ) { + // Did not find a new format file, or an old file format, so use the new format: + results = newPlayerFile; + } + + // If the file chosen is not equal to the newFileName, then rename it: + else if ( !newFileName.equals(results.getName()) ) { + File newFile = new File( path, newFileName ); + results.renameTo(newFile); + + // Rename does not change the original file path in results so have to reassign it: + results = newFile; + } + + return results; + } + + + /** + * Do not use. Use 'filenameCache( player )'. + * + * @param player + * @return + */ + public static String filenameCacheNew( Player player ) { + + return "cache_" + getPlayerFileNameNewVersion( player ); + } + /** + * Do not use. Use 'filenameCache( player )'. + * + * @param player + * @return + */ + public static String filenameCacheOld( Player player ) { + + return getPlayerFileNameShortVersion( player ); + } + + /** + * Do not use. Use 'filenamePlayer( player )'. + * + * @param player + * @return + */ + public static String filenamePlayerNew( Player player ) + { + return "player_" + getPlayerFileNameNewVersion( player ); + } + /** + * Do not use. Use 'filenamePlayer( player )'. + * + * @param player + * @return + */ + public static String filenamePlayerOld( Player player ) + { + return "player_" + player.getUUID().getLeastSignificantBits() + FILE_SUFFIX_JSON; + } + + + /** + *

Do not use. This version is not compatible with bedrock players + * because all bedrock UUIDs are just zeros when using this formmat. + * The newer format also includes the trailing + * + *

This constructs a player file named based upon the UUID followed + * by the player's name. This format is used so it's easier to identify + * the correct player. + *

+ * + *

The format should be UUID-PlayerName.json. The UUID is a shortened + * format, which should still produce a unique id. The name, when read, + * is based upon the UUID and not the player's name, which may change. + * This format includes the player's name to make it easier to identify + * who's record is whom's. + *

+ * + * @return + */ + @Deprecated + public static String getPlayerFileNameShortVersion( Player player ) { + + String UUIDString = player.getUUID().toString(); + String uuidFragment = getFileNamePrefixObsolete( UUIDString ); + + return uuidFragment + "_" + player.getName() + FILE_SUFFIX_JSON; + } + + /** + *

Do not use. This does not support bedrock players because + * the prefix of bedrock UUIDs is all zeros. + *

+ * + *

This function returns the first 13 characters of the supplied + * file name, or UUID String. The hyphen is around the 12 or 13th position, + * so it may or may not include it. + *

+ * + * @param playerFileName + * @return + */ + @Deprecated + private static String getFileNamePrefixObsolete( String UUIDString ) { + return UUIDString.substring( 0, 14 ); + } + + + public List getFilesFromPrefix( String filePrefix, File path ) { + List results = new ArrayList<>(); + + FileFilter fFilter = getFilePrefixFilter( filePrefix ); + + + File[] collectionFiles = path.listFiles( fFilter ); + if ( collectionFiles != null ) { + + for (File file : collectionFiles ) { + results.add(file); + } + } + + return results; + } + + + public FileFilter getFilePrefixFilter( String filePrefix ) { + + FileFilter fileFilter = (file) -> { + + String fname = file.getName(); + boolean isTemp = fname.startsWith( FILE_PREFIX_BACKUP ) || + fname.endsWith( FILE_SUFFIX_BACKUP ) || + fname.endsWith( FILE_SUFFIX_TEMP ) || + fname.endsWith( FILE_SUFFIX_TXT ); + + return + fname.toLowerCase().startsWith( filePrefix.toLowerCase() ) && + !file.isDirectory() && !isTemp && + fname.endsWith( FILE_SUFFIX_JSON ); + }; + + return fileFilter; + } + + public static FileFilter getPrisonFileFilter() { + + FileFilter fileFilter = (file) -> { + + String fname = file.getName(); + boolean isTemp = fname.startsWith( FILE_PREFIX_BACKUP ) || + fname.endsWith( FILE_SUFFIX_BACKUP ) || + fname.endsWith( FILE_SUFFIX_TEMP ) || + fname.endsWith( FILE_SUFFIX_TXT ); + + return !file.isDirectory() && !isTemp && + fname.endsWith( FILE_SUFFIX_JSON ); + }; + + return fileFilter; + } + private String getTimestampFormat() { return sdf.format( new Date() ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileStorage.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileStorage.java index 52ee63ea9..bdfde2b81 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileStorage.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileStorage.java @@ -47,23 +47,23 @@ public FileStorage(File rootDir) { *

*/ public void refresh() { - databaseMap.clear(); - - // Each folder in the root directory is its own database. - // We'll initialize each of them here. - File[] databaseFiles = this.rootDir.listFiles(File::isDirectory); - if (databaseFiles != null) { - for (File dbFile : databaseFiles) { - if ( isDeleted( dbFile ) ) { - String message = "FileStorage.refresh skipping logically deleted FileDatabase: " + - dbFile.getAbsolutePath(); - Output.get().logInfo( message ); - } else { - databaseMap.put(dbFile.getName(), new FileDatabase(dbFile)); - - } - } - } + databaseMap.clear(); + + // Each folder in the root directory is its own database. + // We'll initialize each of them here. + File[] databaseFiles = this.rootDir.listFiles(File::isDirectory); + if (databaseFiles != null) { + for (File dbFile : databaseFiles) { + if ( isDeleted( dbFile ) ) { + String message = "FileStorage.refresh skipping logically deleted FileDatabase: " + + dbFile.getAbsolutePath(); + Output.get().logInfo( message ); + } else { + databaseMap.put(dbFile.getName(), new FileDatabase(dbFile)); + + } + } + } } @@ -86,24 +86,22 @@ public boolean isConnected() { */ @Override public Optional getDatabase(String name) { - Database results = databaseMap.get(name); - - if ( results == null ) - { - // try to create the FileDatabase: - createDatabase(name); - results = databaseMap.get(name); - } - + Database results = databaseMap.get(name); + + if ( results == null ) + { + // try to create the FileDatabase: + createDatabase(name); + results = databaseMap.get(name); + } + return Optional.ofNullable(results); } /** *

This function will create a new FileDatabase on the file system (a directory). - * It will generate the new directory with the provided name. If there is already - * a directory by that name, then this function will fail and it will log a - * warning. If successful, then it will add a FileDatabase entry to the - * databaseMap. + * It will generate the new directory with the provided name. + * If successful, then it will add a FileDatabase entry to the databaseMap. *

* * @param name @@ -111,17 +109,18 @@ public Optional getDatabase(String name) { */ @Override public boolean createDatabase(String name) { - boolean results = false; + boolean results = false; File directory = new File(rootDir, name); if (!directory.exists()) { - results = directory.mkdir(); - databaseMap.put(name, new FileDatabase(directory)); - } else { - String message = "The attempt to create a new FileDatabase named " + name + - " failed because a directory on the file system already exists by that name."; - Output.get().logWarn( message ); + results = directory.mkdirs(); + } + else { + // directory already exists, so use it: + results = true; } + databaseMap.put(name, new FileDatabase(directory)); + return results; } @@ -149,24 +148,24 @@ public boolean createDatabase(String name) { */ @Override public boolean deleteDatabase(String name) { - boolean results = false; + boolean results = false; File directory = new File(rootDir, name); Database db = databaseMap.get(name); if (directory.exists() && db != null) { - // Perform a logical delete on the database so it can be manually recovered if this is an error: - virtualDelete( directory ); - - // This dispose just removes the entries from the collection and deletes nothing from the file system: - db.dispose(); - //directory.delete(); - databaseMap.remove(name); - results = true; + // Perform a logical delete on the database so it can be manually recovered if this is an error: + virtualDelete( directory ); + + // This dispose just removes the entries from the collection and deletes nothing from the file system: + db.dispose(); + //directory.delete(); + databaseMap.remove(name); + results = true; } else { - String message = "The attempt to delete a FileDatabase named " + name + - " failed because either the directory does not exist or it was not in the databaseMap."; - Output.get().logWarn( message ); + String message = "The attempt to delete a FileDatabase named " + name + + " failed because either the directory does not exist or it was not in the databaseMap."; + Output.get().logWarn( message ); } return results; diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java b/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java index 5be2b65a6..5663a15a0 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/FileVirtualDelete.java @@ -1,6 +1,3 @@ -/** - * - */ package tech.mcprison.prison.file; import java.io.File; @@ -12,9 +9,6 @@ import tech.mcprison.prison.output.Output; -/** - * - */ public abstract class FileVirtualDelete { public static final String FILE_LOGICAL_DELETE_PREFIX = ".deleted_"; @@ -55,23 +49,23 @@ protected boolean virtualDelete( File source ) */ protected File virtualBackup( File source ) { - SimpleDateFormat sdf = new SimpleDateFormat("_yyyy-MM-dd_HH-mm-ss"); - String name = FILE_LOGICAL_BACKUP_PREFIX + source.getName() + sdf.format( new Date() ) + ".bu"; - File backupFile = new File( source.getParentFile(), name); - - try { - Files.copy( source, backupFile ); - } - catch ( IOException e ) - { - Output.get().logError( - String.format( - "Could not create a backup. SourceFile: %s BackupFile: %s Error: [%s]", - source.getAbsolutePath(), backupFile.getAbsolutePath(), e.getMessage() )); - e.printStackTrace(); - } - - return backupFile; + SimpleDateFormat sdf = new SimpleDateFormat("_yyyy-MM-dd_HH-mm-ss"); + String name = FILE_LOGICAL_BACKUP_PREFIX + source.getName() + sdf.format( new Date() ) + ".bu"; + File backupFile = new File( source.getParentFile(), name); + + try { + Files.copy( source, backupFile ); + } + catch ( IOException e ) + { + Output.get().logError( + String.format( + "Could not create a backup. SourceFile: %s BackupFile: %s Error: [%s]", + source.getAbsolutePath(), backupFile.getAbsolutePath(), e.getMessage() )); + e.printStackTrace(); + } + + return backupFile; } /** @@ -85,9 +79,9 @@ protected File virtualBackup( File source ) */ protected boolean isDeleted( File source ) { - return - source.getName().toLowerCase().startsWith( FILE_LOGICAL_DELETE_PREFIX ) || - source.getName().toLowerCase().startsWith( FILE_LOGICAL_BACKUP_PREFIX ); + return + source.getName().toLowerCase().startsWith( FILE_LOGICAL_DELETE_PREFIX ) || + source.getName().toLowerCase().startsWith( FILE_LOGICAL_BACKUP_PREFIX ); } } 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 b2deb33dc..a12790a9b 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 @@ -6,18 +6,12 @@ import com.google.gson.GsonBuilder; import tech.mcprison.prison.error.ErrorManager; -import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.modules.ModuleStatus; import tech.mcprison.prison.output.Output; public class JsonFileIO extends FileIO { - public static final String FILE_SUFFIX_JSON = ".json"; - public static final String FILE_PREFIX_BACKUP = ".backup_"; - public static final String FILE_SUFFIX_BACKUP = ".bu"; - public static final String FILE_SUFFIX_TEMP = ".temp"; - public static final String FILE_TIMESTAMP_FORMAT = "_yyyy-MM-dd_HH-mm-ss"; private final Gson gson; @@ -51,44 +45,7 @@ public Gson getGsonExposed() .create(); } - - - /** - *

This constructs a player file named based upon the UUID followed - * by the player's name. This format is used so it's easier to identify - * the correct player. - *

- * - *

The format should be UUID-PlayerName.json. The UUID is a shortened - * format, which should still produce a unique id. The name, when read, - * is based upon the UUID and not the player's name, which may change. - * This format includes the player's name to make it easier to identify - * who's record is whom's. - *

- * - * @return - */ - public static String getPlayerFileName( Player player ) { - - String UUIDString = player.getUUID().toString(); - String uuidFragment = getFileNamePrefix( UUIDString ); - - return uuidFragment + "_" + player.getName() + FILE_SUFFIX_JSON; - } - - /** - *

This function returns the first 13 characters of the supplied - * file name, or UUID String. The hyphen is around the 12 or 13th position, - * so it may or may not include it. - *

- * - * @param playerFileName - * @return - */ - private static String getFileNamePrefix( String UUIDString ) { - return UUIDString.substring( 0, 14 ); - } - + public String toString( Object obj ) { String json = getGson().toJson( obj ); @@ -96,6 +53,18 @@ public String toString( Object obj ) { return json; } + public T fromString( String json, Class klass ) { + + + T obj = getGson().fromJson( json, klass ); + + + return obj; + } + + + + /** * 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 @@ -155,8 +124,11 @@ public FileIOData readJsonFile( File file, FileIOData data ) String message = String.format( "JsonFileIO.readJsonFile: JsonParse failure: file: [%s] " + "error: [%s] json: [%s] ", - file.getAbsoluteFile(), e.getMessage(), - json ); + file.getAbsoluteFile(), + (e.getMessage() == null ? "no-error-message" : e.getMessage()), + (json.length() > 500 ? + json.substring(0, 500) + "... (first 500 chars)" : json ) + .replace("%", "\\%")); Output.get().logError( message ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/file/YamlFileIO.java b/prison-core/src/main/java/tech/mcprison/prison/file/YamlFileIO.java index e01e17bbb..376f4e493 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/file/YamlFileIO.java +++ b/prison-core/src/main/java/tech/mcprison/prison/file/YamlFileIO.java @@ -98,35 +98,6 @@ public boolean saveYamlAutoFeatures( Map config ) { break; } -// if ( value.isNullNode() ) { -// // skip nulls -// set( key, null ); -// } -// else if ( value.isBooleanNode() ) { -// set( key, ((BooleanNode) value).getValue() ); -// } -// else if ( value.isTextNode() ) { -// set( key, ((TextNode) value).getValue() ); -// } -// else if ( value.isDoubleNode() ) { -// set( key, ((DoubleNode) value).getValue() ); -// } -// else if ( value.isLongNode() ) { -// set( key, ((LongNode) value).getValue() ); -// } -// else if ( value.isIntegerNode() ) { -// set( key, ((IntegerNode) value).getValue() ); -// } -// else if ( value.isStringListNode() ) { -// set( key, ((StringListNode) value).getValue() ); -// } -// else if ( value.isBlockConverterNode() ) { -// set( key, ((BlockConvertersNode) value).t ); -// } -// else { -// // invalid type... not supported. -//// set( key, value ); -// } } return saveYaml(); diff --git a/prison-core/src/main/java/tech/mcprison/prison/gui/PrisonCoreGuiMessages.java b/prison-core/src/main/java/tech/mcprison/prison/gui/PrisonCoreGuiMessages.java index e9bdbbd4b..fa4d86723 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/gui/PrisonCoreGuiMessages.java +++ b/prison-core/src/main/java/tech/mcprison/prison/gui/PrisonCoreGuiMessages.java @@ -6,6 +6,9 @@ public class PrisonCoreGuiMessages { + public PrisonCoreGuiMessages() { + super(); + } protected String guiClickToDecreaseMsg() { return Prison.get().getLocaleManager() diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java b/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java index 8c6a015fb..a05c4b3a8 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/CustomBlockIntegration.java @@ -51,7 +51,6 @@ public CustomBlockIntegration( String keyName, String providerName, public abstract void setCustomBlockIdAsync( PrisonBlock prisonBlock, Location location ); public abstract List getDrops( Player player, PrisonBlock prisonBlock, ItemStack tool ); -// public abstract List getDrops( PrisonBlock prisonBlock ); public abstract List getCustomBlockList(); diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationManager.java b/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationManager.java index 96d190737..4046e2e6d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationManager.java @@ -76,35 +76,35 @@ public boolean hasForType(IntegrationType type) { * @param i The {@link Integration}. */ public void register(Integration i) { - IntegrationType iType = i.getType(); - if ( !integrations.containsKey( iType ) ) { - integrations.put(iType, new ArrayList<>()); - } - - // If integration is already stored, remove the older one. Check on keyName: - List regIntegrations = integrations.get(iType); - for ( int x = 0; x < regIntegrations.size(); x++ ) { - if ( i.getKeyName().equals( regIntegrations.get(x).getKeyName() ) ) { - regIntegrations.remove( x ); - break; - } - } - integrations.get(iType).add(i); + IntegrationType iType = i.getType(); + if ( !integrations.containsKey( iType ) ) { + integrations.put(iType, new ArrayList<>()); + } + + // If integration is already stored, remove the older one. Check on keyName: + List regIntegrations = integrations.get(iType); + for ( int x = 0; x < regIntegrations.size(); x++ ) { + if ( i.getKeyName().equals( regIntegrations.get(x).getKeyName() ) ) { + regIntegrations.remove( x ); + break; + } + } + integrations.get(iType).add(i); } public PermissionIntegration getPermission() { - return (PermissionIntegration) getForType(IntegrationType.PERMISSION) - .orElse( null ); + return (PermissionIntegration) getForType(IntegrationType.PERMISSION) + .orElse( null ); } public EconomyIntegration getEconomy() { - return (EconomyIntegration) getForType(IntegrationType.ECONOMY) - .orElse( null ); + return (EconomyIntegration) getForType(IntegrationType.ECONOMY) + .orElse( null ); } public EconomyCurrencyIntegration getEconomyForCurrency(String currency) { - EconomyCurrencyIntegration results = null; - + EconomyCurrencyIntegration results = null; + if(integrations.containsKey(IntegrationType.ECONOMY)) { List econs = getAllForType(IntegrationType.ECONOMY); @@ -129,34 +129,16 @@ public EconomyCurrencyIntegration getEconomyForCurrency(String currency) { public CustomBlockIntegration getCustomBlockIntegration( PrisonBlockType blockType ) { - CustomBlockIntegration results = null; - - for ( CustomBlockIntegration customBlock : getCustomBlockIntegrations() ) - { - - if ( customBlock.getBlockType() == blockType ) { - results = customBlock; - break; - } + CustomBlockIntegration results = null; + + for ( CustomBlockIntegration customBlock : getCustomBlockIntegrations() ) { + + if ( customBlock.getBlockType() == blockType ) { + results = customBlock; + break; + } } -// if(integrations.containsKey(IntegrationType.CUSTOMBLOCK)) { -// -// List cbIntegrations = getAllForType(IntegrationType.CUSTOMBLOCK); -// -// for ( Integration cbIntegration : cbIntegrations ) { -// if ( cbIntegration.hasIntegrated() && cbIntegration instanceof CustomBlockIntegration ) { -// -// CustomBlockIntegration customBlock = (CustomBlockIntegration) cbIntegration; -// -// if ( customBlock.getBlockType() == blockType ) { -// results = customBlock; -// break; -// } -// } -// } -// } - return results; } @@ -186,38 +168,38 @@ public List getCustomBlockIntegrations() public String getIntegrationDetails( IntegrationType integrationType ) { - StringBuilder sb = new StringBuilder(); - Set keys = integrations.keySet(); - - for ( IntegrationType key : keys ) { - if ( key == integrationType ) { - sb.append( key.name() ); - sb.append( ": [" ); - - StringBuilder sb2 = new StringBuilder(); - List integrates = integrations.get( key ); - for ( Integration i : integrates ) { - if ( sb2.length() > 0 ) { - sb2.append( ", " ); - } - sb2.append( i.getDisplayName() ); - sb2.append( " (registered=" ); - sb2.append( i.isRegistered() ); - sb2.append( ", integrated=" ); - sb2.append( i.hasIntegrated() ); - sb2.append( ")" ); - if ( i.getDebugInfo() != null && i.getDebugInfo().trim().length() > 0 ) { - sb2.append( " Debug: {" ); - sb2.append( i.getDebugInfo() ); - sb2.append( "}" ); - } - } - - sb.append( sb2 ); - sb.append( "] " ); - } + StringBuilder sb = new StringBuilder(); + Set keys = integrations.keySet(); + + for ( IntegrationType key : keys ) { + if ( key == integrationType ) { + sb.append( key.name() ); + sb.append( ": [" ); + + StringBuilder sb2 = new StringBuilder(); + List integrates = integrations.get( key ); + for ( Integration i : integrates ) { + if ( sb2.length() > 0 ) { + sb2.append( ", " ); + } + sb2.append( i.getDisplayName() ); + sb2.append( " (registered=" ); + sb2.append( i.isRegistered() ); + sb2.append( ", integrated=" ); + sb2.append( i.hasIntegrated() ); + sb2.append( ")" ); + if ( i.getDebugInfo() != null && i.getDebugInfo().trim().length() > 0 ) { + sb2.append( " Debug: {" ); + sb2.append( i.getDebugInfo() ); + sb2.append( "}" ); + } + } + + sb.append( sb2 ); + sb.append( "] " ); + } } - return sb.toString(); + return sb.toString(); } /** @@ -233,25 +215,25 @@ public String getIntegrationDetails( IntegrationType integrationType ) { * @return */ public List getIntegrationComponents(boolean isBasic) { - List results = new ArrayList<>(); + List results = new ArrayList<>(); for ( IntegrationType integrationType : IntegrationType.values() ) { - if ( integrationType == IntegrationType.WORLDGUARD ) { - // Skip this integration type: - break; + + if ( integrationType == IntegrationType.WORLDGUARD ) { + // Skip this integration type: + continue; } boolean activeIntegration = false; - results.add( new TextComponent( String.format( "&7Integration Type: &3%s", integrationType.name() ) )); + results.add( new TextComponent( String.format( "&7Integration Type: &3%s", integrationType.name() ) )); - // Generates the placeholder list for the /prison version command, printing - // two placeholders per line. + // Generates the placeholder list for the /prison version command, printing + // two placeholders per line. if ( integrationType == IntegrationType.PLACEHOLDER ) { results.add( new TextComponent( ". . &7To list all or search for placeholders see: " + "&a/prison placeholders") ); -// getPlaceholderTemplateList( results ); } List plugins = getAllForType( integrationType ); @@ -319,7 +301,7 @@ else if ( plugins == null || plugins.size() == 0 ) { } } - return results; + return results; } /** @@ -328,33 +310,12 @@ else if ( plugins == null || plugins.size() == 0 ) { */ public void getPlaceholderTemplateList( List results ) { - //results.add( new TextComponent( " &7Available PlaceHolders: " )); List placeholders = PrisonPlaceHolders.getAllChatList(true); -// StringBuilder sb = new StringBuilder(); for ( String placeholder : placeholders ) { results.add( new TextComponent( " " + placeholder )); -// if ( sb.length() == 0) { -// sb.append( " " ); -// sb.append( placeholder ); -// } -// else if ( (sb.length() + placeholder.length()) > 90) { -// // will be too long combined so write existing sb then start over: -// results.add( new TextComponent( sb.toString() )); -// sb.setLength( 0 ); -// -// sb.append( " " ); -// sb.append( placeholder ); -// } else { -// sb.append( placeholder ); -// results.add( new TextComponent( sb.toString() )); -// sb.setLength( 0 ); -// } } -// if ( sb.length() > 0 ) { -// results.add( new TextComponent( sb.toString() )); -// } } public List getDeferredIntegrations() { @@ -380,30 +341,19 @@ public void register( Integration integration, boolean isRegistered, String vers if ( integration.hasIntegrated() ) { register(integration ); } -// else { -// boolean deferredRemoved = getDeferredIntegrations().remove( integration ); -// -// Output.get().logWarn( -// String.format( "Warning: An integration that is registered with bukkit " + -// "failed to integrate: %s %s %s[%s]", -// integration.getKeyName(), integration.getVersion(), -// ( deferredRemoved ? "(Deferred Processing Removed) " : "" ), -// (integration.getDebugInfo() == null ? -// "no debug info" : integration.getDebugInfo()) )); -// } } catch ( Exception e ) { - boolean deferredRemoved = getDeferredIntegrations().remove( integration ); - - removeIntegration( integration ); - - Output.get().logWarn( - String.format( "Warning: An integration caused an error while loading. " + - "Disabling the integration to protect Prison: %s %s %s[%s]", - integration.getKeyName(), integration.getVersion(), - ( deferredRemoved ? "(Deferred Processing Removed) " : "" ), - (integration.getDebugInfo() == null ? - "no debug info" : integration.getDebugInfo()) )); + boolean deferredRemoved = getDeferredIntegrations().remove( integration ); + + removeIntegration( integration ); + + Output.get().logWarn( + String.format( "Warning: An integration caused an error while loading. " + + "Disabling the integration to protect Prison: %s %s %s[%s]", + integration.getKeyName(), integration.getVersion(), + ( deferredRemoved ? "(Deferred Processing Removed) " : "" ), + (integration.getDebugInfo() == null ? + "no debug info" : integration.getDebugInfo()) )); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationType.java b/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationType.java index 9fb735d4a..3a8e4febe 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationType.java +++ b/prison-core/src/main/java/tech/mcprison/prison/integration/IntegrationType.java @@ -5,6 +5,11 @@ */ public enum IntegrationType { - ECONOMY, PERMISSION, PLACEHOLDER, WORLDGUARD, CUSTOMBLOCK + ECONOMY, + PERMISSION, + PLACEHOLDER, + CUSTOMBLOCK, + BACKPACK, + WORLDGUARD } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/ArmorStand.java b/prison-core/src/main/java/tech/mcprison/prison/internal/ArmorStand.java new file mode 100644 index 000000000..697767f4d --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/ArmorStand.java @@ -0,0 +1,42 @@ +package tech.mcprison.prison.internal; + +public interface ArmorStand + extends Entity { + + public boolean isVisible(); + public void setVisible( boolean visible ); + + public boolean getRemoveWhenFarAway(); + public void setRemoveWhenFarAway( boolean removeWhenFarAway ); + + public ItemStack getItemInHand(); + public void setItemInHand( ItemStack itemm ); + + + public ItemStack getHelmet(); + public void setHelmet( ItemStack item ); + + + public void setRightArmPose( EulerAngle arm ); + + public boolean isGlowing(); + public void setGlowing( boolean glowing ); + + public boolean hasGravity(); + public void setGravity( boolean gravity ); + + public boolean hasArms(); + public void setArms( boolean arms ); + + public boolean hasBasePlate(); + public void setBasePlate( boolean basePlate ); + + public boolean getCanPickupItems(); + public void setCanPickupItems( boolean canPickupItems ); + + public boolean isSmall(); + public void setSmall(boolean small); + + public void setInvulnerable(boolean b); + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/CommandSender.java b/prison-core/src/main/java/tech/mcprison/prison/internal/CommandSender.java index 50b5a53c7..1780ff33b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/CommandSender.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/CommandSender.java @@ -31,13 +31,6 @@ public interface CommandSender extends PlayerPermissions { -// /** -// * Returns the UUID for CommandSender if they are a bukkit Player. -// * -// * @return -// */ -// public UUID getUUID(); - /** * Returns the name of the command sender. */ @@ -89,18 +82,6 @@ public interface CommandSender public void sendRaw(String json); -// public boolean isOp(); -// -// public void recalculatePermissions(); -// -// /** -// * Returns true if the command sender has access to the permission specified. -// * -// * @param perm The permission to check. -// */ -// boolean hasPermission(String perm); - - public boolean isPlayer(); public List getSellAllMultiplierListings(); @@ -120,5 +101,15 @@ public interface CommandSender public RankPlayer getRankPlayer(); + + /** + * This miscText is not used for any specific purpose other than to hold a String + * value. It can be used to return a message from a function, but it should always + * be cleared when done using it. + * + * @return + */ + public String getMiscText(); + public void setMiscText( String text ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/Entity.java b/prison-core/src/main/java/tech/mcprison/prison/internal/Entity.java new file mode 100644 index 000000000..d770d637f --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/Entity.java @@ -0,0 +1,140 @@ +package tech.mcprison.prison.internal; + +import java.util.List; +import java.util.UUID; + +import tech.mcprison.prison.util.Location; +import tech.mcprison.prison.util.Vector; + +public interface Entity + extends CommandSender +{ + + public String getNbtString( String key ); + public void setNbtString( String key, String value ); + + + /** Returns a unique and persistent id for this entity */ + public UUID getUniqueId(); + + + /** Gets the custom name on a mob. */ + public String getCustomName(); + + /** Returns a unique id for this entity */ + public int getEntityId(); + + /** Eject any passenger. */ + public boolean eject(); + + /** Gets the entity's current position */ + public Location getLocation(); + + /** Stores the entity's current position in the provided Location object. */ + public Location getLocation(Location loc); + + + /** Returns the distance this entity has fallen */ + public float getFallDistance(); + + /** Returns the entity's current fire ticks (ticks before the entity stops being on fire). */ + public int getFireTicks(); + + /** Retrieve the last EntityDamageEvent inflicted on this entity. */ +// public EntityDamageEvent getLastDamageCause(); + + /** Returns the entity's maximum fire ticks. */ + public int getMaxFireTicks(); + + /** Returns a list of entities within a bounding box centered around this entity */ + public List getNearbyEntities(double x, double y, double z); + + /** Gets the primary passenger of a vehicle. */ + public Entity getPassenger(); + + /** Gets the Server that contains this Entity */ + //public Server getServer(); + + /** Gets the amount of ticks this entity has lived for. */ + public int getTicksLived(); + + /** Get the type of the entity. */ + public EntityType getType(); + + /** Get the vehicle that this player is inside. */ + public Entity getVehicle(); + + /** Gets this entity's current velocity */ + public Vector getVelocity(); + + /** Gets the current world this entity resides in */ + public World getWorld(); + + /** Gets whether or not the mob's custom name is displayed client side. */ + public boolean isCustomNameVisible(); + + /** Sets a custom name on a mob. */ + public void setCustomName(String name); + + /** Sets whether or not to display the mob's custom name client side. */ + public void setCustomNameVisible(boolean flag); + + + /** Returns true if this entity has been marked for removal. */ + public boolean isDead(); + + /** Check if a vehicle has passengers. */ + public boolean isEmpty(); + + /** Returns whether this entity is inside a vehicle. */ + public boolean isInsideVehicle(); + + /** Returns true if the entity is supported by a block. */ + public boolean isOnGround(); + + /** Returns false if the entity has died or been despawned for some other reason. */ + public boolean isValid(); + + /** Leave the current vehicle. */ + public boolean leaveVehicle(); + + /** Performs the specified EntityEffect for this entity. */ + //public void playEffect(EntityEffect type); + + /** Mark the entity's removal. */ + public void remove(); + + /** Sets the fall distance for this entity */ + public void setFallDistance(float distance); + + /** Sets the entity's current fire ticks (ticks before the entity stops being on fire). */ + public void setFireTicks(int ticks); + + /** Record the last EntityDamageEvent inflicted on this entity */ + //public void setLastDamageCause(EntityDamageEvent event); + + /** Set the passenger of a vehicle. */ + public boolean setPassenger(Entity passenger); + + /** Sets the amount of ticks this entity has lived for. */ + public void setTicksLived(int value); + + /** Sets this entity's velocity */ + public void setVelocity(Vector velocity); + + //public Entity.Spigot spigot(); + + /** Teleports this entity to the target Entity. */ + boolean teleport(Entity destination); + + /** Teleports this entity to the target Entity. */ + //public boolean teleport(Entity destination, PlayerTeleportEvent.TeleportCause cause); + + /** Teleports this entity to the given location. */ + public boolean teleport(Location location); + + /** Teleports this entity to the given location. */ + // public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause); + + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/EntityType.java b/prison-core/src/main/java/tech/mcprison/prison/internal/EntityType.java new file mode 100644 index 000000000..e15b4d062 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/EntityType.java @@ -0,0 +1,22 @@ +package tech.mcprison.prison.internal; + +public class EntityType { + + public static final EntityType ENTITY_TYPE_ARMOR_STAND = new EntityType( "ARMOR_STAND" ); + + private String entityType; + + public EntityType( String entityType ) { + super(); + + this.entityType = entityType; + } + + public String getEntityType() { + return entityType; + } + public void setEntityType(String entityType) { + this.entityType = entityType; + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/EulerAngle.java b/prison-core/src/main/java/tech/mcprison/prison/internal/EulerAngle.java new file mode 100644 index 000000000..2f94f4270 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/EulerAngle.java @@ -0,0 +1,149 @@ +package tech.mcprison.prison.internal; + +import java.text.DecimalFormat; + +public class EulerAngle { + + private double x; + private double y; + private double z; + + public EulerAngle( double x, double y, double z ) { + super(); + + this.x = x; + this.y = y; + this.z = z; + } + + public String toString() { + DecimalFormat dFmt = new DecimalFormat( "#,##0.0000" ); + String fmt = String.format( + "EulerAngle: x: %s y: %s z: %s", + dFmt.format( getX() ), + dFmt.format( getY() ), + dFmt.format( getZ() ) + ); + return fmt; + } + + public EulerAngle add( double x, double y, double z ) { + EulerAngle ea = new EulerAngle( x + getX(), y + getY(), z + getZ() ); + return ea; + } + + public EulerAngle subtract( double x, double y, double z ) { + EulerAngle ea = new EulerAngle( getX() - x , getY() - y, getZ() - z ); + return ea; + } + + + /** + * NOTE: These do not work. Not sure what the angle should be, or what + * the starting angles should be, but it goes to zero pretty quickly. + * So do not use these functions. + * + * + * The rotateAroundAxis is based upon the following post, reply number 11: + * https://www.spigotmc.org/threads/how-to-calculate-armorstand-arm-tip-location.331825/#post-3284591 + * + * @param angle + * @return + */ + public EulerAngle rotateAroundAxisX( double angle ) { + EulerAngle ea = rotateAroundAxisX( getX(), getY(), getZ(), angle ); + + setX( ea.getX() ); + setY( ea.getY() ); + setZ( ea.getZ() ); + + return this; + } + + public static EulerAngle rotateAroundAxisX( double x, double y, double z, double angle ) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + y = y * cos - z * sin; + z = y * sin + z * cos; + return new EulerAngle( x, y, z ); + } + + public EulerAngle rotateAroundAxisY( double angle ) { + EulerAngle ea = rotateAroundAxisY( getX(), getY(), getZ(), angle ); + + setX( ea.getX() ); + setY( ea.getY() ); + setZ( ea.getZ() ); + + return this; + } + + public static EulerAngle rotateAroundAxisY( double x, double y, double z, double angle ) { + angle = -angle; + double cos = Math.cos(angle); + double sin = Math.sin(angle); + x = x * cos + z * sin; + z = x * -sin + z * cos; + return new EulerAngle( x, y, z ); + } + + public EulerAngle rotateAroundAxisZ( double angle ) { + EulerAngle ea = rotateAroundAxisZ( getX(), getY(), getZ(), angle ); + + setX( ea.getX() ); + setY( ea.getY() ); + setZ( ea.getZ() ); + + return this; + } + + public EulerAngle rotateAroundAxisZ( double x, double y, double z, double angle ) { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + x = x * cos - y * sin; + y = x * sin + y * cos; + return new EulerAngle( x, y, z ); + } + + + /** + * https://math.oxford.emory.edu/site/cs171/generatingHashCodes/ + */ + public int hashCode() { + int h = 17; + h = 31 * h + ((Double) getX()).hashCode(); + h = 31 * h + ((Double) getY()).hashCode(); + h = 31 * h + ((Double) getZ()).hashCode(); + + return h; + } + + public double getX() { + return x; + } + public EulerAngle setX( double x ) { + this.x = x; +// EulerAngle ea = new EulerAngle( x, getY(), getZ() ); + return this; + } + + public double getY() { + return y; + } + public EulerAngle setY( double y ) { + this.y = y; +// EulerAngle ea = new EulerAngle( getX(), y, getZ() ); + return this; + } + + public double getZ() { + return z; + } + public EulerAngle setZ( double z ) { + this.z = z; +// EulerAngle ea = new EulerAngle( getX() , getY(), z ); + return this; + } + + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/ItemStack.java b/prison-core/src/main/java/tech/mcprison/prison/internal/ItemStack.java index c49d47b4b..4d105e035 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/ItemStack.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/ItemStack.java @@ -39,39 +39,66 @@ public class ItemStack { private int amount; private PrisonBlock material; private List lore; -// private Map enchantments; + public static final ItemStack SELECTION_WAND; + static { + SELECTION_WAND = new ItemStack( 1, PrisonBlock.SELECTION_WAND, + "&7Corner 1 - Left click", + "&7Corner 2 - Right click"); + } + + /** + * Do not use this constructor, it is for unit testing. + */ protected ItemStack() { - super(); - - this.lore = new ArrayList<>(); -// this.enchantments = new HashMap<>(); + super(); + + this.lore = new ArrayList<>(); } public ItemStack(String displayName, int amount, PrisonBlock material, String... lore) { this.displayName = displayName; this.amount = amount; - this.material = material; + this.material = material.clone(); this.lore = new ArrayList<>(Arrays.asList(lore)); -// this.enchantments = new HashMap<>(); + + if ( displayName != null && displayName.trim().length() > 0 ) { + this.material.setDisplayName( displayName.trim() ); + } + } public ItemStack(int amount, PrisonBlock material, String... lore) { this.amount = amount; this.material = material; this.lore = new ArrayList<>(Arrays.asList(lore)); + + if ( material.getDisplayName() != null && material.getDisplayName().trim().length() > 0 ) { + setDisplayName( material.getDisplayName() ); + } } + public ItemStack( ItemStack iStack ) { + this.displayName = iStack.getDisplayName(); + this.amount = iStack.getAmount(); + this.material = iStack.getMaterial().clone(); + this.lore = new ArrayList<>( iStack.getLore() ); + + if ( displayName != null && displayName.trim().length() > 0 ) { + this.material.setDisplayName( displayName.trim() ); + } + } + /** * Returns the name of the item stack, derived from its BlockType name. */ public String getName() { - String name = (material != null ? - material.getBlockName() : - ( getDisplayName() != null ? - getDisplayName() : - "none")); + String name = (material != null ? + material.getBlockName() : + ( getDisplayName() != null ? + getDisplayName() : + "none")); return StringUtils.capitalize(name.replaceAll("_", " ").toLowerCase()); } @@ -99,11 +126,28 @@ public void setAmount( int amount ) { * Returns the type of items in this stack. */ public PrisonBlock getMaterial() { + + if ( getDisplayName() != null && getDisplayName().trim().length() > 0 && + material.getDisplayName() == null || + material.getDisplayName() != null && material.getDisplayName().trim().length() == 0 ) { + material.setDisplayName( getDisplayName() ); + } + return material; } public void setMaterial( PrisonBlock material ) { this.material = material; } + + /** + *

The material for an item stack is the PrisonBlock. + *

+ * + * @return + */ + public PrisonBlock getPrisonBlock() { + return getMaterial(); + } public List getLore() { return lore; @@ -112,23 +156,9 @@ public void setLore( List lore ) { this.lore = lore; } -// public Map getEnchantments() { -// return enchantments; -// } -// -// public void addEnchantment(Object enchantment, int level) { -// enchantments.put(enchantment, level); -// } -// -// public boolean hasEnchantments() { -// return !enchantments.isEmpty(); -// } -// -// public boolean hasEnchantment(int enchantment) { -// return enchantments.containsKey(enchantment); -// } - - @Override public boolean equals(Object o) { + + @Override + public boolean equals(Object o) { if (this == o) { return true; } @@ -147,16 +177,17 @@ public void setLore( List lore ) { material.compareTo( stack.material ) == 0; } - @Override public int hashCode() { + @Override + public int hashCode() { int result = amount; result = 31 * result + material.hashCode(); return result; } - @Override public String toString() { + @Override + public String toString() { return "ItemStack{" + "displayName='" + displayName + '\'' + ", amount=" + amount + ", material=" + material + ", lore=" + lore + "}"; - //", enchantments=" + enchantments + '}'; } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/OfflineMcPlayer.java b/prison-core/src/main/java/tech/mcprison/prison/internal/OfflineMcPlayer.java index 6f99e3da0..ff6e92b0f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/OfflineMcPlayer.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/OfflineMcPlayer.java @@ -7,23 +7,24 @@ public interface OfflineMcPlayer /** * Returns the unique identifier for this player. */ - UUID getUUID(); + public UUID getUUID(); /** * Returns the player's display name (nickname), which may include colors. */ - String getDisplayName(); + public String getDisplayName(); /** * Sets the player's display name (nickname). * * @param newDisplayName The new display name. May include colors, amp-prefixed. */ - void setDisplayName(String newDisplayName); + public void setDisplayName(String newDisplayName); /** * @return Returns true if the player is online, false otherwise. */ - boolean isOnline(); - + public boolean isOnline(); + + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java b/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java index a0c7e61ae..2a49849b6 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/Player.java @@ -105,7 +105,7 @@ public interface Player * * @param location The new {@link Location}. */ - public void teleport(Location location); + public boolean teleport(Location location); /** * @return Returns true if the player is online, false otherwise. @@ -178,6 +178,14 @@ public default boolean doesSupportColors() { public void incrementMinecraftStatsDropCount( Player player, String blockName, int quantity); + /** + * Returns the bukkit's last seen date as a long. + * + * @return + */ + public long getLastSeenDate(); + + // public RankPlayer getRankPlayer(); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/PlayerPermissions.java b/prison-core/src/main/java/tech/mcprison/prison/internal/PlayerPermissions.java index 21d7566ba..a0aa24a4a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/PlayerPermissions.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/PlayerPermissions.java @@ -28,9 +28,13 @@ public interface PlayerPermissions { public List getPermissions( String prefix ); + public List getPermissions( String prefix, List perms ); + public double getSellAllMultiplier(); + public double getSellAllMultiplierDebug(); + public List getPermissionsIntegrations( boolean detailed ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/World.java b/prison-core/src/main/java/tech/mcprison/prison/internal/World.java index 00f70483c..c37391c11 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/World.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/World.java @@ -20,6 +20,7 @@ import java.util.List; +import tech.mcprison.prison.bombs.MineBombs.AnimationArmorStandItemLocation; import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.block.MineResetType; import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; @@ -44,6 +45,13 @@ public interface World { */ List getPlayers(); + + /** + * Returns a list of all entities in this world. + * @return + */ + List getEntities(); + /** * Returns the {@link Block} at a specified location. * @@ -72,5 +80,18 @@ public void setBlocksSynchronously( List tBlocks, MineResetType resetType, PrisonStatsElapsedTimeNanos nanos ); + + + public Entity spawnEntity( Location loc, EntityType entityType); + + + public ArmorStand spawnArmorStand( Location location ); + + + public ArmorStand spawnArmorStand(Location location, String itemType, + AnimationArmorStandItemLocation asLocation ); + + public int getMaxHeight(); + } 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 df65f516f..0cc80727f 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 @@ -36,7 +36,7 @@ public interface Block { * * @return The {@link Location} of the block. */ - Location getLocation(); + public Location getLocation(); /** * Returns the {@link Block} at the position relative to this one. @@ -44,27 +44,12 @@ public interface Block { * @param face The {@link BlockFace} that the relative block touches. * @return The {@link Block} relative to this one. */ - Block getRelative(BlockFace face); + public Block getRelative(BlockFace face); -// /** -// * Returns the type of this block. -// * -// * @return The {@link BlockType}. -// */ -// BlockType getType(); - public PrisonBlock getPrisonBlock(); -// /** -// * Sets the block to a different type. -// * -// * @param type The new {@link BlockType}. -// */ -// void setType(BlockType type); - - public void setPrisonBlock( PrisonBlock prisonBlock ); /** diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/BlockFace.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/BlockFace.java index cd71f48fe..f54ae67f4 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/BlockFace.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/BlockFace.java @@ -33,21 +33,21 @@ public BlockFace getOppositeFace() { case NORTH: return SOUTH; case SOUTH: - return NORTH; + return NORTH; case EAST: - return WEST; + return WEST; case WEST: - return EAST; + return EAST; case TOP: - return BOTTOM; + return BOTTOM; case BOTTOM: - return TOP; + return TOP; case UP: - return DOWN; + return DOWN; case DOWN: - return UP; + return UP; default: - return NORTH; + return NORTH; } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/BlockState.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/BlockState.java index 480222cdc..837f231b2 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/BlockState.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/BlockState.java @@ -19,14 +19,16 @@ package tech.mcprison.prison.internal.block; /** - * Represents a captured state of a block, which will not change + *

Represents a captured state of a block, which will not change * automatically. - *

- * Unlike {@link Block }, which only one object can exist per coordinate, {@link BlockState} + *

+ * + *

Unlike {@link Block }, which only one object can exist per coordinate, {@link BlockState} * can exist multiple times for any given Block. Note that another plugin may * change the state of the block and you will not know, or they may change the * block to another type entirely, causing your BlockState to become invalid. - * + *

+ * * @author Faizaan A. Datoo * @since API 1.0 */ diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/Door.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/Door.java index 3b157900b..4eef48e1a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/Door.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/Door.java @@ -54,16 +54,11 @@ default void toggleOpen() { */ default boolean isWoodenDoor() { - String blockName = getBlock().getPrisonBlock().getBlockName(); - - return blockName != null && - blockName.matches( "ACACIA_DOOR|BIRCH_DOOR|CRIMSON_DOOR|OAK_DOOR|DARK_OAK_DOOR|" + - "JUNGLE_DOOR|SPRUCE_DOOR|WARPED_DOOR" ); - -// BlockType block = getBlock().getType(); -// return block == BlockType.ACACIA_DOOR_BLOCK || block == BlockType.BIRCH_DOOR_BLOCK -// || block == BlockType.DARK_OAK_DOOR_BLOCK || block == BlockType.JUNGLE_DOOR_BLOCK -// || block == BlockType.OAK_DOOR_BLOCK || block == BlockType.SPRUCE_DOOR_BLOCK; + String blockName = getBlock().getPrisonBlock().getBlockName(); + + return blockName != null && + blockName.matches( "ACACIA_DOOR|BIRCH_DOOR|CRIMSON_DOOR|OAK_DOOR|DARK_OAK_DOOR|" + + "JUNGLE_DOOR|SPRUCE_DOOR|WARPED_DOOR" ); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetBlockKey.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetBlockKey.java index a1ba58713..179c6ccad 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetBlockKey.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/MineTargetBlockKey.java @@ -6,13 +6,27 @@ public class MineTargetBlockKey implements Comparable { - private final World world; + private final String worldName; + private final transient World world; private final int x, y, z; + public MineTargetBlockKey() { + super(); + + this.world = null; + this.worldName = null; + + this.x = 0; + this.y = 0; + this.z = 0; + + } + public MineTargetBlockKey( World world, int x, int y, int z ) { super(); this.world = world; + this.worldName = world == null ? null : world.getName(); this.x = x; this.y = y; @@ -44,6 +58,10 @@ public World getWorld() { return world; } + public String getWorldName() { + return worldName; + } + public int getX() { return x; } @@ -102,13 +120,7 @@ public int hashCode() hash += x * 13 + y * 37 + z * 17; - // TODO Auto-generated method stub -// return super.hashCode(); - return hash; } - - - } 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 f812ed5fd..7fefc4925 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 @@ -18,7 +18,6 @@ public class MineTargetPrisonBlock private boolean mined = false; private Block minedBlock; -// private boolean blockEvent = false; private boolean counted = false; private boolean ignoreAllBlockEvents = false; @@ -123,7 +122,6 @@ public String getBlockCoordinates() { StringBuilder sb = new StringBuilder(); sb.append( getPrisonBlock().getBlockName() ); -// sb.append( getPrisonBlock().getBlockNameFormal() ); if ( getLocation() != null ) { sb.append( "::" ); @@ -180,13 +178,6 @@ public void setMined( boolean mined ) { this.mined = mined; } -// public boolean isBlockEvent() { -// return blockEvent; -// } -// public void setBlockEvent( boolean blockEvent ) { -// this.blockEvent = blockEvent; -// } - public boolean isCounted() { return counted; } 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 be4af9ed8..632773694 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 @@ -6,6 +6,7 @@ import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.block.PrisonBlockTypes.InternalBlockTypes; import tech.mcprison.prison.util.Location; +import tech.mcprison.prison.util.Text; /** *

This class embodies the nature of the block and different behaviors, if @@ -24,20 +25,17 @@ public class PrisonBlock public static PrisonBlock AIR; public static PrisonBlock GLASS; public static PrisonBlock PINK_STAINED_GLASS; + public static PrisonBlock SELECTION_WAND; public static PrisonBlock BLAZE_ROD; public static PrisonBlock LAPIS_ORE; public static PrisonBlock IGNORE; public static PrisonBlock NULL_BLOCK; - private PrisonBlockType blockType; private boolean useBlockTypeAsPrefix = false; -// private String blockName; - -// private double chance; - private boolean valid = true; private boolean block = true; + private boolean sellallOnly = false; private boolean legacyBlock = false; @@ -52,6 +50,9 @@ public class PrisonBlock AIR = new PrisonBlock( InternalBlockTypes.AIR.name(), false ); GLASS = new PrisonBlock( InternalBlockTypes.GLASS.name(), true ); PINK_STAINED_GLASS = new PrisonBlock( InternalBlockTypes.PINK_STAINED_GLASS.name(), true ); + SELECTION_WAND = new PrisonBlock( InternalBlockTypes.BLAZE_ROD.name(), false ); + SELECTION_WAND.setDisplayName( "&6Selection Wand" ); + BLAZE_ROD = new PrisonBlock( InternalBlockTypes.BLAZE_ROD.name(), false ); LAPIS_ORE = new PrisonBlock( InternalBlockTypes.LAPIS_ORE.name(), true ); IGNORE = new PrisonBlock( InternalBlockTypes.IGNORE.name(), true ); @@ -77,6 +78,32 @@ public boolean isCustomBlockType() { */ public PrisonBlock( String blockName ) { this( PrisonBlockType.minecraft, blockName, 0, 0); + + // If the blockName as a PrisonBlockType, then strip it off of the blockName + // and set the new name for the block, plus set the BlockType. + for (PrisonBlockType bType : PrisonBlockType.values() ) { + String blockType = bType.name() + ":"; + + if ( blockName.startsWith( blockType ) ) { + blockName = blockName.replace( blockType, blockName ); + setBlockName( blockName ); + setBlockType( bType ); + + break; + } + } + + // If there is still a ':' then everything after that is a formatted displayName. + // Strip it off save it. + if ( getBlockName().contains( ":" ) ) { + String[] bNameDisplayName = getBlockName().split(":"); + + if ( bNameDisplayName.length == 2 ) { + setBlockName( bNameDisplayName[0] ); + setDisplayName( bNameDisplayName[1] ); + } + } + } public PrisonBlock( String blockName, String displayName ) { this( PrisonBlockType.minecraft, blockName, 0, 0); @@ -101,11 +128,6 @@ public PrisonBlock( String blockName, boolean block ) { public PrisonBlock( PrisonBlockType blockType, String blockName, double chance, long blockCountTotal ) { super( blockType, blockName, chance, blockCountTotal ); - this.blockType = blockType; - -// this.blockName = blockName.toLowerCase(); -// this.chance = chance; - } public PrisonBlock( PrisonBlock clonable ) { @@ -114,11 +136,18 @@ public PrisonBlock( PrisonBlock clonable ) { clonable.getChance(), clonable.getBlockCountTotal() ); + this.setDisplayName( clonable.getDisplayName() ); + this.useBlockTypeAsPrefix = clonable.isUseBlockTypeAsPrefix(); this.valid = clonable.isValid(); this.block = clonable.isBlock(); + this.sellallOnly = clonable.isSellallOnly(); + this.legacyBlock = clonable.isLegacyBlock(); + this.setLoreAllowed( clonable.isLoreAllowed() ); + this.setSalePrice( clonable.getSalePrice() ); + this.setPurchasePrice( clonable.getPurchasePrice() ); this.location = clonable == null || clonable.getLocation() == null ? null : new Location( clonable.getLocation() ); @@ -126,23 +155,19 @@ public PrisonBlock( PrisonBlock clonable ) { @Override public String toString() { - return getBlockType().name() + ": " + getBlockName() + - ( getChance() > 0 ? " " + Double.toString( getChance()) : ""); + + StringBuilder sb = new StringBuilder(); + + sb.append( getBlockNameSearch() ); + + if ( getChance() > 0 ) { + sb.append( " " ) + .append( Double.toString( getChance()) ); + } + + return sb.toString(); } - public PrisonBlockType getBlockType() { - return blockType; - } - public void setBlockType( PrisonBlockType blockType ) { - this.blockType = blockType; - } - -// public String getBlockName() { -// return blockName; -// } -// public void setBlockName( String blockName ) { -// this.blockName = blockName; -// } /** *

This function always prefixes the block name with the BlockType. @@ -172,6 +197,10 @@ public String getBlockNameFormal() { * a type of minecraft. *

* + *

If the PrisonBlock has a display name, the color codes are stripped and then + * set to lower case, and spaces are replaced with '_'. Then the block search name is + * appended with the display name preceded with a ':'. + * * @return */ public String getBlockNameSearch() { @@ -181,12 +210,27 @@ public String getBlockNameSearch() { String blockName = getBlockName().toLowerCase(); - String displayName = getDisplayName() != null ? - ":" + getDisplayName().toLowerCase() : ""; + String displayName = getDisplayNameText(); + if ( displayName != null ) { + displayName = ":" + displayName.toLowerCase().replace(" ", "_"); + } + else { + displayName = ""; + } + return blockType + blockName + displayName; } + public String getDisplayNameText() { + String results = getDisplayName(); + + if ( results != null ) { + results = Text.stripColor( results.trim() ); + } + + return results; + } public String getBlockCoordinates() { StringBuilder sb = new StringBuilder(); @@ -250,13 +294,6 @@ public void setUseBlockTypeAsPrefix( boolean useBlockTypeAsPrefix ) { this.useBlockTypeAsPrefix = useBlockTypeAsPrefix; } -// public double getChance() { -// return chance; -// } -// public void setChance( double chance ) { -// this.chance = chance; -// } - public boolean isValid() { return valid; } @@ -271,6 +308,25 @@ public void setBlock( boolean isBlock ){ this.block = isBlock; } + /** + *

If isSellallOnly, this item should never be used within a mine since prison + * cannot regenerate the block to place it in the mines. Custom blocks have + * many uncontrollable aspects on how they create and use blocks, of which + * prison cannot begin to magically guess all of these requirements. + *

+ * + *

If this value is set to true, then the PrisonBlock was added to prison as + * a custom block that is supported only within sellall. + *

+ * + * @return + */ + public boolean isSellallOnly() { + return sellallOnly; + } + public void setSellallOnly(boolean sellallOnly) { + this.sellallOnly = sellallOnly; + } /** *

This value isLegacyBlock indicates that there was not a direct match * with the stored (saved) name of the block, and list of valid block types @@ -380,8 +436,8 @@ public int compareTo( PrisonBlock block ) results = getBlockName().compareToIgnoreCase( block.getBlockName() ); - if ( results == 0 && getDisplayName() != null && block.getDisplayName() != null ) { - results = getDisplayName().compareToIgnoreCase( block.getDisplayName() ); + if ( results == 0 && getBlockNameSearch() != null && block.getBlockNameSearch() != null ) { + results = getBlockNameSearch().compareToIgnoreCase( block.getBlockNameSearch() ); } } } @@ -474,16 +530,6 @@ public void setBlockFace( BlockFace blockFace ) { (( PrisonBlock ) relativeBlock).setPrisonBlock( this ); -// PrisonBlock cloned = this.clone(); -// -// (( PrisonBlock ) relativeBlock).getLocation().setBlockAsync( cloned ); -// -// PrisonBlockType blockType = getBlockType(); -// -// // Set that block with this block's type: -// (( PrisonBlock ) relativeBlock).setBlockType( blockType ); -// (( PrisonBlock ) relativeBlock).setBlockName( getBlockName() ); - } } @@ -504,7 +550,6 @@ public boolean breakNaturally() { @Override public List getDrops() { - // TODO Auto-generated method stub return null; } @@ -515,7 +560,6 @@ public List getDrops() @Override public List getDrops( ItemStack tool ) { - // TODO Auto-generated method stub return null; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java index 0dab4b8d0..74df1befa 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockStatusData.java @@ -42,7 +42,9 @@ public abstract class PrisonBlockStatusData { private boolean gravity = false; -// private transient boolean includeInLayerCalculations; + + private boolean preventDrops = false; + private transient String altAlias; @@ -51,6 +53,10 @@ public abstract class PrisonBlockStatusData { private transient int altCountPhysical; + public PrisonBlockStatusData() { + super(); + } + public PrisonBlockStatusData( PrisonBlockType blockType, String blockName, String displayName, double chance, long blockCountTotal ) { @@ -90,7 +96,8 @@ public PrisonBlockStatusData( this.gravity = checkGravityAffects( blockName ); -// this.includeInLayerCalculations = true; + this.preventDrops = false; + } @@ -144,9 +151,14 @@ public void incrementMiningBlockCount() { } public String toSaveFileFormat() { - return getBlockName() + "-" + getChance() + "-" + getBlockCountTotal() + "-" + - getConstraintMin() + "-" + getConstraintMax() + "-" + - getConstraintExcludeTopLayers() + "-" + getConstraintExcludeBottomLayers(); + return getBlockName() + "-" + + getChance() + "-" + + getBlockCountTotal() + "-" + + getConstraintMin() + "-" + + getConstraintMax() + "-" + + getConstraintExcludeTopLayers() + "-" + + getConstraintExcludeBottomLayers() + "-" + + Boolean.toString( isPreventDrops() ); } @@ -171,13 +183,6 @@ public static PrisonBlock parseFromSaveFileFormat( String blockString ) { results.parseFromSaveFileFormatStats( blockString ); } -// else { -// if ( blockTypeName.equalsIgnoreCase( "gold_ore" ) ) { -// Output.get().logInfo( "### parseFromSaveFile: no results!? [" + -// String.join( ", ", split ) + "]" -// ); -// } -// } } return results; @@ -192,7 +197,6 @@ public void parseFromSaveFileFormatStats( String blockString ) { String[] split = blockString.split("-"); if ( split != null && split.length > 0 ) { -// String blockTypeName = split[0]; // The new way to get the PrisonBlocks: double chance = split.length > 1 ? Double.parseDouble(split[1]) : 0; @@ -201,6 +205,7 @@ public void parseFromSaveFileFormatStats( String blockString ) { int constraintMax = split.length > 4 ? Integer.parseInt(split[4]) : 0; int constraintExcludeTopLayers = split.length > 5 ? Integer.parseInt(split[5]) : 0; int constraintExcludeBottomLayers = split.length > 6 ? Integer.parseInt(split[6]) : 0; + boolean preventDrops = split.length > 7 ? Boolean.parseBoolean(split[7]) : false; setChance( chance ); setBlockCountTotal( blockCount ); @@ -208,13 +213,8 @@ public void parseFromSaveFileFormatStats( String blockString ) { setConstraintMax( constraintMax ); setConstraintExcludeTopLayers( constraintExcludeTopLayers ); setConstraintExcludeBottomLayers( constraintExcludeBottomLayers ); + setPreventDrops(preventDrops); -// if ( blockTypeName.equalsIgnoreCase( "gold_ore" ) ) { -// Output.get().logInfo( "### parseFromSaveFile: [" + -// String.join( ", ", split ) + "] [" + -// block.toSaveFileFormat() + "]" -// ); -// } } } @@ -246,17 +246,19 @@ public String toPlaceholderString() { String percent = fFmt.format(getChance()); -// String spawned = dFmt.format( getResetBlockCount() ); String remaining = dFmt.format( getBlockPlacedCount() - getBlockCountUnsaved() ); String total = PlaceholdersUtil.formattedKmbtSISize( 1.0d * getBlockCountTotal(), dFmt, "" ); sb.append( getBlockName() ).append( " (" ) .append( percent ).append( " pct) " ) -// .append( spawned ) .append( " r: " ).append( remaining ) .append( " T: " ) .append( total ) ; + if ( isPreventDrops() ) { + sb.append( " NoDrops!" ); + } + return sb.toString(); } @@ -387,6 +389,11 @@ private boolean checkGravityAffects( String blockName ) { case "sand": case "red_sand": + case "falling_sand": + case "falling_block": + case "suspicious_sand": + case "suspicious_gravel": + case "gravel": case "white_concrete_powder": @@ -554,14 +561,13 @@ public void setGravity( boolean gravity ) { this.gravity = gravity; } + public boolean isPreventDrops() { + return preventDrops; + } + public void setPreventDrops(boolean preventDrops) { + this.preventDrops = preventDrops; + } - -// public boolean isIncludeInLayerCalculations() { -// return includeInLayerCalculations; -// } -// public void setIncludeInLayerCalculations(boolean includeInLayerCalculations) { -// this.includeInLayerCalculations = includeInLayerCalculations; -// } /** diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java index b5054d682..b6feae6e7 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/block/PrisonBlockTypes.java @@ -58,12 +58,11 @@ private void initializeBlockTypes() { // Add in prison's internal block types here: getBlockTypes().add( PrisonBlock.IGNORE ); -// getBlockTypes().add( PrisonBlock.NULL_BLOCK ); // Map all available blocks to the blockTypesByName map: for ( PrisonBlock pb : getBlockTypes() ) { - getBlockTypesByName().put( pb.getBlockName().toLowerCase(), pb ); + getBlockTypesByName().put( pb.getBlockNameSearch(), pb ); } } @@ -86,30 +85,33 @@ public void addBlockTypes( List blockTypes ) { // Map all available blocks to the blockTypesByName map: for ( PrisonBlock pb : blockTypes ) { + + String blockKey = pb.getBlockNameSearch(); // Check to see if this current block pb already exists, if it does // then set the prefix usage: - if ( getBlockTypesByName().containsKey( pb.getBlockName().toLowerCase() )) { + if ( getBlockTypesByName().containsKey( blockKey ) ) { pb.setUseBlockTypeAsPrefix( true ); } - getBlockTypesByName().put( pb.getBlockName().toLowerCase(), pb ); + + getBlockTypesByName().put( blockKey, pb ); getBlockTypes().add( pb ); - if ( pb.getBlockType() != PrisonBlockType.minecraft ) { - - getBlockTypesByName().put( pb.getBlockNameSearch().toLowerCase(), pb ); - } } } public List getBlockTypes( String searchTerm, boolean restrictToBlocks ) { List results = new ArrayList<>(); + searchTerm = searchTerm.toLowerCase().replace(" ", "_"); + for ( PrisonBlock pBlock : getBlockTypes() ) { - if ( (!restrictToBlocks || restrictToBlocks && pBlock.isBlock()) && - pBlock.getBlockNameSearch().toLowerCase().contains( searchTerm.toLowerCase() )) { + if ( (!restrictToBlocks || + restrictToBlocks && + pBlock.isBlock() && !pBlock.isSellallOnly()) && + pBlock.getBlockNameSearch().contains( searchTerm )) { results.add( pBlock ); } } @@ -140,7 +142,10 @@ public PrisonBlock getBlockTypesByName( String blockName ) { blockName = blockName.toLowerCase(); if ( "air".equals( blockName ) ) { results = PrisonBlock.AIR; + return results; } + + // only minecraft types should not have the prefix: else if ( blockName.startsWith( PrisonBlockType.minecraft.name() + ":" )) { blockName = blockName.replaceAll( PrisonBlockType.minecraft.name() + ":", "" ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/block/BlockBreakEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/block/BlockBreakEvent.java index 2a1fe9915..bc1c9be05 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/block/BlockBreakEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/block/BlockBreakEvent.java @@ -42,9 +42,6 @@ public class BlockBreakEvent public BlockBreakEvent( PrisonBlock block, Location blockLocation, Player player) { this(block,blockLocation,player,0); } -// public BlockBreakEvent(BlockType block, Location blockLocation, Player player) { -// this(block,blockLocation,player,0); -// } public BlockBreakEvent( PrisonBlock block, Location blockLocation, Player player, int xp ) { this.block = block; @@ -53,11 +50,13 @@ public BlockBreakEvent( PrisonBlock block, Location blockLocation, Player player this.exp = xp; } - @Override public boolean isCanceled() { + @Override + public boolean isCanceled() { return canceled; } - @Override public void setCanceled(boolean canceled) { + @Override + public void setCanceled(boolean canceled) { this.canceled = canceled; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/block/BlockPlaceEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/block/BlockPlaceEvent.java index c041b2cfa..6f5258534 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/block/BlockPlaceEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/block/BlockPlaceEvent.java @@ -40,17 +40,14 @@ public BlockPlaceEvent( PrisonBlock block, Location blockLocation, Player player this.blockLocation = blockLocation; this.player = player; } -// public BlockPlaceEvent(BlockType block, Location blockLocation, Player player) { -// this.block = block; -// this.blockLocation = blockLocation; -// this.player = player; -// } - @Override public boolean isCanceled() { + @Override + public boolean isCanceled() { return canceled; } - @Override public void setCanceled(boolean canceled) { + @Override + public void setCanceled(boolean canceled) { this.canceled = canceled; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/BrewEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/BrewEvent.java index 7aab8134f..a5327053b 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/BrewEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/BrewEvent.java @@ -23,8 +23,6 @@ import tech.mcprison.prison.internal.inventory.BrewerInventory; /** - * Currently undocumented. - * * @author DMP9 */ public class BrewEvent implements Cancelable { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/CraftItemEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/CraftItemEvent.java index b0b2a3504..11b5eb540 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/CraftItemEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/CraftItemEvent.java @@ -24,8 +24,6 @@ import tech.mcprison.prison.internal.inventory.Viewable; /** - * Currently undocumented. - * * @author DMP9 */ public class CraftItemEvent extends InventoryClickEvent { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceBurnEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceBurnEvent.java index 6b33c8231..eff044725 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceBurnEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceBurnEvent.java @@ -23,8 +23,6 @@ import tech.mcprison.prison.internal.events.Cancelable; /** - * Currently undocumented. - * * @author DMP9 */ public class FurnaceBurnEvent implements Cancelable { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceExtractEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceExtractEvent.java index cd1f29ec3..2e82cd36c 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceExtractEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceExtractEvent.java @@ -22,8 +22,6 @@ import tech.mcprison.prison.internal.block.PrisonBlock; /** - * Currently undocumented. - * * @author DMP9 */ public class FurnaceExtractEvent { @@ -32,9 +30,6 @@ public class FurnaceExtractEvent { private int expToDrop; private PrisonBlock prisonBlock; -// private Block block; -// private BlockType blockType; - private PrisonBlock blockType; private Player player; diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceSmeltEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceSmeltEvent.java index 999875c01..ce15e7097 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceSmeltEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/FurnaceSmeltEvent.java @@ -23,8 +23,6 @@ import tech.mcprison.prison.internal.events.Cancelable; /** - * Currently undocumented. - * * @author DMP9 */ public class FurnaceSmeltEvent implements Cancelable { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryClickEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryClickEvent.java index 066e05fc7..3884bed8a 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryClickEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryClickEvent.java @@ -23,8 +23,6 @@ import tech.mcprison.prison.internal.inventory.Viewable; /** - * Currently undocumented. - * * @author DMP9 */ public class InventoryClickEvent extends InventoryInteractEvent { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryCloseEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryCloseEvent.java index 23dfc5ba2..eb9fd58bc 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryCloseEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryCloseEvent.java @@ -22,8 +22,6 @@ import tech.mcprison.prison.internal.inventory.Viewable; /** - * Currently undocumented. - * * @author DMP9 */ public class InventoryCloseEvent extends InventoryEvent { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryCreativeEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryCreativeEvent.java index ec2873ab7..74c75a417 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryCreativeEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryCreativeEvent.java @@ -23,8 +23,6 @@ import tech.mcprison.prison.internal.inventory.Viewable; /** - * Currently undocumented. - * * @author DMP9 */ public class InventoryCreativeEvent extends InventoryClickEvent { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryDragEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryDragEvent.java index d18902205..c4cd2a899 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryDragEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryDragEvent.java @@ -26,8 +26,6 @@ import java.util.Set; /** - * Currently undocumented. - * * @author DMP9 */ public class InventoryDragEvent extends InventoryInteractEvent { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryInteractEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryInteractEvent.java index fbabf137b..cb9d3ddae 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryInteractEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryInteractEvent.java @@ -23,8 +23,6 @@ import tech.mcprison.prison.internal.inventory.Viewable; /** - * Currently undocumented. - * * @author DMP9 */ public class InventoryInteractEvent extends InventoryEvent implements Cancelable { @@ -35,11 +33,13 @@ public InventoryInteractEvent(Viewable transaction) { super(transaction); } - @Override public boolean isCanceled() { + @Override + public boolean isCanceled() { return cancel; } - @Override public void setCanceled(boolean canceled) { + @Override + public void setCanceled(boolean canceled) { cancel = canceled; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryMoveItemEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryMoveItemEvent.java index 3682e7f13..3075660ab 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryMoveItemEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryMoveItemEvent.java @@ -23,8 +23,6 @@ import tech.mcprison.prison.internal.inventory.Inventory; /** - * Currently undocumented. - * * @author DMP9 */ public class InventoryMoveItemEvent implements Cancelable { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryOpenEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryOpenEvent.java index bcedbd3b6..0953da08d 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryOpenEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/InventoryOpenEvent.java @@ -23,8 +23,6 @@ import tech.mcprison.prison.internal.inventory.Viewable; /** - * Currently undocumented. - * * @author DMP9 */ public class InventoryOpenEvent extends InventoryEvent implements Cancelable { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/PrepareAnvilEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/PrepareAnvilEvent.java index 055cfa904..193407628 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/PrepareAnvilEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/PrepareAnvilEvent.java @@ -23,8 +23,6 @@ import tech.mcprison.prison.internal.inventory.Viewable; /** - * Currently undocumented. - * * @author DMP9 */ public class PrepareAnvilEvent extends InventoryEvent { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/PrepareItemCraftEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/PrepareItemCraftEvent.java index 008830e64..559e7b4ef 100755 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/PrepareItemCraftEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/inventory/PrepareItemCraftEvent.java @@ -23,8 +23,6 @@ import tech.mcprison.prison.internal.inventory.Viewable; /** - * Currently undocumented. - * * @author DMP9 */ public class PrepareItemCraftEvent extends InventoryEvent { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerChatEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerChatEvent.java index 571559337..a3bb27c0d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerChatEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerChatEvent.java @@ -60,11 +60,13 @@ public void setFormat(String format) { this.format = format; } - @Override public boolean isCanceled() { + @Override + public boolean isCanceled() { return canceled; } - @Override public void setCanceled(boolean canceled) { + @Override + public void setCanceled(boolean canceled) { this.canceled = canceled; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerDropItemEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerDropItemEvent.java index 92146fef0..be5a2e465 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerDropItemEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerDropItemEvent.java @@ -47,11 +47,13 @@ public ItemStack getItemStack() { return itemStack; } - @Override public boolean isCanceled() { + @Override + public boolean isCanceled() { return canceled; } - @Override public void setCanceled(boolean canceled) { + @Override + public void setCanceled(boolean canceled) { this.canceled = canceled; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerSuffocationEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerSuffocationEvent.java index 441f92748..2829a4139 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerSuffocationEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PlayerSuffocationEvent.java @@ -10,7 +10,7 @@ public class PlayerSuffocationEvent private boolean canceled = false; public PlayerSuffocationEvent( Player player ) { - this.player = player; + this.player = player; } public Player getPlayer() { diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PrisonPlayerInteractEvent.java b/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PrisonPlayerInteractEvent.java index 15fe44b74..526eb7940 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PrisonPlayerInteractEvent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/events/player/PrisonPlayerInteractEvent.java @@ -41,20 +41,19 @@ public class PrisonPlayerInteractEvent implements Cancelable { public enum Action { LEFT_CLICK_BLOCK, RIGHT_CLICK_BLOCK; - public static Action fromString( String value ) { - Action results = null; - - if ( value != null ) { - for ( Action action : values() ) - { + public static Action fromString( String value ) { + Action results = null; + + if ( value != null ) { + for ( Action action : values() ) { if ( action.name().equalsIgnoreCase( value.trim() ) ) { results = action; } } - } - - return results; - } + } + + return results; + } } public PrisonPlayerInteractEvent(Player player, ItemStack itemInHand, Action action, @@ -81,11 +80,13 @@ public Location getClicked() { return clicked; } - @Override public boolean isCanceled() { + @Override + public boolean isCanceled() { return canceled; } - @Override public void setCanceled(boolean canceled) { + @Override + public void setCanceled(boolean canceled) { this.canceled = canceled; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/internal/item/ItemFlag.java b/prison-core/src/main/java/tech/mcprison/prison/internal/item/ItemFlag.java index 806d3fab7..4545cc855 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/internal/item/ItemFlag.java +++ b/prison-core/src/main/java/tech/mcprison/prison/internal/item/ItemFlag.java @@ -2,9 +2,16 @@ /** * @author Faizaan A. Datoo + * + * @deprecated Not used. */ public enum ItemFlag { - HIDE_ENCHANTS, HIDE_ATTRIBUTES, HIDE_UNBREAKABLE, HIDE_DESTROYS, HIDE_PLACED_ON, HIDE_POTION_EFFECTS +// HIDE_ENCHANTS, +// HIDE_ATTRIBUTES, +// HIDE_UNBREAKABLE, +// HIDE_DESTROYS, +// HIDE_PLACED_ON, +// HIDE_POTION_EFFECTS } 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 94c3d8f51..123baa640 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 @@ -26,6 +26,7 @@ import java.util.UUID; import tech.mcprison.prison.backpacks.PlayerBackpack; +import tech.mcprison.prison.bombs.MineBombEffectsData; import tech.mcprison.prison.commands.PluginCommand; import tech.mcprison.prison.file.YamlFileIO; import tech.mcprison.prison.internal.CommandSender; @@ -73,6 +74,24 @@ public interface Platform { public void getWorldLoadErrors( ChatDisplay display ); + /** + *

Providing a RankPlayer, generate and return a + * platform player object, that is connected to the + * platform, such as bukkit through the spigot platform. + *

+ * + * @param rankPlayer + * @return + */ + public Player getPlatformPlayer(RankPlayer rankPlayer); + + + public RankPlayer getRankPlayer(UUID uuid, String name); + + + public boolean saveRankPlayer(RankPlayer rPlayer); + + /** * Returns the player with the specified name. */ @@ -313,6 +332,16 @@ public default Optional getCommand(String label) { public List getConfigHashKeys(String hashPrefix); + /** + *

This returns a value of true if the given config path exists. + *

+ * + * @param section + * @return + */ + public boolean isConfigSection( String section ); + + public boolean isWorldExcluded( String worldName ); @@ -496,4 +525,6 @@ public String autoCreateMineLinerAssignment(ModuleElement eMine, public Map loadYaml(File file); + public MineBombEffectsData validateMineBombEffect(MineBombEffectsData mineBombEffectsData); + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/jackson/JacksonYaml.java b/prison-core/src/main/java/tech/mcprison/prison/jackson/JacksonYaml.java index 45feaa17e..a9bc1aaee 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/jackson/JacksonYaml.java +++ b/prison-core/src/main/java/tech/mcprison/prison/jackson/JacksonYaml.java @@ -34,6 +34,8 @@ *
  • com.fasterxml.jackson.databind.node.ObjectNode (a Map)
  • * * + * @deprecated Not used. Empty. + * */ public class JacksonYaml { @@ -42,163 +44,7 @@ public JacksonYaml() { } -// /** -// *

    This function will read a yaml file, which loads as a hierarchical -// * map. Then it will flatten the hierarchical map and return it. -// *

    -// * -// * -// * @param file -// */ -// public Map loadYamlConfigFile( File file ) { -// Map map = null; -// -// ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); -// -// // If using something like a custom date formatter, etc: -// mapper.findAndRegisterModules(); -// -// -// try { -// JsonNode tree = mapper.readTree( file ); -// -// map = flattenJson( tree ); -// -//// for (Map.Entry kv : map.entrySet()) { -//// System.out.println(kv.getKey() + ": " + -//// kv.getValue().asText() + " [" + -//// kv.getValue().getClass() + "]"); -//// } -// } -// catch ( IOException e ) { -// Output.get().logError( String.format( "JacksonYaml.loadYamlConfigFile: " + -// "Failure: file= %s :: %s ", file.getAbsoluteFile(), e.getMessage() )); -// } -// -// return map; -// } -// -// -// -// private Map flattenJson(JsonNode input) { -// Map map = new LinkedHashMap<>(); -// flattenJson(input, null, map); -// return map; -// } -// -// private void flattenJson(JsonNode node, String parent, Map map) { -// if (node instanceof ValueNode) { -// map.put(parent, (ValueNode)node); -// } -// else { -// String prefix = parent == null ? "" : parent + "."; -// if (node instanceof ArrayNode) { -// ArrayNode arrayNode = (ArrayNode)node; -// for(int i = 0; i < arrayNode.size(); i++) { -// flattenJson(arrayNode.get(i), prefix + i, map); -// } -// } -// else if (node instanceof ObjectNode) { -// ObjectNode objectNode = (ObjectNode) node; -// for (Iterator> it = objectNode.fields(); it.hasNext(); ) { -// Map.Entry field = it.next(); -// flattenJson(field.getValue(), prefix + field.getKey(), map); -// } -// } -// else { -// Output.get().logWarn( String.format( "JacksonYaml.flattenJson: " + -// "Warning: Unknown node type. node= %s ", node.getClass())); -// -// } -// } -// } -// -// -// -// /** -// *

    This function will write a flat map to a yaml file after it -// * expands it to an hierarchical map, expanding the key values on -// * their periods. -// *

    -// * -// * @param file Target file to save to -// * @param map A flat map of all the configs -// */ -// public void writeYamlConfigFile( File file, Map map ) { -// -// String filenameTemp = file.getName() + ".tmp.yml"; -// File fileTemp = new File( file.getParentFile(), filenameTemp ); -// -// ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); -// -// // If using something like a custom date formatter, etc: -// mapper.findAndRegisterModules(); -// -// try { -// Map mapExpanded = expandMap( map ); -// -// // Write to the temp file: -// mapper.writeValue( fileTemp, mapExpanded ); -// -// // Delete the original file if it exists: -// if ( file.exists() ) { -// file.delete(); -// } -// -// // Rename the temp file to the actual file: -// fileTemp.renameTo( file ); -// } -// catch ( IOException e ) { -// Output.get().logError( String.format( "JacksonYaml.writeYamlConfigFile: " + -// "Failure: file= %s :: %s ", file.getAbsoluteFile(), e.getMessage() )); -// } -// } -// -// /** -// *

    This takes a flat map and expands the keys, breaking on the periods, -// * and builds a multi-level hierarchy. -// *

    -// * -// * @param map Flat map -// * @return Hierarchical map -// */ -// private Map expandMap( Map map ) { -// Map m = new LinkedHashMap<>(); -// -// for ( Entry node : map.entrySet() ) { -// -// String key = node.getKey(); -// -// if ( key != null ) { -// -// ValueNode value = node.getValue(); -// -// String[] keyz = key.split( "\\." ); -// -// // There are multiple depths and we must place the value at the -// // leaf nodes. getChildExpandedMap traverses all the children -// // to get to the leaf node, making the nodes if needed. -// Map child = getChildExpandedMap(m, keyz, 0); -// -// child.put( keyz[keyz.length-1], value ); -// } -// } -// -// return m; -// } -// -// @SuppressWarnings( "unchecked" ) -// private Map getChildExpandedMap( Map map, String[] keyz, int pos ) { -// if ( pos < keyz.length - 1 ) { -// String key = keyz[pos]; -// if ( !map.containsKey( key ) ) { -// map.put( key, new LinkedHashMap<>() ); -// } -// return getChildExpandedMap( (Map) map.get( key ), keyz, pos + 1); -// } -// -// return map; -// } - + // NOTE: The commented out source was purged. This appears to be a dead class. + // See git history for what was purged. } 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 c8c6f1181..96d5d7c2b 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 @@ -159,9 +159,9 @@ public LocaleManager(PluginEntity module) { public void reload() { - // Reset configs: - configs.clear(); - + // Reset configs: + configs.clear(); + // Always get the config's default-language settings to ensure we are always // accessing the correct files. @@ -193,38 +193,38 @@ public static List getRegisteredInstances() @Override public String toString() { - StringBuilder sb = new StringBuilder(); - - sb.append( "LocalManager: " ).append( module.getName() ) - .append( " Internal Path: " ).append( internalPath ) - .append( " Local Folder:" ).append( getLocalFolder().getAbsolutePath() ); - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + sb.append( "LocalManager: " ).append( module.getName() ) + .append( " Internal Path: " ).append( internalPath ) + .append( " Local Folder:" ).append( getLocalFolder().getAbsolutePath() ); + + return sb.toString(); } public File getLocalDataFolder() { - // Setup the local folders: - File dataFolder = fixPrisonCoreLanguagePath( getOwningPlugin().getModuleDataFolder() ); - File localeDirectory = new File(dataFolder, LOCALE_FOLDER); - - // if the folder does not exist, try to create it: - if ( !localeDirectory.exists() ) { - localeDirectory.mkdirs(); - - // Now copy all of the default language files that are in the prison jar to this new directory. - // This will make it a lot easier for admins to modify the language files. - extractShippedLocales( localeDirectory ); - - } - if ( !localeDirectory.isDirectory() ) { - Output.get().logWarn( - "The Locale Folder is not a directory. [" + - localeDirectory.getAbsolutePath() + "] Plugin: " + - getOwningPlugin() + - " Not able to load custom locales"); - } - - return localeDirectory; + // Setup the local folders: + File dataFolder = fixPrisonCoreLanguagePath( getOwningPlugin().getModuleDataFolder() ); + File localeDirectory = new File(dataFolder, LOCALE_FOLDER); + + // if the folder does not exist, try to create it: + if ( !localeDirectory.exists() ) { + localeDirectory.mkdirs(); + + // Now copy all of the default language files that are in the prison jar to this new directory. + // This will make it a lot easier for admins to modify the language files. + extractShippedLocales( localeDirectory ); + + } + if ( !localeDirectory.isDirectory() ) { + Output.get().logWarn( + "The Locale Folder is not a directory. [" + + localeDirectory.getAbsolutePath() + "] Plugin: " + + getOwningPlugin() + + " Not able to load custom locales"); + } + + return localeDirectory; } protected class PropertyFileFilter @@ -246,22 +246,22 @@ public boolean accept( File dir, String name ) private void refreshLocalLocales() { - // Setup the local folders: - File localeFolder = getLocalDataFolder(); - - // Get a Map of all properties files in the selected directory: - TreeMap localFilesByName = new TreeMap<>(); - File[] localFiles = localeFolder.listFiles( new PropertyFileFilter() ); - - for ( File file : localFiles ) { - LocalManagerPropertyFileData pfd = new LocalManagerPropertyFileData( file ); - localFilesByName.put( pfd.getLocalPropertiesName(), pfd ); - - checkLocalPropertiesStatus( pfd ); + // Setup the local folders: + File localeFolder = getLocalDataFolder(); + + // Get a Map of all properties files in the selected directory: + TreeMap localFilesByName = new TreeMap<>(); + File[] localFiles = localeFolder.listFiles( new PropertyFileFilter() ); + + for ( File file : localFiles ) { + LocalManagerPropertyFileData pfd = new LocalManagerPropertyFileData( file ); + localFilesByName.put( pfd.getLocalPropertiesName(), pfd ); + + checkLocalPropertiesStatus( pfd ); } - // Prison's module properties files in the Prison jar that need to be scanned: + // Prison's module properties files in the Prison jar that need to be scanned: CodeSource cs = getOwningPlugin().getClass().getProtectionDomain().getCodeSource(); if (cs != null) { @@ -271,87 +271,87 @@ private void refreshLocalLocales() { ZipEntry entry; try ( - ZipInputStream zip = new ZipInputStream(jar.openStream()); + ZipInputStream zip = new ZipInputStream(jar.openStream()); ) { - while ( (entry = zip.getNextEntry()) != null) { - String entryName = entry.getName(); - - if (entryName.startsWith(internalPath) && entryName.endsWith(".properties")) { - - String[] arr = entryName.split("/"); - String jarResourceName = arr[arr.length - 1]; - - LocalManagerPropertyFileData pfd = localFilesByName.get( jarResourceName ); - - BufferedInputStream inStream = new BufferedInputStream( zip ); - - if ( pfd != null ) { - // Need to check to see if there the local needs to be updated: - - // Read the whole properties file since it may need to be used more than once - String propertiesData = readInputStream( inStream ); - - - - checkJarPropertiesStatus( pfd, propertiesData, jarResourceName ); - - - if ( pfd.replaceLocalWithJar() ) { - // Replace the local with what's in the jar: - - // Archive the existing file: - archiveOldPropertiesFile( pfd.getLocalPropFile() ); - - File newFile = new File( localeFolder, jarResourceName ); - - - - Files.copy( new ByteArrayInputStream( - propertiesData.getBytes( StandardCharsets.UTF_8 ) ), newFile.toPath() ); - - Output.get().logInfo( "### LocalManager refreshLocalLocales(): Replace Local " + - "Jar. " + pfd.toString() + " Replaced."); - - } - else { - // Do not replace: -// Output.get().logInfo( "### LocalManager refreshLocalLocales(): Keep existing " + -// "local jar. " + pfd.toString() ); - } - - } - else { - // The current Zip Entry does not exist in the local directory. - // Need to extract it. - - File newFile = new File( localeFolder, jarResourceName ); - - if ( newFile.exists() ) { - // Not really sure why the pfd would fail find a resource, but the File exists, - // so archive it since there must be an issue with it. - archiveOldPropertiesFile( newFile ); - } - - Files.copy( inStream, newFile.toPath() ); - - Output.get().logInfo( "### LocalManager refreshLocalLocales(): Local did not exist. " + - "Jar copied to local. " ); - } - } - else { - - } - // Need to close the entry to position to the next entry: - zip.closeEntry(); - - } + while ( (entry = zip.getNextEntry()) != null) { + String entryName = entry.getName(); + + if (entryName.startsWith(internalPath) && entryName.endsWith(".properties")) { + + String[] arr = entryName.split("/"); + String jarResourceName = arr[arr.length - 1]; + + LocalManagerPropertyFileData pfd = localFilesByName.get( jarResourceName ); + + BufferedInputStream inStream = new BufferedInputStream( zip ); + + if ( pfd != null ) { + // Need to check to see if there the local needs to be updated: + + // Read the whole properties file since it may need to be used more than once + String propertiesData = readInputStream( inStream ); + + + + checkJarPropertiesStatus( pfd, propertiesData, jarResourceName ); + + + if ( pfd.replaceLocalWithJar() ) { + // Replace the local with what's in the jar: + + // Archive the existing file: + archiveOldPropertiesFile( pfd.getLocalPropFile() ); + + File newFile = new File( localeFolder, jarResourceName ); + + + + Files.copy( new ByteArrayInputStream( + propertiesData.getBytes( StandardCharsets.UTF_8 ) ), newFile.toPath() ); + + Output.get().logInfo( "### LocalManager refreshLocalLocales(): Replace Local " + + "Jar. " + pfd.toString() + " Replaced."); + + } + else { + // Do not replace: + // Output.get().logInfo( "### LocalManager refreshLocalLocales(): Keep existing " + + // "local jar. " + pfd.toString() ); + } + + } + else { + // The current Zip Entry does not exist in the local directory. + // Need to extract it. + + File newFile = new File( localeFolder, jarResourceName ); + + if ( newFile.exists() ) { + // Not really sure why the pfd would fail find a resource, but the File exists, + // so archive it since there must be an issue with it. + archiveOldPropertiesFile( newFile ); + } + + Files.copy( inStream, newFile.toPath() ); + + Output.get().logInfo( "### LocalManager refreshLocalLocales(): Local did not exist. " + + "Jar copied to local. " ); + } + } + else { + + } + // Need to close the entry to position to the next entry: + zip.closeEntry(); + + } } } catch ( Exception e ) { - e.printStackTrace(); + e.printStackTrace(); } } @@ -391,13 +391,13 @@ private String readInputStream( BufferedInputStream inStream ) private void archiveOldPropertiesFile( File localPropFile ) { - String name = localPropFile.getName(); - - String newName = "_archived_" + name + "_" + getDateTime() + ".txt"; - - File targetName = new File( localPropFile.getParentFile(), newName ); - - localPropFile.renameTo( targetName ); + String name = localPropFile.getName(); + + String newName = "_archived_" + name + "_" + getDateTime() + ".txt"; + + File targetName = new File( localPropFile.getParentFile(), newName ); + + localPropFile.renameTo( targetName ); } private String getDateTime() { @@ -412,7 +412,6 @@ private void checkLocalPropertiesStatus( LocalManagerPropertyFileData pfd ) try ( FileReader fr = new FileReader( pfd.getLocalPropFile() ); -// FileReader fr = new FileReader( pfd.getLocalPropFile(), StandardCharsets.UTF_8 ); // Java 11 ) { prop.load( fr ); @@ -439,132 +438,132 @@ private void checkLocalPropertiesStatus( LocalManagerPropertyFileData pfd ) private void checkJarPropertiesStatus( LocalManagerPropertyFileData pfd, String propertiesData, String jarPath ) { - Properties prop = new Properties(); - - try { - - prop.load( new StringReader( propertiesData ) ); - - boolean hasVersion = prop.containsKey( "messages__version" ); - String version = prop.getProperty( "messages__version" ); - - boolean hasAutoRefresh = prop.containsKey( "messages__auto_refresh" ); - String autoRefresh = prop.getProperty( "messages__auto_refresh" ); - - if ( hasVersion && version != null && !version.trim().isEmpty() ) { - pfd.setJarVersion( version ); - } - pfd.setJarHasAutoReplace( hasAutoRefresh ); - pfd.setJarAutoReplace( autoRefresh != null && "true".equalsIgnoreCase( autoRefresh ) ); - } - catch ( IOException e ) { - Output.get().logWarn( "Unable to open and read a property file within the jar file. " + - "[" + jarPath + "]", e ); - } + Properties prop = new Properties(); + + try { + + prop.load( new StringReader( propertiesData ) ); + + boolean hasVersion = prop.containsKey( "messages__version" ); + String version = prop.getProperty( "messages__version" ); + + boolean hasAutoRefresh = prop.containsKey( "messages__auto_refresh" ); + String autoRefresh = prop.getProperty( "messages__auto_refresh" ); + + if ( hasVersion && version != null && !version.trim().isEmpty() ) { + pfd.setJarVersion( version ); + } + pfd.setJarHasAutoReplace( hasAutoRefresh ); + pfd.setJarAutoReplace( autoRefresh != null && "true".equalsIgnoreCase( autoRefresh ) ); + } + catch ( IOException e ) { + Output.get().logWarn( "Unable to open and read a property file within the jar file. " + + "[" + jarPath + "]", e ); + } } private void loadCustomLocales() { // Setup the local folders: - File localeFolder = getLocalDataFolder(); - - File[] contents = localeFolder.listFiles( new PropertyFileFilter() ); - - if (contents != null) { - for (File locale : contents) { - if (!locale.isDirectory()) { - try ( - InputStream is = new FileInputStream(locale); - ) { - - loadLocale(locale.getName().replace(".properties", ""), is, false); - } - catch (IOException ex) { - Output.get().logWarn( - "Failed to load custom locale " + locale.getName() + - " for plugin " + getOwningPlugin() + " (" + - ex.getMessage() + ")"); - } - } - else { - Output.get().logWarn("Found subfolder " + locale.getName() + - " within locale folder " + LOCALE_FOLDER + - " in data folder for plugin " + getOwningPlugin() + - " - not loading"); - } - } - - - // Get the English properties, and use that to ensure entries exist for all of the other - // languages... if not, then copy over the english value. - Properties enUS = configs.get( DEFAULT_LOCALE ); - if ( enUS != null ) { - boolean forceDefault = false; - - // If the config.yml default lang does not exist in this module, copy enUS to - // be used in it's place: - if ( !configs.containsKey( defaultLocale ) ) { - configs.put( defaultLocale, enUS ); - - // log it - Prison.get().getLocaleLoadInfo().add( String.format( - "&3Module: &7%s &3Locale: &7%s &3Warning: Locale specific file does not exist for this " + - "module so defaulting to &7%s.properties&3.", - module.getName(), defaultLocale, DEFAULT_LOCALE ) ); - forceDefault = true; - } - - Set keys = configs.keySet(); - for ( String key : keys ) - { - if ( !key.equalsIgnoreCase( DEFAULT_LOCALE ) ) { - Properties otherLang = configs.get( key ); - if ( otherLang != null ) { - - int fallbackCount = 0; - - - - for ( String enUSKey : enUS.stringPropertyNames() ) - { - String propValueOther = otherLang.getProperty( enUSKey ); - - if ( propValueOther == null || propValueOther.trim().length() == 0 - ) { - - // Add the english value since it is missing: - otherLang.put( enUSKey, enUS.getProperty( enUSKey ) ); - fallbackCount++; - + File localeFolder = getLocalDataFolder(); + + File[] contents = localeFolder.listFiles( new PropertyFileFilter() ); + + if (contents != null) { + for (File locale : contents) { + if (!locale.isDirectory()) { + try ( + InputStream is = new FileInputStream(locale); + ) { + + loadLocale(locale.getName().replace(".properties", ""), is, false); + } + catch (IOException ex) { + Output.get().logWarn( + "Failed to load custom locale " + locale.getName() + + " for plugin " + getOwningPlugin() + " (" + + ex.getMessage() + ")"); + } + } + else { + Output.get().logWarn("Found subfolder " + locale.getName() + + " within locale folder " + LOCALE_FOLDER + + " in data folder for plugin " + getOwningPlugin() + + " - not loading"); + } + } + + + // Get the English properties, and use that to ensure entries exist for all of the other + // languages... if not, then copy over the english value. + Properties enUS = configs.get( DEFAULT_LOCALE ); + if ( enUS != null ) { + boolean forceDefault = false; + + // If the config.yml default lang does not exist in this module, copy enUS to + // be used in it's place: + if ( !configs.containsKey( defaultLocale ) ) { + configs.put( defaultLocale, enUS ); + + // log it + Prison.get().getLocaleLoadInfo().add( String.format( + "&3Module: &7%s &3Locale: &7%s &3Warning: Locale specific file does not exist for this " + + "module so defaulting to &7%s.properties&3.", + module.getName(), defaultLocale, DEFAULT_LOCALE ) ); + forceDefault = true; + } + + Set keys = configs.keySet(); + for ( String key : keys ) + { + if ( !key.equalsIgnoreCase( DEFAULT_LOCALE ) ) { + Properties otherLang = configs.get( key ); + if ( otherLang != null ) { + + int fallbackCount = 0; + + + + for ( String enUSKey : enUS.stringPropertyNames() ) + { + String propValueOther = otherLang.getProperty( enUSKey ); + + if ( propValueOther == null || propValueOther.trim().length() == 0 + ) { + + // Add the english value since it is missing: + otherLang.put( enUSKey, enUS.getProperty( enUSKey ) ); + fallbackCount++; + + } } - } - - if ( defaultLocale.equalsIgnoreCase( key ) && !forceDefault ) { - - if ( fallbackCount > 0 ) { - // log it - Prison.get().getLocaleLoadInfo().add( String.format( - "&3Module: &7%s &3Locale: &7%s &3Warning: Locale had &7%d &3missing entries " + - "and will fallback to settings from &7%s.properties&3.", - module.getName(), defaultLocale, fallbackCount, DEFAULT_LOCALE ) ); - - } - else { - Prison.get().getLocaleLoadInfo().add( String.format( - "&3Module: &7%s &3Locale language file: &7%s.properties", - module.getName(), defaultLocale ) ); - - - } - } - - } - } - } - - } - } + + if ( defaultLocale.equalsIgnoreCase( key ) && !forceDefault ) { + + if ( fallbackCount > 0 ) { + // log it + Prison.get().getLocaleLoadInfo().add( String.format( + "&3Module: &7%s &3Locale: &7%s &3Warning: Locale had &7%d &3missing entries " + + "and will fallback to settings from &7%s.properties&3.", + module.getName(), defaultLocale, fallbackCount, DEFAULT_LOCALE ) ); + + } + else { + Prison.get().getLocaleLoadInfo().add( String.format( + "&3Module: &7%s &3Locale language file: &7%s.properties", + module.getName(), defaultLocale ) ); + + + } + } + + } + } + } + + } + } } /** @@ -589,7 +588,7 @@ private File fixPrisonCoreLanguagePath( File targetPath ) { if ( !targetPath.getAbsolutePath().startsWith( ModuleManager.getModuleRootDefault().getAbsolutePath() ) ) { targetPath = Module.setupModuleDataFolder( Prison.PSEDUO_MODLE_NAME ); - } + } return targetPath; } @@ -603,7 +602,7 @@ private File fixPrisonCoreLanguagePath( File targetPath ) { */ private void extractShippedLocales( File targetPath ) { - targetPath = fixPrisonCoreLanguagePath( targetPath ); + targetPath = fixPrisonCoreLanguagePath( targetPath ); CodeSource cs = getOwningPlugin().getClass().getProtectionDomain().getCodeSource(); if (cs != null) { @@ -649,15 +648,6 @@ private void extractShippedLocales( File targetPath ) { } -// private void copyStreams(InputStream inStream, OutputStream outStream) -// throws IOException { -// byte[] buf = new byte[8192]; -// int length; -// while ((length = inStream.read(buf)) > 0) { -// outStream.write(buf, 0, length); -// } -// } - private void loadShippedLocales() { CodeSource cs = getOwningPlugin().getClass().getProtectionDomain().getCodeSource(); @@ -671,15 +661,15 @@ private void loadShippedLocales() { ZipInputStream zip = new ZipInputStream(jar.openStream()); ) { - while ((entry = zip.getNextEntry()) != null) { - String entryName = entry.getName(); - if (entryName.startsWith(internalPath) && entryName - .endsWith(".properties")) { - String[] arr = entryName.split("/"); - String localeName = arr[arr.length - 1].replace(".properties", ""); - loadLocale(localeName, zip, true); - } - } + while ((entry = zip.getNextEntry()) != null) { + String entryName = entry.getName(); + if (entryName.startsWith(internalPath) && entryName + .endsWith(".properties")) { + String[] arr = entryName.split("/"); + String localeName = arr[arr.length - 1].replace(".properties", ""); + loadLocale(localeName, zip, true); + } + } } } catch (IOException ex) { @@ -697,32 +687,28 @@ private void loadShippedLocales() { private void loadLocale(String name, InputStream is, boolean printStackTrace) { try { - - Properties temp = new Properties(); - -// temp.load(is); - - // The InputStream is part of a zipEntry so it cannot be closed, or it will close the zip stream - BufferedReader br = new BufferedReader( new InputStreamReader( is, Charset.forName("UTF-8") )); - String line = br.readLine(); - - while ( line != null ) { - if ( !line.startsWith( "#" ) && line.contains( "=" ) ) { - - 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 ); - } - - line = br.readLine(); - } - - + + Properties temp = new Properties(); + + + // The InputStream is part of a zipEntry so it cannot be closed, or it will close the zip stream + BufferedReader br = new BufferedReader( new InputStreamReader( is, Charset.forName("UTF-8") )); + String line = br.readLine(); + + while ( line != null ) { + if ( !line.startsWith( "#" ) && line.contains( "=" ) ) { + + String[] keyValue = line.split( "\\=" ); + String value = (keyValue.length > 1 ? keyValue[1] : ""); // StringEscapeUtils.escapeJava( keyValue[1] ); + + + temp.put( keyValue[0], value ); + } + + line = br.readLine(); + } + + Properties config; if (configs.containsKey(name)) { config = configs.get(name); @@ -763,12 +749,12 @@ public PluginEntity getOwningPlugin() { * @since 1.0 */ public String getDefaultLocale() { - if ( defaultLocale == null ) { - defaultLocale = Prison.get().getPlatform().getConfigString( "default-language", "en_US" ); - if ( defaultLocale == null ) { - defaultLocale = "en_US"; - } - } + if ( defaultLocale == null ) { + defaultLocale = Prison.get().getPlatform().getConfigString( "default-language", "en_US" ); + if ( defaultLocale == null ) { + defaultLocale = "en_US"; + } + } return defaultLocale; } 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 9b32423e0..73d4bc8f8 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 @@ -124,8 +124,8 @@ public boolean isFailSilently() { * @return */ public Localizable setFailSilently() { - this.failSilently = true; - return this; + this.failSilently = true; + return this; } /** @@ -135,8 +135,8 @@ public Localizable setFailSilently() { * @return */ public Localizable setFailNormally() { - this.failSilently = false; - return this; + this.failSilently = false; + return this; } /** @@ -157,17 +157,17 @@ public Localizable setFailNormally() { * @since 1.0 */ public Localizable withReplacements(String... replacements) { - if ( replacements == null ) { - replacements = new String[1]; - replacements[0] = ""; - } - else { - for ( int i = 0; i < replacements.length; i++ ) { - if ( replacements[i] == null ) { - replacements[i] = ""; - } - } - } + if ( replacements == null ) { + replacements = new String[1]; + replacements[0] = ""; + } + else { + for ( int i = 0; i < replacements.length; i++ ) { + if ( replacements[i] == null ) { + replacements[i] = ""; + } + } + } this.replacements = Arrays.copyOf(replacements, replacements.length); this.locReplacements = null; return this; @@ -351,14 +351,14 @@ public String localize() { * @since 1.0 */ public String localizeFor(CommandSender sender) { - String results = - sender instanceof Player ? - localizeIn(getParent().getLocale((Player) sender)) : - localize(); - - results = applySecondaryPlaceholders( sender, results ); - - return results; + String results = + sender instanceof Player ? + localizeIn(getParent().getLocale((Player) sender)) : + localize(); + + results = applySecondaryPlaceholders( sender, results ); + + return results; } /** @@ -376,21 +376,21 @@ public String localizeFor(CommandSender sender) { * @since 1.0 */ public void sendTo(CommandSender sender, LogLevel level) { - String message = localizeFor(sender); - if ( message != null && !message.isEmpty() ) { - - try { - Output.get().sendMessage(sender, message, level); - } - catch (Exception e) { - Output.get().logRaw( - "Tried to send a formatted mmessage to a player but it ended in " - + "failure. Was the original message edited and an extra parameter added? " - + "raw message: [" + - message - + "]"); - } - } + String message = localizeFor(sender); + if ( message != null && !message.isEmpty() ) { + + try { + Output.get().sendMessage(sender, message, level); + } + catch (Exception e) { + Output.get().logRaw( + "Tried to send a formatted mmessage to a player but it ended in " + + "failure. Was the original message edited and an extra parameter added? " + + "raw message: [" + + message + + "]"); + } + } } /** @@ -406,23 +406,23 @@ public void sendTo(CommandSender sender, LogLevel level) { * @param sender The {@link CommandSender} to send this {@link Localizable} to */ public void sendTo(CommandSender sender ) { - PlaceholderStringCoverter placeholderConverter = null; - sendTo( sender, placeholderConverter ); - } - public void sendTo(CommandSender sender, PlaceholderStringCoverter placeholderConverter ) { - - String message = localize(); - if ( message != null && !message.isEmpty() ) { - - if ( placeholderConverter != null ) { - message = placeholderConverter.convertStringPlaceholders(message); - } -// message = applySecondaryPlaceholders( -// (playerStats != null ? playerStats : sender ), -// message ); - - sendTo(sender, LogLevel.PLAIN); - } + PlaceholderStringCoverter placeholderConverter = null; + sendTo( sender, placeholderConverter ); + } + public void sendTo(CommandSender sender, PlaceholderStringCoverter placeholderConverter ) { + + String message = localize(); + if ( message != null && !message.isEmpty() ) { + + if ( placeholderConverter != null ) { + message = placeholderConverter.convertStringPlaceholders(message); + } + // message = applySecondaryPlaceholders( + // (playerStats != null ? playerStats : sender ), + // message ); + + sendTo(sender, LogLevel.PLAIN); + } } /** @@ -432,19 +432,20 @@ public void sendTo(CommandSender sender, PlaceholderStringCoverter placeholderCo * @since 1.0 */ public void broadcast() { - PlaceholderStringCoverter placeholderConverter = null; - broadcast( placeholderConverter ); + PlaceholderStringCoverter placeholderConverter = null; + broadcast( placeholderConverter ); } + public void broadcast( PlaceholderStringCoverter placeholderConverter ) { - - String message = localize(); - if ( message != null && !message.isEmpty() ) { - - for (Player player : Prison.get().getPlatform().getOnlinePlayers()) { - sendTo(player, placeholderConverter); - } - Output.get().logInfo( message ); - } + + String message = localize(); + if ( message != null && !message.isEmpty() ) { + + for (Player player : Prison.get().getPlatform().getOnlinePlayers()) { + sendTo(player, placeholderConverter); + } + Output.get().logInfo( message ); + } } /** @@ -455,16 +456,16 @@ public void broadcast( PlaceholderStringCoverter placeholderConverter ) { * @since 1.0 */ public void broadcast(World... worlds) { - String message = localize(); - if ( message != null && !message.isEmpty() ) { - - for (World w : worlds) { - for (Player player : w.getPlayers()) { - sendTo(player); - } - } - Output.get().logInfo( message ); - } + String message = localize(); + if ( message != null && !message.isEmpty() ) { + + for (World w : worlds) { + for (Player player : w.getPlayers()) { + sendTo(player); + } + } + Output.get().logInfo( message ); + } } /** @@ -478,10 +479,6 @@ private String fromNullableString(String nullable) { return nullable != null ? nullable : ""; } - // Use LogLevel instead since they are the same: -// public enum Level { -// PLAIN, INFO, WARN, ERROR -// } /** diff --git a/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java b/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java index 65a982a9e..87e534110 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java +++ b/prison-core/src/main/java/tech/mcprison/prison/modules/Module.java @@ -32,10 +32,6 @@ */ public abstract class Module implements PluginEntity { - /* - * Fields & Constants - */ - private String name, version; private File moduleDataFolder; @@ -43,10 +39,6 @@ public abstract class Module implements PluginEntity { private ModuleStatus status; private ErrorManager errorManager; - /* - * Constructor - */ - /** * Initialize your module. * @@ -93,9 +85,6 @@ public static File setupModuleDataFolder( String name ) { * @return */ abstract public String getBaseCommands(); - /* - * Methods, to be overridden - */ /** * Called when the module is to be enabled. @@ -126,9 +115,6 @@ protected void fail(String reason) { getStatus().toFailed(reason); } - /* - * Getters & Setters - */ public String getName() { return name; @@ -164,7 +150,13 @@ public String getPackageName() { } public boolean isEnabled() { - return status.getStatus() == ModuleStatus.Status.ENABLED; + boolean results = false; + + if ( status != null && status.getStatus() != null ) { + results = status.getStatus() == ModuleStatus.Status.ENABLED; + } + + return results; } public void setEnabled(boolean enabled) { @@ -189,5 +181,18 @@ public ModuleStatus getStatus() { public File getModuleDataFolder() { return moduleDataFolder; } + + + /** + * For modules that have elements, this will return the count. If a module has no + * elements, then it will return a -1. Otherwise a zero would indicate that a module + * should have elements, but it currently has none. + * + * Example would be ranks and mines. For these, if it returns a zero, then they have + * no ranks or mines defined. If it return a -1 then the module is not active. + * + * @return + */ + abstract public int getElementCount(); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleElement.java b/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleElement.java index 965c64cf2..448b93095 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleElement.java +++ b/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleElement.java @@ -14,7 +14,6 @@ */ public interface ModuleElement { - // private transient final ModuleElementType elementType; public ModuleElementType getModuleElementType(); public int getId(); 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 532424f75..65c8d67cc 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 @@ -72,12 +72,21 @@ public static File getModuleRootDefault() { * Register a new module. */ public void registerModule(Module module) { - if ( getModule(module.getName()) == null ) { - // Module does not exist, so add it: - modules.add(module); - enableModule(module); -// return; // Already added - } + + if ( module != null ) { + + // If module already exists, remove it so it can be added: + if ( getModule(module.getName()) != null ) { + removeModule( module.getName() ); + } + + if ( getModule(module.getName()) == null ) { + // Module does not exist, so add it: + modules.add(module); + enableModule(module); + // return; // Already added + } + } } private void validateVersion(Module module) { @@ -129,7 +138,6 @@ public void unregisterModule(Module module) { disableModule(module); getModules().remove(module); -// getModule(module.getName()).ifPresent(modules::remove); } /** @@ -159,38 +167,52 @@ public void unregisterAll() { * Returns the {@link Module} with the specified name. */ public Module getModule(String name) { - Module results = null; - - for (Module module : getModules() ) { - - if ( module.getName().equalsIgnoreCase(name) ) { - results = module; - break; - } + Module results = null; + + for (Module module : getModules() ) { + + if ( module.getName().equalsIgnoreCase(name) ) { + results = module; + break; + } } - return results; - -// return modules.stream().filter(module -> module.getName().equalsIgnoreCase(name)) -// .findFirst(); + return results; + } + + /** + * Removes a module, if its already been added, by name. + * + * @param name + * @return + */ + public boolean removeModule( String name ) { + Module results = null; + + for (Module module : getModules() ) { + + if ( module.getName().equalsIgnoreCase(name) ) { + results = module; + break; + } + } + + return results == null ? false : getModules().remove( results ); } /** * Returns the {@link Module} with the specified package name. */ public Module getModuleByPackageName(String name) { - Module results = null; - - for (Module module : getModules() ) { - - if ( module.getPackageName().equalsIgnoreCase(name) ) { - results = module; - break; - } + Module results = null; + + for (Module module : getModules() ) { + + if ( module.getPackageName().equalsIgnoreCase(name) ) { + results = module; + break; + } } - return results; - -// return modules.stream().filter(module -> module.getPackageName().equalsIgnoreCase(name)) -// .findFirst(); + return results; } /** @@ -208,40 +230,6 @@ public File getModuleRoot() { return moduleRoot; } -// /** -// * Returns the status of a module (enabled or error message), in the form of a color-coded string. -// * This is meant to show to users. -// * -// * @deprecated Use {@link Module#getStatus()} instead. -// */ -// @Deprecated public String getStatus(String moduleName) { -// Optional moduleOptional = getModule(moduleName); -// return moduleOptional.map(module -> module.getStatus().getMessage()).orElse(null); -// } - -// /** -// * Set the status of a module. -// * -// * @param moduleName The name of the module. -// * @param newStatus The module's status. May include color codes, amp-prefixed. -// * @deprecated Use {@link Module#getStatus()} instead. -// */ -// @Deprecated public void setStatus(String moduleName, String newStatus) { -// Optional moduleOptional = getModule(moduleName); -// if (!moduleOptional.isPresent()) { -// return; -// } -// Module module = moduleOptional.get(); -// -// if (newStatus.toLowerCase().contains("enabled")) { -// module.getStatus().toEnabled(); -// } else if (newStatus.toLowerCase().contains("disabled")) { -// module.getStatus().toDisabled(); -// } else { -// module.getStatus().toFailed(newStatus); -// } -// -// } public boolean isModuleActive(String moduleName) { boolean results = false; diff --git a/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleStatus.java b/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleStatus.java index 9033e5b1d..6e336ee8e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleStatus.java +++ b/prison-core/src/main/java/tech/mcprison/prison/modules/ModuleStatus.java @@ -26,20 +26,12 @@ */ public class ModuleStatus { - /* - * Enums - */ - public enum Status { ENABLED, DISABLED, FAILED } private Status status; - /* - * Fields & Constants - */ - private String message; /** @@ -51,10 +43,6 @@ public void toEnabled() { setMessage("&aEnabled"); } - /* - * Methods - */ - /** * Quickly set a module to the {@link Status#DISABLED} status, and set the message to "Disabled" * in red (c). @@ -93,10 +81,6 @@ public String getStatusText() { } - /* - * Getters & Setters - */ - public void setStatus(Status status) { this.status = status; } @@ -110,11 +94,11 @@ public void setMessage(String message) { } public void addMessage(String message) { - if ( this.message == null ) { - setMessage(message); - } else { - setMessage( getMessage() + ". " + message); - } + if ( this.message == null ) { + setMessage(message); + } else { + setMessage( getMessage() + ". " + message); + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/BulletedListComponent.java b/prison-core/src/main/java/tech/mcprison/prison/output/BulletedListComponent.java index c81163d94..dbdc92ccc 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/BulletedListComponent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/BulletedListComponent.java @@ -40,13 +40,15 @@ public class BulletedListComponent extends DisplayComponent { this.messages = messages; } - @Override public String text() { + @Override + public String text() { List messageStrs = new ArrayList<>(messages.size()); messages.forEach(message -> messageStrs.add(message.toOldMessageFormat())); return Text.implode(messageStrs, "\n"); } - @Override public void send(CommandSender sender) { + @Override + public void send(CommandSender sender) { messages.forEach(message -> message.send(sender)); } @@ -59,8 +61,8 @@ public BulletedListBuilder() { } public BulletedListBuilder add(FancyMessage message) { - bullets.add(message); - return this; + bullets.add(message); + return this; } public BulletedListBuilder add(RowComponent row) { diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/ButtonComponent.java b/prison-core/src/main/java/tech/mcprison/prison/output/ButtonComponent.java index 858819b6a..4697b7c4e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/ButtonComponent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/ButtonComponent.java @@ -72,7 +72,7 @@ public void send(CommandSender sender) { } public FancyMessage getFancyMessage() { - return button; + return button; } /** 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 306300843..e3dbe32cb 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 @@ -32,28 +32,16 @@ */ public class ChatDisplay { - /* - * Fields & Constants - */ - private String title; private LinkedList displayComponents; private boolean showTitle = true; - /* - * Constructor - */ - public ChatDisplay(String title) { this.title = Text.titleize(title); this.displayComponents = new LinkedList<>(); } - /* - * Methods - */ - public ChatDisplay addComponent(DisplayComponent component) { component.setDisplay(this); displayComponents.add(component); @@ -71,19 +59,19 @@ public ChatDisplay addEmptyLine() { } public void send(CommandSender sender) { - if ( isShowTitle() ) { - sender.sendMessage(title); - } - + if ( isShowTitle() ) { + sender.sendMessage(title); + } + for (DisplayComponent component : displayComponents) { component.send(sender); } } public void toLog(LogLevel logLevel) { - if ( isShowTitle() ) { - Output.get().log( title, logLevel ); - } + if ( isShowTitle() ) { + Output.get().log( title, logLevel ); + } for (DisplayComponent component : displayComponents) { Output.get().log( component.text(), logLevel ); @@ -91,9 +79,9 @@ public void toLog(LogLevel logLevel) { } public void sendtoOutputLogInfo() { - if ( isShowTitle() ) { - Output.get().logInfo( title ); - } + if ( isShowTitle() ) { + Output.get().logInfo( title ); + } for (DisplayComponent component : displayComponents) { Output.get().logInfo( component.text() ); @@ -101,11 +89,11 @@ public void sendtoOutputLogInfo() { } public StringBuilder toStringBuilder() { - StringBuilder sb = new StringBuilder(); - - if ( isShowTitle() ) { - sb.append( title ).append( "\n" ); - } + StringBuilder sb = new StringBuilder(); + + if ( isShowTitle() ) { + sb.append( title ).append( "\n" ); + } for (DisplayComponent component : displayComponents) { sb.append( component.text() ).append( "\n" ); @@ -115,17 +103,17 @@ public StringBuilder toStringBuilder() { } public StringBuilder toStringBuilderEscaped() { - StringBuilder sb = new StringBuilder(); - - if ( isShowTitle() ) { - sb.append( title ).append( "\\n" ); - } - - for (DisplayComponent component : displayComponents) { - sb.append( component.text() ).append( "\\n" ); - } - - return sb; + StringBuilder sb = new StringBuilder(); + + if ( isShowTitle() ) { + sb.append( title ).append( "\\n" ); + } + + for (DisplayComponent component : displayComponents) { + sb.append( component.text() ).append( "\\n" ); + } + + return sb; } public void addChatDisplay( ChatDisplay cDisp ) @@ -133,9 +121,9 @@ public void addChatDisplay( ChatDisplay cDisp ) addComponent(new TextComponent(cDisp.getTitle())); - for (DisplayComponent component : cDisp.getDisplayComponents() ) { - addComponent( component ); - } + for (DisplayComponent component : cDisp.getDisplayComponents() ) { + addComponent( component ); + } } protected String getTitle() { diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/DisplayComponent.java b/prison-core/src/main/java/tech/mcprison/prison/output/DisplayComponent.java index 1e790027b..88f2ba3ec 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/DisplayComponent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/DisplayComponent.java @@ -30,16 +30,8 @@ */ public abstract class DisplayComponent { - /* - * Fields & Constants - */ - protected ChatDisplay display; - /* - * Methods - */ - /** * Returns the text that is being appended to the {@link ChatDisplay}. * This should return the raw JSON if {@link tech.mcprison.prison.chat.FancyMessage} is involved. @@ -57,10 +49,6 @@ public abstract class DisplayComponent { */ public abstract void send(CommandSender sender); - /* - * Getters & Setters - */ - void setDisplay(ChatDisplay display) { this.display = display; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/output/FancyMessageComponent.java b/prison-core/src/main/java/tech/mcprison/prison/output/FancyMessageComponent.java index c8769183b..e8485e556 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/output/FancyMessageComponent.java +++ b/prison-core/src/main/java/tech/mcprison/prison/output/FancyMessageComponent.java @@ -42,11 +42,13 @@ public FancyMessage getMessage() { return message; } - @Override public String text() { + @Override + public String text() { return message.toOldMessageFormat(); } - @Override public void send(CommandSender sender) { + @Override + public void send(CommandSender sender) { message.send(sender); } 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 f89c3a5c6..58aa3bb7c 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 @@ -42,7 +42,6 @@ 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; @@ -83,7 +82,9 @@ public enum DebugTarget { rankup, // support - blockConstraints + blockConstraints, + + commandHandler ; public static DebugTarget fromString( String target ) { @@ -142,12 +143,12 @@ private Output() { public static Output get() { if (instance == null) { - synchronized ( Output.class ) { - if (instance == null) { - - new Output(); - - } + synchronized ( Output.class ) { + if (instance == null) { + + new Output(); + + } } } return instance; @@ -187,29 +188,29 @@ private String getLogPrefix( LogLevel level) { } private String getLogColorCode( LogLevel level) { - String colorCode = null; - - switch ( level ) - { - case INFO: - colorCode = colorCodeInfo; - break; - case WARNING: - colorCode = colorCodeWarning; - break; - case ERROR: - colorCode = colorCodeError; - break; - case DEBUG: - colorCode = colorCodeDebug; - break; - - case PLAIN: - default: - colorCode = ""; - break; - } - return colorCode; + String colorCode = null; + + switch ( level ) + { + case INFO: + colorCode = colorCodeInfo; + break; + case WARNING: + colorCode = colorCodeWarning; + break; + case ERROR: + colorCode = colorCodeError; + break; + case DEBUG: + colorCode = colorCodeDebug; + break; + + case PLAIN: + default: + colorCode = ""; + break; + } + return colorCode; } public String format(String message, LogLevel level, Object... args) { @@ -259,89 +260,85 @@ public static String decodePercentEncoding( String message ) { * Log a message with a specified {@link LogLevel} */ public void log(String message, LogLevel level, Object... args) { - if ( message == null || message.trim().isEmpty() ) { - // do not send an empty message... do nothing... - } - else if ( Prison.get() == null || Prison.get().getPlatform() == null ) { - String errorMessage = coreOutputErrorStartupFailureMsg(); - if ( errorMessage == null || errorMessage.trim().isEmpty() ) { - // NOTE: The following must remain as is. This is a fallback for if there - // are major failures in prison. At least it can prefix the messages so they - // can be identified along with the reasons. - errorMessage = "Prison: (Sending to System.err due to Output.log Logger failure):"; - } - - StringBuilder sb = new StringBuilder(); - for ( Object arg : args ) { - sb.append( "[" ).append( arg ).append( "] " ); - } - - System.err.println( errorMessage + " message: [" + message + - "] params: " + sb.toString() ); - } - else { - try { - - String msg = args == null || args.length == 0 ? - message : - String.format(message, args); - - msg = decodePercentEncoding( msg ); -// if ( msg.contains( PERCENT_ENCODING ) ) { -// msg = msg.replace( PERCENT_ENCODING, PERCENT_DECODING ); -// } - - 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 ) - { - StringBuilder sb = new StringBuilder(); + if ( message == null || message.trim().isEmpty() ) { + // do not send an empty message... do nothing... + } + else if ( Prison.get() == null || Prison.get().getPlatform() == null ) { + String errorMessage = coreOutputErrorStartupFailureMsg(); + if ( errorMessage == null || errorMessage.trim().isEmpty() ) { + // NOTE: The following must remain as is. This is a fallback for if there + // are major failures in prison. At least it can prefix the messages so they + // can be identified along with the reasons. + errorMessage = "Prison: (Sending to System.err due to Output.log Logger failure):"; + } + StringBuilder sb = new StringBuilder(); for ( Object arg : args ) { sb.append( "[" ).append( arg ).append( "] " ); } - String errorMessage = coreOutputErrorIncorrectNumberOfParametersMsg( - level.name(), e.getMessage(), message, sb.toString() ); - - Prison.get().getPlatform().logCore( - prefixTemplatePrison + " " + - getLogColorCode(LogLevel.ERROR) + - errorMessage ); - } - catch ( UnknownFormatConversionException | - FormatFlagsConversionMismatchException e) - { - StringBuilder sb = new StringBuilder(); - - for ( Object arg : args ) { - sb.append( "[" ).append( arg ).append( "] " ); + System.err.println( errorMessage + " message: [" + message + + "] params: " + sb.toString() ); + } + else { + try { + + String msg = args == null || args.length == 0 ? + message : + String.format(message, args); + + msg = decodePercentEncoding( 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; + } + } - - String errorMessage = "Error with Java format usage (eg %s): " + - " LogLevel: " + level.name() + - " message: [" + message + "] params: [" + sb.toString() + "]" + - " error: [" + e.getMessage() + "] " + - " Escape with backslash or double percent [\\b \\n \\f \\r \\t \\\\ %%]"; - - Prison.get().getPlatform().logCore( - prefixTemplatePrison + " " + - getLogColorCode(LogLevel.ERROR) + - errorMessage ); - - //e.printStackTrace(); - } - } + catch ( MissingFormatArgumentException e ) + { + StringBuilder sb = new StringBuilder(); + + for ( Object arg : args ) { + sb.append( "[" ).append( arg ).append( "] " ); + } + + String errorMessage = coreOutputErrorIncorrectNumberOfParametersMsg( + level.name(), e.getMessage(), message, sb.toString() ); + + Prison.get().getPlatform().logCore( + prefixTemplatePrison + " " + + getLogColorCode(LogLevel.ERROR) + + errorMessage ); + } + catch ( UnknownFormatConversionException | + FormatFlagsConversionMismatchException e) + { + StringBuilder sb = new StringBuilder(); + + for ( Object arg : args ) { + sb.append( "[" ).append( arg ).append( "] " ); + } + + String errorMessage = "Error with Java format usage (eg %s): " + + " LogLevel: " + level.name() + + " message: [" + message + "] params: [" + sb.toString() + "]" + + " error: [" + e.getMessage() + "] " + + " Escape with backslash or double percent [\\b \\n \\f \\r \\t \\\\ %%]"; + + Prison.get().getPlatform().logCore( + prefixTemplatePrison + " " + + getLogColorCode(LogLevel.ERROR) + + errorMessage ); + + } + } } /** @@ -350,6 +347,7 @@ else if ( Prison.get() == null || Prison.get().getPlatform() == null ) { * @param message The informational message. May include color codes, but the default is white. */ public void logInfo(String message, Object... args) { + log(message, LogLevel.INFO, args); } @@ -361,8 +359,15 @@ public void logInfo(String message, Object... args) { * @param throwable The exceptions thrown, if any. */ public void logWarn(String message, Throwable... throwable) { - log(message, LogLevel.WARNING); + try { + log(message, LogLevel.WARNING); + } + catch (Exception e) { + log( "Failure: Output.logWarn: failed to log an error message. Retrying without formatting.", LogLevel.ERROR ); + logRaw( message ); + } + if (throwable.length > 0) { Arrays.stream(throwable).forEach(Throwable::printStackTrace); } @@ -376,7 +381,14 @@ public void logWarn(String message, Throwable... throwable) { * @param throwable The exceptions thrown, if any. */ public void logError(String message, Throwable... throwable) { - log(message, LogLevel.ERROR); + + try { + log(message, LogLevel.ERROR); + } + catch (Exception e) { + log( "Failure: Output.logError: failed to log an error message. Retrying without formatting.", LogLevel.ERROR ); + logRaw( message ); + } if (throwable.length > 0) { Arrays.stream(throwable).forEach(Throwable::printStackTrace); @@ -602,6 +614,18 @@ public boolean isSelectiveTarget( DebugTarget debugTarget ) { return getSelectiveDebugTargets().contains( debugTarget ); } + /** + *

    This will return a value of true if the debug target was + * enabled by the admin/console. + *

    + * + * @param debugTarget + * @return + */ + public boolean isActiveTarget( DebugTarget debugTarget ) { + return getActiveDebugTargets().contains( debugTarget ); + } + public boolean isDebug() { return debug; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceHolderKey.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceHolderKey.java index 8215c6e73..5ab237de9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceHolderKey.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceHolderKey.java @@ -10,6 +10,9 @@ public class PlaceHolderKey { private boolean primary = true; private String aliasName; + private boolean papiExpansion = false; + private String description = null; + // // NOTE: Pattern is thread safe so make it static. Matcher is not thead safe. // public static Pattern PLACEHOLDER_SEQUENCE_PATTERN = Pattern.compile( "(\\_([0-9]+)\\_)" ); @@ -32,203 +35,6 @@ public PlaceHolderKey( String key, PrisonPlaceHolders placeholder, String data, this.data = data; } -// /** -// *

    This function will take a full text String and apply the placeholder that -// * this PlaceHolderKey represents and tries to match it to the provided text. If it -// * is found within the text, then this function will return the identifier, which is -// * full text, including any placeholder attributes, but without the escape characters. -// *

    -// * -// * @param text -// * @return -// */ -// public PlaceholderResults getIdentifier( String text ) { -// PlaceholderResults results = new PlaceholderResults(this, text); -// -// -// String textLowercase = text.toLowerCase(); -// String key = getKey().toLowerCase(); -// -// -// // For placeholders with sequence numbers, such as _nnn_, will need to search -// // for 1 to 3 digits and replace the number in the "text" with _nnn_ and also -// // need to store that numeric value in the PlaceholderResults object. -// if ( getPlaceholder().hasSequence() ) { -// -// Matcher matcher = PLACEHOLDER_SEQUENCE_PATTERN.matcher( textLowercase ); -// if ( matcher.find() ) { -// -// //String group0 = matcher.group( 0 ); -// String group1 = matcher.group( 1 ); -// String group2 = matcher.group( 2 ); -// -// textLowercase = textLowercase.replace( group1, "_nnn_" ); -// -//// Output.get().logInfo( "### PlaceHolderKey: seq pattern detected: " + placeholder.name() + -//// " group0= " + group0 + " group1= " + group1 + " group2= " + group2 + " replacedText: " + textLowercase ); -// -// results.setNumericSequencePattern( group1 ); -// -// // a value of -1 indicates it was not able to be parsed: -// int parsed = -1; -// -// try { -// parsed = Integer.parseInt( group2 ); -// } -// catch ( NumberFormatException e ) { -// // Not a number so ignore... but based upon matcher.find() it should be... Hmm... -// } -// -// results.setNumericSequence( parsed ); -// -// -// // DO something more: -// -// } -// } -// -// -// // If the text is an exact match to the key (no escape characters): -// if ( textLowercase.equalsIgnoreCase( key ) ) { -// -// results.setIdentifier( textLowercase ); -// results.setPlaceholder( this ); -// -// } -// else { -// -// checkIdentifier( key, text, textLowercase, "{", "}", results ); -// -// if ( textLowercase.equalsIgnoreCase( key ) || -// textLowercase.contains( key ) || -// checkIdentifier( key, text, textLowercase, "{", "}", results ) || -// checkIdentifier( key, text, textLowercase, "%", "%", results ) -// ) { -// -// -// -// // Nothing to do, since it was already done within this if statement. -// -// -//// // Performing all the String searching and indexing can be expensive, especially -//// // since there can be thousands of PlaceHolderKeys on a server. So to provide -//// // a quick proof to see if additional, more complex calculations should be -//// // performed, we'll just see if the text input contains a hit on the key: -//// -//// // Rank in to an issue with placeholders: prison_mbm_minename and prison_mbm_pm, -//// // because the mine P has a placeholder prison_mbm_p which gets hit for the -//// // prison_mbm_pm. So to zero in on the correct placeholder, but bracket the end -//// // of the placeholder with either } or :: to ensure the correct association. -//// String test1 = "{" + key + "}"; -//// String test2 = "{" + key + -//// PlaceholderManager.PRISON_PLACEHOLDER_ATTRIBUTE_SEPARATOR; -//// -//// if ( textLowercase.contains( test1 ) || textLowercase.contains( test2 ) ) { -//// -//// // The key1 and key2 helps ensure that the full placeholder, -//// // including the attribute, is replaced: -//// String key1 = "{" + key; -//// String key2 = "}"; -//// -//// int idx = textLowercase.indexOf( key1 ); -//// int idx2 = ( idx == -1 ? -1 : textLowercase.indexOf( key2, idx + key1.length() - 1 ) ); -//// if ( idx > -1 && idx2 > -1 ) { -//// -//// String identifier = text.substring( idx + 1, idx2 ); -//// results.setIdentifier( identifier ); -////// results = results.replace("{" + identifier + "}", -////// pm.getTranslatePlayerPlaceHolder( playerUuid, playerName, identifier ) ); -//// } -//// } -// -// } -// } -// -// -// return results; -// } - - -// private boolean checkIdentifier( String key, String text, String textLowercase, -// String escLeft, String escRight, PlaceholderResults results ) { -// boolean foundIdentifier = false; -// -// // Performing all the String searching and indexing can be expensive, especially -// // since there can be thousands of PlaceHolderKeys on a server. So to provide -// // a quick proof to see if additional, more complex calculations should be -// // performed, we'll just see if the text input contains a hit on the key: -// -// // Rank in to an issue with placeholders: prison_mbm_minename and prison_mbm_pm, -// // because the mine P has a placeholder prison_mbm_p which gets hit for the -// // prison_mbm_pm. So to zero in on the correct placeholder, but bracket the end -// // of the placeholder with either } or :: to ensure the correct association. -// String test1 = escLeft + key + escRight; -// String test2 = escLeft + key + -// PlaceholderManager.PRISON_PLACEHOLDER_ATTRIBUTE_SEPARATOR; -// -// int adjustment = 0; -// // If the text contains a sequence, then calculate the adjustment position based upon -// // the length of '_nnn_' compared to the original value. -// // These adjustments will align properly with 'text'. -// if ( results.getNumericSequence() >= 0 && results.getNumericSequencePattern() != null ) { -// adjustment = 5 - results.getNumericSequencePattern().length(); -// } -// -// // Warning this is not case insensitive in the results: -// if ( textLowercase.contains( test1 ) ) { -// -// int idx = textLowercase.indexOf( test1 ); -// int idxStart = idx + 1; -// -// -// int idxEnd = idx + test1.length() - 1 - adjustment; -// String identifier = text.substring( idxStart, idxEnd); -// -// results.setIdentifier( identifier, escLeft, escRight ); -// results.setPlaceholder( this ); -// -//// results.setIdentifier( key, escLeft, escRight ); -// foundIdentifier = true; -// } -// else if ( text.contains( test2 ) ) { -// -// // The key1 and key2 helps ensure that the full placeholder, -// // including the attribute, is replaced: -// String key1 = test2; -// String key2 = escRight; -// -// int idx = text.indexOf( key1 ); -// int idx2 = ( idx == -1 ? -1 : text.indexOf( key2, idx + key1.length() - 1 ) ) - adjustment; -// if ( idx > -1 && idx2 > -1 ) { -// -// String identifier = text.substring( idx + 1, idx2 ); -// -// results.setIdentifier( identifier, escLeft, escRight ); -// results.setPlaceholder( this ); -// -// foundIdentifier = true; -//// results = results.replace("{" + identifier + "}", -//// pm.getTranslatePlayerPlaceHolder( playerUuid, playerName, identifier ) ); -// } -// } -//// else if ( textLowercase.contains( key ) ) { -//// -//// int idx = textLowercase.indexOf( key ); -//// int idxStart = idx + 1; -//// -//// -//// int idxEnd = idx + key.length() - 1 - adjustment; -//// String identifier = text.substring( idxStart, idxEnd); -//// -//// results.setIdentifier( identifier, "", "" ); -//// results.setPlaceholder( this ); -//// -////// results.setIdentifier( key, escLeft, escRight ); -//// foundIdentifier = true; -//// } -// -// return foundIdentifier; -// } @Override public String toString() { @@ -276,4 +82,18 @@ public String getAliasName() { public void setAliasName( String aliasName ) { this.aliasName = aliasName; } + + public boolean isPapiExpansion() { + return papiExpansion; + } + public void setPapiExpansion(boolean papiExpansion) { + this.papiExpansion = papiExpansion; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } } 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 b3602f68d..3cc93b0a6 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 @@ -219,10 +219,8 @@ public void setBarConfig( PlaceholderProgressBarConfig barConfig ) { @Override public String format( String value ) { - // TODO Auto-generated method stub - return null; + return value; } - } 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 023e5e733..6d19db18d 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 @@ -229,9 +229,6 @@ public String format( Double value ) { break; } -// if ( results.contains( "^|^" ) ) { -// //results = results.replace( "^|^", "&" ); -// } } catch (Exception e ) { 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 06d75ed15..e16c4b93b 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 @@ -43,6 +43,25 @@ * * * + *

    Please note that there are a couple of different ways you can enter hex codes + * in prison, and in turn, placeholder attributes. + *

    + * + *

    If you use a hex code of `𞉀` then using 'hex', it will be translated as + * `&x&1&2&3&4&5&6`. hex2 would get translated as `§x§1§2§3§4§5§5`. This is actually + * somewhat odd, since even `&x&1&2&3&4&5&6` will ultimately be passed to the raw + * underlying bukkit handler as `§x§1§2§3§4§5§5`, but what makes it odd is that sometimes + * 'hex' works differently than 'hex2'. Disclaimer.. I may have misread the source + * code that I wrote a few years ago, and `hex2` may be something slightly different. + * Too see the actual content, enable `debug` in your attribute and see exactly how + * its passed. + *

    + * + *

    There is another way to use hex codes too, and that is to use them as '#123456' + * without the leading '&'. Without using '&' color code, prison will allow the + * raw '#123456' hex code to be passed along, unchanged by prison. So the target + * plugin, or bukkit/spigot/paper will have to be able to handle that natively. + *

    * */ public class PlaceholderAttributeText 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 index b96edc9c4..7edb38e48 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeTime.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderAttributeTime.java @@ -1,13 +1,10 @@ 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; @@ -77,15 +74,6 @@ public class PlaceholderAttributeTime 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. 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 a9409b9d4..653e1efc6 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 @@ -5,6 +5,7 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.ranks.data.RankPlayer; public class PlaceholderIdentifier { @@ -176,29 +177,11 @@ public boolean checkPlaceholderKey(PlaceHolderKey placeHolderKey) { * @param playerName */ public void setPlayer( UUID playerUuid, String playerName ) { - Player player = null; - if ( playerUuid != null ) { - - player = Prison.get().getPlatform().getPlayer( playerUuid ).orElse( null ); - } - - if ( player == null && playerName != null ) { - - player = Prison.get().getPlatform().getPlayer( playerName ).orElse( null ); - } + RankPlayer rPlayer = Prison.get().getPlatform().getRankPlayer( playerUuid, playerName ); - if ( player == null && playerUuid != null ) { + Player player = Prison.get().getPlatform().getPlatformPlayer( rPlayer ); - player = Prison.get().getPlatform().getOfflinePlayer( playerUuid ).orElse( null ); - } - - if ( player == null && playerName != null ) { - - player = Prison.get().getPlatform().getOfflinePlayer( playerName ).orElse( null ); - } - - if ( player != null ) { setPlayer(player); } 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 b3cf4bfe7..461e7d367 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 @@ -12,6 +12,8 @@ public class PlaceholderManager { public static final String PRISON_PLACEHOLDER_PREFIX = "prison"; public static final String PRISON_PLACEHOLDER_PREFIX_EXTENDED = PRISON_PLACEHOLDER_PREFIX + "_"; + public static final String PRISON_PLACEHOLDER_CUSTOM_PREFIX_EXTENDED = PRISON_PLACEHOLDER_PREFIX + "__"; + public static final String PRISON_PLACEHOLDER_MINENAME_SUFFIX = "_minename"; public static final String PRISON_PLACEHOLDER_LADDERNAME_SUFFIX = "_laddername"; public static final String PRISON_PLACEHOLDER_RANKNAME_SUFFIX = "_rankname"; @@ -29,133 +31,136 @@ public class PlaceholderManager { public static Pattern PLACEHOLDER_ESCAPE_CHARACTER_RIGHT_PATTERN = Pattern.compile( "(\\p{Punct}$)" ); -// private PlaceholderProgressBarConfig progressBarConfig; public enum placeholderFlagType { - supress, - sequence, - normal + supress, + sequence, + normal } public enum PlaceholderFlags { - // PlayerManager - PLAYER, - LADDERS, - - - // RankManager - RANKS, - RANKPLAYERS, - STATSRANKS( true ), - STATSPLAYERS( true ), - - - // MineManager - MINES, - MINEPLAYERS, - PLAYERBLOCKS, - STATSMINES( true ), - - - - SUPRESS, - ALIAS, - ONLY_DEFAULT_OR_PRESTIGES - ; - - private final boolean sequence; - - @SuppressWarnings("unused") - private final String desc; - - private PlaceholderFlags() { - this.sequence = false; - this.desc = null; - } - private PlaceholderFlags( boolean hasSequence ) { - this.sequence = hasSequence; - this.desc = null; - } + // PlayerManager + PLAYER, + LADDERS, + + + // RankManager + RANKS, + RANKPLAYERS, + STATSRANKS( true ), + STATSPLAYERS( true ), + + + // MineManager + MINES, + MINEPLAYERS, + PLAYERBLOCKS, + STATSMINES( true ), + + // A custom prison placeholder is one that starts with `prison__` and it cannot have any + // placeholder attributes. Basically, it's a substitution of the custom placeholder + // with whatever has been paired to it within the config.yml file. The mappings can + // be as long as needed and contain any other combination of other placeholders. + CUSTOM, + + SUPRESS, + ALIAS, + ONLY_DEFAULT_OR_PRESTIGES + ; - /** - *

    This identifies if a placeholder type contains a sequence as - * part of its placeholder name. For example a sequence would be - * identified as '_nnn_' where 'n' represents a positive number and - * can be 1 digit in length or more. Three 'n's are used to represent - * this numeric sequence, but does not require it to be three digits - * in length. The number may also be left-padded with zeros; as long - * as it parses successfully with Integer.parse(). - *

    - * - * @return - */ - public boolean hasSequence() { - return sequence; - } + private final boolean sequence; + + @SuppressWarnings("unused") + private final String desc; + + private PlaceholderFlags() { + this.sequence = false; + this.desc = null; + } + private PlaceholderFlags( boolean hasSequence ) { + this.sequence = hasSequence; + this.desc = null; + } + + /** + *

    This identifies if a placeholder type contains a sequence as + * part of its placeholder name. For example a sequence would be + * identified as '_nnn_' where 'n' represents a positive number and + * can be 1 digit in length or more. Three 'n's are used to represent + * this numeric sequence, but does not require it to be three digits + * in length. The number may also be left-padded with zeros; as long + * as it parses successfully with Integer.parse(). + *

    + * + * @return + */ + public boolean hasSequence() { + return sequence; + } } public enum PlaceholderAttributePrefixes { - nFormat, - bar, - text, - time; - - public static PlaceholderAttributePrefixes fromString( String value ) { - PlaceholderAttributePrefixes pap = null; - - if ( value != null ) { - for ( PlaceholderAttributePrefixes attrPrefix : values() ) { - if ( attrPrefix.name().equalsIgnoreCase( value ) ) { - pap = attrPrefix; - } - } - } - - return pap; - } + nFormat, + bar, + text, + time; + + public static PlaceholderAttributePrefixes fromString( String value ) { + PlaceholderAttributePrefixes pap = null; + + if ( value != null ) { + for ( PlaceholderAttributePrefixes attrPrefix : values() ) { + if ( attrPrefix.name().equalsIgnoreCase( value ) ) { + pap = attrPrefix; + } + } + } + + return pap; + } } public enum NumberTransformationUnitTypes { - none, - kmg, - kmbt, - binary; - - public static NumberTransformationUnitTypes fromString( String value ) { - NumberTransformationUnitTypes pap = none; - - if ( value != null ) { - for ( NumberTransformationUnitTypes nTrans : values() ) { - if ( nTrans.name().equalsIgnoreCase( value ) ) { - pap = nTrans; - } - } - } + none, + kmg, + kmbt, + binary; + + public static NumberTransformationUnitTypes fromString( String value ) { + NumberTransformationUnitTypes pap = none; + + if ( value != null ) { + for ( NumberTransformationUnitTypes nTrans : values() ) { + if ( nTrans.name().equalsIgnoreCase( value ) ) { + pap = nTrans; + } + } + } - return pap; - } + return pap; + } } 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; - } + 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; + } } /** @@ -197,6 +202,10 @@ public enum PrisonPlaceHolders { no_match__(PlaceholderFlags.SUPRESS), + + custom_placeholder__(PlaceholderFlags.CUSTOM, PlaceholderFlags.SUPRESS), + + // Rank aliases: prison_r(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), prison_rn(PlaceholderFlags.PLAYER, PlaceholderFlags.ALIAS), @@ -699,6 +708,9 @@ public boolean hasAlias() { public boolean isAlias() { return flags.contains( PlaceholderFlags.ALIAS ); } + public boolean isCustomPlaceholder() { + return flags.contains( PlaceholderFlags.CUSTOM ); + } public boolean isSuppressed() { return flags.contains( PlaceholderFlags.SUPRESS ); } @@ -737,16 +749,22 @@ public static PrisonPlaceHolders fromString( String placeHolder ) { if ( placeHolder != null && placeHolder.trim().length() > 0 ) { placeHolder = placeHolder.trim(); - // This allows us to get rid of suppressed placeholders that were used for - // internal matching when placeholder APIs strip off the prefix: - if ( !placeHolder.toLowerCase().startsWith( PRISON_PLACEHOLDER_PREFIX ) ) { - placeHolder = PRISON_PLACEHOLDER_PREFIX + "_" + placeHolder; + if ( placeHolder.startsWith(PRISON_PLACEHOLDER_CUSTOM_PREFIX_EXTENDED) ) { + result = custom_placeholder__; } - - for ( PrisonPlaceHolders ph : values() ) { - if ( ph.name().equalsIgnoreCase( placeHolder ) ) { - result = ph; - break; + else { + + // This allows us to get rid of suppressed placeholders that were used for + // internal matching when placeholder APIs strip off the prefix: + if ( !placeHolder.toLowerCase().startsWith( PRISON_PLACEHOLDER_PREFIX ) ) { + placeHolder = PRISON_PLACEHOLDER_PREFIX + "_" + placeHolder; + } + + for ( PrisonPlaceHolders ph : values() ) { + if ( ph.name().equalsIgnoreCase( placeHolder ) ) { + result = ph; + break; + } } } } @@ -808,6 +826,7 @@ public static List getAllChatList( boolean omitSuppressable) { int totalCount = 0; + int totalAliases = 0; for ( PlaceholderFlags type : PlaceholderFlags.values() ) { if ( type == PlaceholderFlags.ALIAS || type == PlaceholderFlags.SUPRESS ) { @@ -866,30 +885,65 @@ else if ( type == PlaceholderFlags.STATSRANKS ) { int count = 0; + int aliases = 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() )) { + if ( ph.getFlags().contains( type ) ) { - if ( !hasDeprecated && ph.isSuppressed() ) { - hasDeprecated = true; + if ( !isRanksEnabled && ( + type == PlaceholderFlags.PLAYER && ph.name().toLowerCase().contains("rank") )) { + + // do nothing since ranks is not enabled: } - results.add( " " + ph.getChatText() ); - - count++; - totalCount++; + else if ( + !omitSuppressable || + omitSuppressable && !ph.isSuppressed() && !ph.isAlias() ) { + + if ( !hasDeprecated && ph.isSuppressed() ) { + hasDeprecated = true; + } + + results.add( " " + ph.getChatText() ); + + count++; + totalCount++; + if ( ph.getAlias() != null && ph.getAlias().isAlias() ) { + aliases++; + totalAliases++; + } + + } + else if ( ph == custom_placeholder__ ) { + // Get the list of custom placeholders: + PrisonCustomPlaceholders cp = new PrisonCustomPlaceholders(); + List phKeys = cp.getTranslatedPlaceHolderKeys(); + + for (PlaceHolderKey phKey : phKeys) { + + results.add( " &a" + phKey.getKey() + + (phKey.isPapiExpansion() ? " &d(papi_expansion)" : "") ); + + if ( phKey.getData() != null ) { + results.add( " \\Q" + phKey.getData() + "\\E" ); + } + + if ( phKey.getDescription() != null && phKey.getDescription().trim().length() > 0 ) { + results.add( " &b" + phKey.getDescription() ); + } + + + count++; + totalCount++; + } + } } + + } results.set( pos, results.get( pos ) + - " (" + (count * 2) + ", " + count + " aliases):"); + " (" + (count + aliases) + ", " + aliases + " aliases):"); } @@ -898,7 +952,7 @@ else if ( type == PlaceholderFlags.STATSRANKS ) { } results.add( 0, "&7Available PlaceHolders" + - " (" + (totalCount * 2) + ", " + totalCount + " aliases):"); + " (" + (totalCount + totalAliases) + ", " + totalAliases + " aliases):"); return results; } @@ -917,80 +971,6 @@ private static String getAllChatTexts( boolean omitSuppressable) { } - -// /** -// *

    This will extract attributes from dynamic placeholders and will return. -// *

    -// * -// *

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

    -// * -// *
    ::nFormat:0.00{unit}
    for no spaces. -// *
    ::nFormat:#,##0.0+{unit}
    for spaces since + will be converted to spaces. -// * -// * @param placeholder -// * @return -// */ -// public PlaceholderAttribute extractPlaceholderExtractAttribute( String placeholder ) { -// PlaceholderAttribute attribute = null; -// -// if ( placeholder != null ) { -// String[] attributes = placeholder.split( PRISON_PLACEHOLDER_ATTRIBUTE_SEPARATOR ); -// -// // attributes[0] will be the placeholder, so ignore: -// if ( attributes != null && attributes.length > 1 ) { -// for ( int i = 1; i < attributes.length ; i++ ) { -// String rawAttribute = attributes[i]; -// -// if ( rawAttribute != null ) { -// attribute = attributeFactory( rawAttribute ); -// break; -// } -// } -// } -// } -// -// return attribute; -// } - - -// private PlaceholderAttribute attributeFactory( String rawAttribute ) { -// PlaceholderAttribute attribute = null; -// -// if ( rawAttribute != null && !rawAttribute.isEmpty() ) { -// ArrayList parts = new ArrayList<>(); -// parts.addAll( Arrays.asList( rawAttribute.split( PRISON_PLACEHOLDER_ATTRIBUTE_FIELD_SEPARATOR )) ); -// -// if ( parts.size() > 1 ) { -// PlaceholderAttributePrefixes pap = PlaceholderAttributePrefixes.fromString( parts.get( 0 ) ); -// -// switch ( pap ) -// { -// case nFormat: -// attribute = new PlaceholderAttributeNumberFormat( parts, rawAttribute ); -// break; -// -// case bar: -// attribute = new PlaceholderAttributeBar( parts, getProgressBarConfig(), rawAttribute ); -// break; -// -// case text: -// attribute = new PlaceholderAttributeText( parts, rawAttribute ); -// break; -// -// default: -// break; -// } -// -// } -// -// } -// -// return attribute; -// } - public String extractPlaceholderString( String identifier ) { String results = null; @@ -1008,171 +988,4 @@ public String extractPlaceholderString( String identifier ) { return results; } -// public void reloadPlaceholderBarConfig() { -// setProgressBarConfig( loadPlaceholderBarConfig() ); -// } -// -// public PlaceholderProgressBarConfig loadPlaceholderBarConfig() { -// PlaceholderProgressBarConfig config = null; -// -// String barSegmentsStr = Prison.get().getPlatform().getConfigString( -// "placeholder.bar-segments" ); -// String barPositiveColor = Prison.get().getPlatform().getConfigString( -// "placeholder.bar-positive-color" ); -// String barPositiveSegment = Prison.get().getPlatform().getConfigString( -// "placeholder.bar-positive-segment" ); -// String barNegativeColor = Prison.get().getPlatform().getConfigString( -// "placeholder.bar-negative-color" ); -// String barNegativeSegment = Prison.get().getPlatform().getConfigString( -// "placeholder.bar-negative-segment" ); -// -// -// // All 5 must not be null: -// if ( barSegmentsStr != null && barPositiveColor != null && barPositiveSegment != null && -// barNegativeColor != null && barNegativeSegment != null ) { -// -// int barSegments = 20; -// -// try { -// barSegments = Integer.parseInt( barSegmentsStr ); -// } -// catch ( NumberFormatException e ) { -// Output.get().logWarn( -// "IntegrationManager.loadPlaceholderBarConfigs(): Failure to convert the" + -// "/plugins/Prison/config.yml prison-placeholder-configs.progress-bar.bar-segments " + -// "to a valid integer. Defaulting to a value of 20 " + -// "[" + barSegmentsStr + "] " + e.getMessage() ); -// -// } -// -// config = new PlaceholderProgressBarConfig( barSegments, -// barPositiveColor, barPositiveSegment, -// barNegativeColor, barNegativeSegment ); -// } -// -// if ( config == null ) { -// // go with default values because the config.yml is not up to date with -// // the default values -// -// config = new PlaceholderProgressBarConfig( -// 20, "&2", "#", "&4", "=" -//// 20, "&2", "â–Š", "&4", "â–’" -// ); -// -// Output.get().logInfo( "The /plugins/Prison/config.yml does not contain the " + -// "default values for the Placeholder Progress Bar." ); -// Output.get().logInfo( "Default values are " + -// "being used. To customize the bar, rename the config.yml and it will be " + -// "regenerated and then edit to restore prior values."); -// -// } -// -// return config; -// } -// -// public PlaceholderProgressBarConfig getProgressBarConfig() { -// if ( progressBarConfig == null ) { -// progressBarConfig = loadPlaceholderBarConfig(); -// } -// return progressBarConfig; -// } -// public void setProgressBarConfig( PlaceholderProgressBarConfig progressBarConfig ) { -// this.progressBarConfig = progressBarConfig; -// } -// -// /** -// *

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

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

    -// * -// *

    The lowest range is always zero and

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

    -// * -// *

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

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

    -// * -// * @param value A value that is changing. Will be set to zero if negative. Will be -// * set to valueTotal if greater than that amount. -// * @param valueTotal The target value that is non-changing. -// * @param reverse Changes the growth direction of the progress bar. -// * @param attribute -// * @return -// */ -// public String getProgressBar( double value, double valueTotal, boolean reverse, -// PlaceholderAttribute attribute ) { -// StringBuilder sb = new StringBuilder(); -// -// // value cannot be greater than valueTotal: -// if ( value > valueTotal ) { -// value = valueTotal; -// } -// else if ( value < 0 ) { -// value = 0; -// } -// -// // If reverse, then the new value is subtracted from valueTotal: -// if ( reverse ) { -// value = valueTotal - value; -// } -// -// double percent = valueTotal == 0 ? 100d : value / valueTotal * 100.0; -// -// PlaceholderAttributeBar barAttribute = attribute == null || -// !(attribute instanceof PlaceholderAttributeBar) ? null : -// (PlaceholderAttributeBar) attribute; -// -//// Output.get().logInfo( "### @@@ ### getProgressBar: barAttribute: " + -//// ( barAttribute != null ? "true" : "false")); -// -// PlaceholderProgressBarConfig barConfig = -// barAttribute != null ? barAttribute.getBarConfig() : -// getProgressBarConfig(); -// -// String lastColorCode = null; -// int segments = barConfig.getSegments(); -// for ( int i = 0; i < segments; i++ ) { -// double pct = i / ((double)barConfig.getSegments()) * 100.0; -// -// // If the calculated percent is less than the threshold and as long as it's not the last -// // segment, then show a positive. If it's the last segment an it's still less than -// // the percent, then show a negative no matter what to indicate it's not yet there. -// if ( pct < percent && (percent == 100d || percent < 100d && i < segments - 1)) { -// if ( lastColorCode == null || -// !barConfig.getPositiveColor().equalsIgnoreCase( lastColorCode )) { -// sb.append( barConfig.getPositiveColor() ); -// lastColorCode = barConfig.getPositiveColor(); -// } -// sb.append( barConfig.getPositiveSegment() ); -// } -// else { -// if ( lastColorCode == null || -// !barConfig.getNegativeColor().equalsIgnoreCase( lastColorCode )) { -// sb.append( barConfig.getNegativeColor() ); -// lastColorCode = barConfig.getNegativeColor(); -// } -// sb.append( barConfig.getNegativeSegment() ); -// -// } -// } -// -// -// if ( barConfig.isReverse() ) { -// sb.reverse(); -// } -// -// -// return sb.toString(); -// } - - - - } 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 6b7ff9aec..1d219b5cb 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 @@ -266,9 +266,9 @@ else if ( value < 0 ) { // Output.get().logInfo( "### @@@ ### getProgressBar: barAttribute: " + // ( barAttribute != null ? "true" : "false")); - PlaceholderProgressBarConfig barConfig = - attributeBar != null ? attributeBar.getBarConfig() : - getProgressBarConfig(); + PlaceholderProgressBarConfig barConfig = + attributeBar != null ? attributeBar.getBarConfig() : + getProgressBarConfig(); String lastColorCode = null; int segments = barConfig.getSegments(); @@ -303,7 +303,7 @@ else if ( value < 0 ) { } - return sb.toString(); + return sb.toString(); } protected void convertPlaceholderSequence( PlaceholderIdentifier pIdentifier ) { @@ -319,8 +319,8 @@ protected void convertPlaceholderSequence( PlaceholderIdentifier pIdentifier ) { pIdentifier.setIdentifier( pIdentifier.getIdentifier().replace( group1, "_nnn_" ) ); -// Output.get().logInfo( "### PlaceHolderKey: seq pattern detected: " + placeholder.name() + -// " group0= " + group0 + " group1= " + group1 + " group2= " + group2 + " replacedText: " + textLowercase ); +// Output.get().logInfo( "### PlaceHolderKey: seq pattern detected: " + placeholder.name() + +// " group0= " + group0 + " group1= " + group1 + " group2= " + group2 + " replacedText: " + textLowercase ); pIdentifier.setSequencePattern( group1 ); @@ -373,7 +373,7 @@ else if ( pIdentifier.getIdentifierRaw().startsWith( "{" ) ) { } } - else { + else if ( !pIdentifier.getIdentifierRaw().startsWith( "_" ) ) { Matcher matcher = PlaceholderManager.PLACEHOLDER_ESCAPE_CHARACTER_LEFT_PATTERN.matcher( pIdentifier.getIdentifierRaw() ); if ( matcher.find() ) { @@ -394,12 +394,8 @@ else if ( pIdentifier.getIdentifierRaw().startsWith( "{" ) ) { int len = pIdentifier.getIdentifierRaw().length(); pIdentifier.setIdentifierRaw( pIdentifier.getIdentifierRaw().substring(0, len - group0Right.length() ) ); } - } - } - } - } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderResults.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderResults.java index c6cf0ae9c..0af5ca7f1 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderResults.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderResults.java @@ -14,118 +14,114 @@ @Deprecated public class PlaceholderResults { - private String identifier; - - private PlaceHolderKey placeholder; - private String escapeLeft; - private String esccapeRight; - - private String numericSequencePattern; - private int numericSequence = -1; - + // NOTE: This class is no longer used and all the code has been commented out before being purged. - - private String text; - -// public PlaceholderResults( PlaceHolderKey placeholder ) { +// private String identifier; +// +// private PlaceHolderKey placeholder; +// private String escapeLeft; +// private String esccapeRight; +// +// private String numericSequencePattern; +// private int numericSequence = -1; +// +// +// +// private String text; +// +// public PlaceholderResults( PlaceHolderKey placeholder, String text ) { // super(); // // this.placeholder = placeholder; -// this.text = null; -// } - public PlaceholderResults( PlaceHolderKey placeholder, String text ) { - super(); - - this.placeholder = placeholder; - - - this.text = text; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - if ( getPlaceholder() != null ) { - sb.append( getPlaceholder().getPlaceholder().name() ) - .append( " " ) - .append( getEscapeLeft() == null ? "" : getEscapeLeft() ) - .append( getEsccapeRight() == null ? "" : getEsccapeRight() ) - .append( " " ) - .append( getIdentifier() == null ? "" : getIdentifier() ); - - } - else { - sb.append( "-- no match --" ); - } - - return sb.toString(); - } - - public boolean hasResults() { - return getIdentifier() != null && getPlaceholder() != null; - } - - public void setIdentifier( String identifier, String escapeLeft, String esccapeRight ) { - setIdentifier( identifier ); - - setEscapeLeft( escapeLeft ); - setEsccapeRight( esccapeRight ); - } - - - public String getEscapedIdentifier() { - return getEscapeLeft() + getIdentifier() + getEsccapeRight(); - } - - - public PlaceHolderKey getPlaceholder() { - return placeholder; - } - public void setPlaceholder( PlaceHolderKey placeholder ) { - this.placeholder = placeholder; - } - - public String getText() { - return text; - } - public void setText(String text) { - this.text = text; - } - - public String getIdentifier() { - return identifier; - } - public void setIdentifier( String identifier ) { - this.identifier = identifier; - } - - public String getNumericSequencePattern() { - return numericSequencePattern; - } - public void setNumericSequencePattern( String numericSequencePattern ) { - this.numericSequencePattern = numericSequencePattern; - } - - public int getNumericSequence() { - return numericSequence; - } - public void setNumericSequence( int numericSequence ) { - this.numericSequence = numericSequence; - } - - public String getEscapeLeft() { - return escapeLeft; - } - public void setEscapeLeft( String escapeLeft ) { - this.escapeLeft = escapeLeft; - } - - public String getEsccapeRight() { - return esccapeRight; - } - public void setEsccapeRight( String esccapeRight ) { - this.esccapeRight = esccapeRight; - } +// +// +// this.text = text; +// } +// +// @Override +// public String toString() { +// StringBuilder sb = new StringBuilder(); +// +// if ( getPlaceholder() != null ) { +// sb.append( getPlaceholder().getPlaceholder().name() ) +// .append( " " ) +// .append( getEscapeLeft() == null ? "" : getEscapeLeft() ) +// .append( getEsccapeRight() == null ? "" : getEsccapeRight() ) +// .append( " " ) +// .append( getIdentifier() == null ? "" : getIdentifier() ); +// +// } +// else { +// sb.append( "-- no match --" ); +// } +// +// return sb.toString(); +// } +// +// public boolean hasResults() { +// return getIdentifier() != null && getPlaceholder() != null; +// } +// +// public void setIdentifier( String identifier, String escapeLeft, String esccapeRight ) { +// setIdentifier( identifier ); +// +// setEscapeLeft( escapeLeft ); +// setEsccapeRight( esccapeRight ); +// } +// +// +// public String getEscapedIdentifier() { +// return getEscapeLeft() + getIdentifier() + getEsccapeRight(); +// } +// +// +// public PlaceHolderKey getPlaceholder() { +// return placeholder; +// } +// public void setPlaceholder( PlaceHolderKey placeholder ) { +// this.placeholder = placeholder; +// } +// +// public String getText() { +// return text; +// } +// public void setText(String text) { +// this.text = text; +// } +// +// public String getIdentifier() { +// return identifier; +// } +// public void setIdentifier( String identifier ) { +// this.identifier = identifier; +// } +// +// public String getNumericSequencePattern() { +// return numericSequencePattern; +// } +// public void setNumericSequencePattern( String numericSequencePattern ) { +// this.numericSequencePattern = numericSequencePattern; +// } +// +// public int getNumericSequence() { +// return numericSequence; +// } +// public void setNumericSequence( int numericSequence ) { +// this.numericSequence = numericSequence; +// } +// +// public String getEscapeLeft() { +// return escapeLeft; +// } +// public void setEscapeLeft( String escapeLeft ) { +// this.escapeLeft = escapeLeft; +// } +// +// public String getEsccapeRight() { +// return esccapeRight; +// } +// public void setEsccapeRight( String esccapeRight ) { +// this.esccapeRight = esccapeRight; +// } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderStatsData.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderStatsData.java index 9524708b0..710e7c07b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderStatsData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PlaceholderStatsData.java @@ -5,7 +5,6 @@ public class PlaceholderStatsData { private String placeholderId; private PlaceHolderKey placeholderKey; -// private PrisonPlaceHolders placeholder; private int hits = 0; private int failHits = 0; @@ -149,16 +148,10 @@ public void setPlaceholderKey(PlaceHolderKey placeholderKey) { public int getHits() { return hits; } -// private void setHits(int hits) { -// this.hits = hits; -// } public int getFailHits() { return failHits; } -// private void setFailHits(int failHits) { -// this.failHits = failHits; -// } public long getTotalDurationNanos() { return totalDurationNanos; @@ -167,13 +160,8 @@ public void setTotalDurationNanos(long totalDurationNanos) { this.totalDurationNanos = totalDurationNanos; } - public boolean isFailedMatch() { return failedMatch; } -// private void setFailedMatch(boolean failedMatch) { -// this.failedMatch = failedMatch; -// } - } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/Placeholders.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/Placeholders.java index dc970203a..f322d4f9c 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/placeholders/Placeholders.java +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/Placeholders.java @@ -9,9 +9,6 @@ public interface Placeholders { -// public void initializePlaceholderManagers(); - - public Map getPlaceholderDetailCounts(); @@ -24,9 +21,6 @@ public interface Placeholders { public String placeholderTranslate(UUID playerUuid, String playerName, String identifier); -// pu-blic String placeholderTranslateText( String text); - - public String placeholderTranslateText( UUID playerUuid, String playerName, String text); 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 56ad91a77..136e1caad 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 @@ -73,7 +73,6 @@ public PlaceholderStatsData getStats( PlaceholderIdentifier pId ) { // Else create a new cache entry: results = new PlaceholderStatsData( key ); -// getPlaceholders().put( key, results ); // Store this new stats object in the cache. If there is a placeholder fail, then // this will help prevent going through all of the calculations for future 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 101ebca6e..8250b9993 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 @@ -89,44 +89,6 @@ public static String formattedTime( double timeSec ) { return formattedTime; -// StringBuilder sb = new StringBuilder(); -// -// long days = (long)(timeSec / TIME_DAY); -// timeSec -= (days * TIME_DAY); -// if ( days > 0 ) { -// sb.append( days ); -// // y,m,w,d,h,m,s -// sb.append( prefixesTimeUnits.get(3) ).append( " " ); -//// sb.append( "d " ); -// } -// -// long hours = (long)(timeSec / TIME_HOUR); -// timeSec -= (hours * TIME_HOUR); -// if ( sb.length() > 0 || hours > 0 ) { -// sb.append( hours ); -// // y,m,w,d,h,m,s -// sb.append( prefixesTimeUnits.get(4) ).append( " " ); -//// sb.append( "h " ); -// } -// -// long mins = (long)(timeSec / TIME_MINUTE); -// timeSec -= (mins * TIME_MINUTE); -// if ( sb.length() > 0 || mins > 0 ) { -// sb.append( mins ); -// // y,m,w,d,h,m,s -// sb.append( prefixesTimeUnits.get(5) ).append( " " ); -//// sb.append( "m " ); -// } -// -// double secs = (double)(timeSec / TIME_SECOND); -// timeSec -= (secs * TIME_SECOND); -// DecimalFormat dFmt = Prison.get().getDecimalFormat("#0"); -// sb.append( dFmt.format( secs )); -// // y,m,w,d,h,m,s -// sb.append( prefixesTimeUnits.get(6) ).append( " " ); -//// sb.append( "s " ); -// -// return sb.toString(); } /** @@ -147,11 +109,11 @@ public static String formattedMetricSISize( double amount ) { } public static String formattedMetricSISize( double amount, DecimalFormat dFmt, String spaces ) { - StringBuilder unit = new StringBuilder(); - - amount = divBy1000( amount, unit, " kMGTPEZY" ); - - String results = dFmt.format( amount ) + spaces + unit.toString(); + StringBuilder unit = new StringBuilder(); + + amount = divBy1000( amount, unit, " kMGTPEZY" ); + + String results = dFmt.format( amount ) + spaces + unit.toString(); return results.trim(); } @@ -167,16 +129,16 @@ public static String formattedKmbtSISize( double amount, DecimalFormat dFmt, Str } private static double divBy1000( double amount, StringBuilder unit, String units ) { - if ( amount < 1000.0 || units.length() == 1 ) { - unit.append( units.subSequence( 0, 1 ) ); - } - else { - // Div amount by 1000.0 and remove the first character of the units: - amount /= 1000.0; - units = units.substring( 1 ); - amount = divBy1000( amount, unit, units ); - } - return amount; + if ( amount < 1000.0 || units.length() == 1 ) { + unit.append( units.subSequence( 0, 1 ) ); + } + else { + // Div amount by 1000.0 and remove the first character of the units: + amount /= 1000.0; + units = units.substring( 1 ); + amount = divBy1000( amount, unit, units ); + } + return amount; } @@ -187,28 +149,28 @@ public static String formattedPrefixBinarySize( double amount ) { } public static String formattedIPrefixBinarySize( double amount, DecimalFormat dFmt, String spaces ) { - StringBuilder unit = new StringBuilder(); - - amount = divBy1024( amount, unit, 0 ); - - String results = dFmt.format( amount ) + spaces + unit.toString(); + StringBuilder unit = new StringBuilder(); + + amount = divBy1024( amount, unit, 0 ); + + String results = dFmt.format( amount ) + spaces + unit.toString(); return results.trim(); } private static double divBy1024( double amount, StringBuilder unit, int prefixesBinaryPos ) { - if ( prefixesBinary.size() == 0) { - // no prefixesBinary units have been defined, so exit returning the original amount: - } - else if ( amount < 1024.0 || prefixesBinary.size() == (prefixesBinaryPos + 1)) { - unit.append( prefixesBinary.get( prefixesBinaryPos ) ); - } - else { - // Div amount by 1000.0 and then recursively call this function while adding one to pos: - amount /= 1024.0; - amount = divBy1024( amount, unit, prefixesBinaryPos + 1 ); - } - return amount; + if ( prefixesBinary.size() == 0) { + // no prefixesBinary units have been defined, so exit returning the original amount: + } + else if ( amount < 1024.0 || prefixesBinary.size() == (prefixesBinaryPos + 1)) { + unit.append( prefixesBinary.get( prefixesBinaryPos ) ); + } + else { + // Div amount by 1000.0 and then recursively call this function while adding one to pos: + amount /= 1024.0; + amount = divBy1024( amount, unit, prefixesBinaryPos + 1 ); + } + return amount; } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/placeholders/PrisonCustomPlaceholders.java b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PrisonCustomPlaceholders.java new file mode 100644 index 000000000..c12168b26 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/placeholders/PrisonCustomPlaceholders.java @@ -0,0 +1,147 @@ +package tech.mcprison.prison.placeholders; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.internal.platform.Platform; +import tech.mcprison.prison.placeholders.PlaceholderManager.PrisonPlaceHolders; + +public class PrisonCustomPlaceholders + implements ManagerPlaceholders { + + public static final String CUSTOM_PLACEHOLDER_CONFIG_PATH = "placeholder.custom-placeholders"; + + private List translatedPlaceHolderKeys; + + public PrisonCustomPlaceholders() { + + } + + + public String getTranslateCustomPlaceHolder( PlaceholderIdentifier identifier ) { + String results = null; + + List placeHolderKeys = getTranslatedPlaceHolderKeys(); + + for ( PlaceHolderKey placeHolderKey : placeHolderKeys ) { + + if ( identifier.checkPlaceholderKey(placeHolderKey) ) { + + results = placeHolderKey.getData(); + identifier.setText(results); + + break; + } + + } + + return results; + } + + + + public String getTranslateCustomPlaceHolder( UUID playerUuid, String playerName, String identifier ) { + String results = null; + + if ( playerUuid != null ) { + + List placeHolderKeys = getTranslatedPlaceHolderKeys(); + + + PlaceholderIdentifier phIdentifier = new PlaceholderIdentifier( identifier ); + phIdentifier.setPlayer(playerUuid, playerName); + + + for ( PlaceHolderKey placeHolderKey : placeHolderKeys ) { + + if ( phIdentifier.checkPlaceholderKey(placeHolderKey) ) { + + results = placeHolderKey.getData(); + + break; + } + + } + } + + return results; + } + + /** + *

    This checks for custom placeholders and gets their values. + * A custom placeholder can be abbreviated, or expanded. + *

    + * + *

    An abbreviated placeholder only has the text with no other settings: + *

    + *
    +     *   
    +  custom-placeholders:
    +    prison__chat_prefix: "{prison_rank_tag_default}{prison_rank_tag_prestiges}"
    +     * 
    + * + *

    An extended placeholder has more details and settings: + *

    + *
    +  custom-placeholders:
    +    prison__chat_prefix: 
    +      placeholder: "{prison_rank_tag_default}{prison_rank_tag_prestiges}"
    +      papi_expansion: false
    +      
    + */ + @Override + public List getTranslatedPlaceHolderKeys() { + + if ( translatedPlaceHolderKeys == null ) { + translatedPlaceHolderKeys = new ArrayList<>(); + + Platform pf = Prison.get().getPlatform(); + + if ( pf.isConfigSection(CUSTOM_PLACEHOLDER_CONFIG_PATH) ) { + + PrisonPlaceHolders customPlaceholder = PrisonPlaceHolders.custom_placeholder__; + + List keys = pf.getConfigHashKeys(CUSTOM_PLACEHOLDER_CONFIG_PATH); + + + for (String key : keys) { + + String keyPath = CUSTOM_PLACEHOLDER_CONFIG_PATH + "." + key; + + String custExpandedPlaceholderKey = keyPath + ".placeholder"; + String custExpandedPapiExpansionKey = keyPath + ".papi_expansion"; + String custExpandedDescriptionKey = keyPath + ".description"; + + String cePlaceholder = pf.getConfigString( custExpandedPlaceholderKey ); + boolean cePapiExpansion = pf.getConfigBooleanFalse( custExpandedPapiExpansionKey ); + String ceDescription = pf.getConfigString( custExpandedDescriptionKey ); + + String customPlaceholderStr = + cePlaceholder != null ? + cePlaceholder : pf.getConfigString( keyPath ); + + PlaceHolderKey placeholder = new PlaceHolderKey(key, customPlaceholder, customPlaceholderStr ); + placeholder.setPapiExpansion( cePapiExpansion ); + placeholder.setDescription( ceDescription ); + + translatedPlaceHolderKeys.add(placeholder); + } + } + } + return translatedPlaceHolderKeys; + } + + @Override + public void reloadPlaceholders() { + + // clear the class variable so they will regenerate: + translatedPlaceHolderKeys = null; + + // Regenerate the translated placeholders: + getTranslatedPlaceHolderKeys(); + + } + +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java index 96342b3ec..05129e7d3 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/PlayerRank.java @@ -20,10 +20,6 @@ protected PlayerRank( Rank rank ) { this.rank = rank; -// double rankMultiplier = getLadderBasedRankMultiplier( rank ); -// -// setRankCost( rankMultiplier ); -//// this.rankCost = rank.getCost() * (1.0 + rankMultiplier); } protected PlayerRank( Rank rank, double rankMultiplier ) { @@ -32,7 +28,6 @@ protected PlayerRank( Rank rank, double rankMultiplier ) { this.rankMultiplier = rankMultiplier; setRankCost( rankMultiplier ); -// this.rankCost = rank.getCost() * (1.0 + rankMultiplier); } @Override @@ -46,7 +41,6 @@ public void applyMultiplier( double rankMultiplier ) { this.rankMultiplier = rankMultiplier; setRankCost( rankMultiplier ); -// this.rankCost = rank.getCost() * (1.0 + rankMultiplier); } protected void setRankCost( double rankMultiplier ) { @@ -80,105 +74,6 @@ public double getLadderBasedRankMultiplier( Rank rank ) { } -// public static double getRawRankCost( Rank rank ) { -// return rank.getCost(); -// } -// public static void setRawRankCost( Rank rank, double rawCost ) { -// rank.setCost( rawCost ); -// } - -// public static PlayerRank getTargetPlayerRankForPlayer( RankPlayer player, Rank targetRank ) { -// PlayerRank targetPlayerRank = null; -// -// if ( targetRank != null ) { -// -// double targetRankMultiplier = getLadderBaseRankdMultiplier( targetRank ); -// -// PlayerRank pRankForPLayer = player.getRank( targetRank.getLadder() ); -// double existingRankMultiplier = pRankForPLayer == null ? 0 : -// getLadderBaseRankdMultiplier( pRankForPLayer.getRank() ); -// -// // Get the player's total rankMultiplier from the default ladder -// // because they will always have a rank there: -// PlayerRank pRank = player.getRank( "default" ); -// double playerMultipler = pRank == null ? 0 : pRank.getRankMultiplier(); -// -// // So the actual rank multiplier that needs to be used, is based upon the -// // Player's current multiplier PLUS the multiplier for the target rank -// // AND MINUS the multiplier for the current rank the player has within the -// // target rank's ladder. -// double rankMultiplier = playerMultipler + targetRankMultiplier - existingRankMultiplier; -// -// targetPlayerRank = new PlayerRank( targetRank, rankMultiplier ); -// } -// -// return targetPlayerRank; -// } - - -// public PlayerRank getTargetPlayerRankForPlayer( RankPlayer player, Rank targetRank ) { -// return getTargetPlayerRankForPlayer( this, player, targetRank ); -// } - -// public PlayerRank getTargetPlayerRankForPlayer( PlayerRank playerRank, RankPlayer player, Rank targetRank ) -// { -// PlayerRank targetPlayerRank = null; -// -// if ( targetRank != null ) -// { -// -// double targetRankMultiplier = playerRank.getLadderBasedRankMultiplier( targetRank ); -// -// -// PlayerRank pRankForPLayer = player.getLadderRanks().get( targetRank.getLadder() ); -// -// // PlayerRank pRankForPLayer = getRank( player, targetRank.getLadder() ); -// double existingRankMultiplier = pRankForPLayer == null ? 0 -// : playerRank.getLadderBasedRankMultiplier( pRankForPLayer.getRank() ); -// -// // Get the player's total rankMultiplier from the default ladder -// // because they will always have a rank there: -// RankLadder defaultLadder = getDefaultLadder( player ); -// -// PlayerRank pRank = player.getLadderRanks().get( defaultLadder ); -//// PlayerRank pRank = getRank( player, "default" ); -// double playerMultipler = pRank == null ? 0 : pRank.getRankMultiplier(); -// -// // So the actual rank multiplier that needs to be used, is based upon -// // the -// // Player's current multiplier PLUS the multiplier for the target rank -// // AND MINUS the multiplier for the current rank the player has within -// // the -// // target rank's ladder. -// double rankMultiplier = playerMultipler + targetRankMultiplier - existingRankMultiplier; -// -// targetPlayerRank = createPlayerRank( targetRank, rankMultiplier ); -// } -// -// return targetPlayerRank; -// } - - -// private RankLadder getDefaultLadder( RankPlayer player ) -// { -// return player.getPlayerRankDefault().getRank().getLadder(); -//// RankLadder defaultLadder = null; -//// -//// for ( RankLadder ladder : player.getLadderRanks().keySet() ) -//// { -//// if ( ladder.getName().equalsIgnoreCase( "default" ) ) { -//// defaultLadder = ladder; -//// } -//// } -//// -//// return defaultLadder; -// } - -// private PlayerRank createPlayerRank( Rank rank, double rankMultiplier ) { -// PlayerRank results = new PlayerRank( rank, rankMultiplier ); -// -// return results; -// } public Rank getRank() { return rank; @@ -194,16 +89,10 @@ public String getCurrency() { public Double getRankMultiplier() { return rankMultiplier; } -// public void setRankMultiplier( Double rankMultiplier ) { -// this.rankMultiplier = rankMultiplier; -// } public Double getRankCost() { return rankCost; } -// public void setRankCost( Double rankCost ) { -// this.rankCost = rankCost; -// } @Override public int compareTo( PlayerRank pr ) 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 007d2fd87..61d072d58 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 @@ -35,7 +35,7 @@ public class Rank ModuleElement, Comparable { -// // This is to help eliminate RankLadder.PositionRank object: + // This is to help eliminate RankLadder.PositionRank object: private transient int position = -1; // The unique identifier used to distinguish this rank from others - this never changes. @@ -63,11 +63,6 @@ public class Rank private List rankUpCommands; - // permissions in ranks is obsolete and is being removed. It can never work with vault. - // And Access by Ranks replaces this. -// private List permissions; -// private List permissionGroups; - private transient Rank rankPrior; private transient Rank rankNext; @@ -83,33 +78,31 @@ public class Rank private transient final StatsRankPlayerBalance statsPlayerBlance; + private transient boolean dirty = false; + public Rank() { - super(); - - this.rankUpCommands = new ArrayList<>(); - - this.mines = new ArrayList<>(); - this.mineStrings = new ArrayList<>(); - -// this.permissions = new ArrayList<>(); -// this.permissionGroups = new ArrayList<>(); - - this.players = new ArrayList<>(); - - this.statsPlayerBlance = new StatsRankPlayerBalance( this ); + super(); + + this.rankUpCommands = new ArrayList<>(); + + this.mines = new ArrayList<>(); + this.mineStrings = new ArrayList<>(); + + this.players = new ArrayList<>(); + + this.statsPlayerBlance = new StatsRankPlayerBalance( this ); } public Rank( int id, String name, String tag, double cost ) { - this(); - -// this.position = position; - - this.id = id; - this.name = name; - this.tag = tag; - this.cost = cost; + this(); + + + this.id = id; + this.name = name; + this.tag = tag; + this.cost = cost; } /** @@ -121,161 +114,12 @@ public Rank( int id, String name, String tag, double cost ) { * @param name */ protected Rank( String name ) { - this(); - -// this.position = 0; - this.id = 0; - this.name = name; + this(); + + this.id = 0; + this.name = name; } -// @SuppressWarnings( "unchecked" ) -// public Rank(Document document) { -// this(); -// -// try -// { -//// Object pos = document.get("position"); -//// this.position = RankUtil.doubleToInt( pos == null ? 0.0d : pos ); -// -// this.id = RankUtil.doubleToInt(document.get("id")); -// this.name = (String) document.get("name"); -// this.tag = (String) document.get("tag"); -// this.cost = (double) document.get("cost"); -// -// String currency = (String) document.get("currency"); -// this.currency = (currency == null || -// "null".equalsIgnoreCase( currency ) ? null : currency); -// -// getRankUpCommands().clear(); -// Object cmds = document.get("commands"); -// if ( cmds != null ) { -// -// List commands = (List) cmds; -// for ( String cmd : commands ) { -// if ( cmd != null ) { -// getRankUpCommands().add( cmd ); -// } -// } -// -// // This was allowing nulls to be added to the live commands... -//// this.rankUpCommands = (List) cmds; -// } -// -// getMines().clear(); -// getMineStrings().clear(); -// Object minesObj = document.get("mines"); -// if ( minesObj != null ) { -// List mineStrings = (List) minesObj; -// setMineStrings( mineStrings ); -// } -// -// -//// getPermissions().clear(); -//// Object perms = document.get( "permissions" ); -//// if ( perms != null ) { -//// List permissions = (List) perms; -//// for ( String permission : permissions ) { -//// getPermissions().add( permission ); -//// } -//// } -//// -//// -//// getPermissionGroups().clear(); -//// Object permsGroups = document.get( "permissionGroups" ); -//// if ( perms != null ) { -//// List permissionGroups = (List) permsGroups; -//// for ( String permissionGroup : permissionGroups ) { -//// getPermissionGroups().add( permissionGroup ); -//// } -//// } -// -// } -// catch ( Exception e ) -// { -// String message = rankFailureLoadingRanksMsg( Integer.toString( this.id ), -// (this.name == null ? "null" : this.name ), -// e.getMessage() ); -// -// Output.get().logError( message ); -// } -// } - -// public Document toDocument() { -// Document ret = new Document(); -//// ret.put("position", this.position ); -// ret.put("id", this.id); -// ret.put("name", this.name); -// ret.put("tag", this.tag); -// ret.put("cost", this.cost); -// ret.put("currency", this.currency); -// -// List cmds = new ArrayList<>(); -// for ( String cmd : getRankUpCommands() ) { -// // Filters out possible nulls: -// if ( cmd != null ) { -// cmds.add( cmd ); -// } -// } -// ret.put("commands", cmds); -// -// List mineStrings = new ArrayList<>(); -// if ( getMines() != null ) { -// for ( ModuleElement mine : getMines() ) { -// String mineString = mine.getModuleElementType() + "," + mine.getName() + "," + -// mine.getId() + "," + mine.getTag(); -// mineStrings.add( mineString ); -// } -// } -// ret.put("mines", mineStrings); -// -//// ret.put( "permissions", getPermissions() ); -//// ret.put( "permissionGroups", getPermissionGroups() ); -// -// return ret; -// } -// - - -// /** -// *

    Identifies of the Ladder contains a permission. -// *

    -// * -// * @param permission -// * @return -// */ -// public boolean hasPermission( String permission ) { -// boolean results = false; -// -// for ( String perm : getPermissions() ) { -// if ( perm.equalsIgnoreCase( permission ) ) { -// results = true; -// break; -// } -// } -// -// return results; -// } - -// /** -// *

    Identifies if the Ladder contains a permission group. -// *

    -// * -// * @param permissionGroup -// * @return -// */ -// public boolean hasPermissionGroup( String permissionGroup ) { -// boolean results = false; -// -// for ( String perm : getPermissionGroups() ) { -// if ( perm.equalsIgnoreCase( permissionGroup ) ) { -// results = true; -// break; -// } -// } -// -// return results; -// } - public StatsRankPlayerBalance getStatsPlayerBlance() { return statsPlayerBlance; @@ -311,24 +155,23 @@ public void removePlayer( RankPlayer player ) { @Override public String toString() { - return "Rank: " + id + " " + name; + return "Rank: " + id + " " + name; + } + + public String filenameNew() { + return "rank_" + getName(); } - public String filename() { - return "rank_" + id; + public String filenameOld() { + return getId() == -1 ? null : "rank_" + getId(); } public RankLadder getLadder() { -// if ( ladder == null ) { -// -// ladder = PrisonRanks.getInstance().getLadderManager().getLadder( this ); -// } - - return ladder; + return ladder; } public void setLadder( RankLadder ladder ) { - this.ladder = ladder; + this.ladder = ladder; } @@ -354,23 +197,6 @@ public boolean equals(Object o) { // Rank.id is unique and there should never be two with the same rank. return id == rank.id; -// if (id != rank.id) { -// return false; -// } -// if (Double.compare(rank.cost, cost) != 0) { -// return false; -// } -// -// if ( currency != null && rank.currency == null || -// currency != null && rank.currency != null && -// !currency.equals( rank.currency ) ) { -// return false; -// } -// -// if (!name.equals(rank.name)) { -// return false; -// } -// return tag != null ? tag.equals(rank.tag) : rank.tag == null; } @Override @@ -438,9 +264,6 @@ public void resetPosition() { position = -1; } -// public void setPosition( int position ) { -// this.position = position; -// } public int getId() { return id; @@ -502,20 +325,6 @@ public void setRankUpCommands( List rankUpCommands ) { this.rankUpCommands = rankUpCommands; } -// public List getPermissions() { -// return permissions; -// } -// public void setPermissions( List permissions ) { -// this.permissions = permissions; -// } -// -// public List getPermissionGroups() { -// return permissionGroups; -// } -// public void setPermissionGroups( List permissionGroups ) { -// this.permissionGroups = permissionGroups; -// } - public Rank getRankPrior() { return rankPrior; } @@ -559,4 +368,11 @@ public List getPlayers() { return players; } + public boolean isDirty() { + return dirty; + } + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java index d35788ce7..f34d64645 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/RankLadder.java @@ -45,9 +45,6 @@ public class RankLadder -// private int maxPrestige; - - // The commands that are run when this rank is attained. private List rankUpCommands; @@ -55,24 +52,24 @@ public class RankLadder private double rankCostMultiplierPerRank = 0.0d; private boolean applyRankCostMultiplierToLadder = true; - private boolean dirty = false; + private transient boolean dirty = false; public RankLadder() { - super(); - - this.rankUpCommands = new ArrayList<>(); - - this.ranks = new ArrayList<>(); - - this.applyRankCostMultiplierToLadder = true; + super(); + + this.rankUpCommands = new ArrayList<>(); + + this.ranks = new ArrayList<>(); + + this.applyRankCostMultiplierToLadder = true; } public RankLadder( int id, String name ) { - this(); - - this.id = id; - this.name = name; + this(); + + this.id = id; + this.name = name; } @@ -85,140 +82,18 @@ public boolean isPrestiges() { } -// @SuppressWarnings( "unchecked" ) -// public RankLadder(Document document, PrisonRanks prisonRanks) { -// this(); -// -// boolean isDirty = false; -// -// this.id = ConversionUtil.doubleToInt(document.get("id")); -// this.name = (String) document.get("name"); -// -// RankManager rankManager = prisonRanks.getRankManager(); -// -// if ( rankManager == null ) { -// -// RankMessages rMessages = new RankMessages(); -// rMessages.rankFailureLoadingRankManagerMsg( getName(), getId() ); -// -// return; -// } -// -// List> ranksLocal = -// (List>) document.get("ranks"); -// -// getRankUpCommands().clear(); -// Object cmds = document.get("commands"); -// if ( cmds != null ) { -// -// List commands = (List) cmds; -// for ( String cmd : commands ) { -// if ( cmd != null ) { -// getRankUpCommands().add( cmd ); -// } -// } -// -// // This was allowing nulls to be added to the live commands... -//// this.rankUpCommands = (List) cmds; -// } -// -// -// this.ranks = new ArrayList<>(); -// for (LinkedTreeMap rank : ranksLocal) { -// -// -// // The only real field that is important here is rankId to tie the -// // rank back to this ladder. Name helps clarify the contents of the -// // Ladder file. -// int rRankId = ConversionUtil.doubleToInt((rank.get("rankId"))); -// String rRankName = (String) rank.get( "rankName" ); -// -// Rank rankPrison = rankManager.getRank( rRankId ); -// -// if ( rankPrison != null && rankPrison.getLadder() != null ) { -// -// RankMessages rMessages = new RankMessages(); -// rMessages.rankFailureLoadingDuplicateRankMsg( -// rankPrison.getName(), rankPrison.getLadder().getName(), -// getName() ); -// -// isDirty = true; -// } -// else if ( rankPrison != null) { -// -// addRank( rankPrison ); -// -//// Output.get().logInfo( "RankLadder load : " + getName() + -//// " rank= " + rankPrison.getName() + " " + rankPrison.getId() + -//// ); -// -//// // if null look it up from loaded ranks: -//// if ( rRankName == null ) { -//// rRankName = rankPrison.getName(); -//// dirty = true; -//// } -// } -// else { -// // Rank not found. Try to create it? The name maybe wrong. -// String rankName = rRankName != null && !rRankName.trim().isEmpty() ? -// rRankName : "Rank " + rRankId; -// -// // NOTE: The following is valid use of getCost(): -// double cost = getRanks().size() == 0 ? 0 : -// getRanks().get( getRanks().size() - 1 ).getCost() * 3; -// Rank newRank = new Rank( rRankId, rankName, null, cost ); -// -// addRank( newRank ); -// -//// String message = String.format( -//// "Loading RankLadder Error: A rank for %s was not found so it was " + -//// "fabricated: %s id=%d tag=%s cost=%d", getName(), newRank.getName(), newRank.getId(), -//// newRank.getTag(), newRank.getCost() ); -//// Output.get().logError( message ); -// } -// -// } -// -//// this.maxPrestige = RankUtil.doubleToInt(document.get("maxPrestige")); -// -// -// Double rankCostMultiplier = (Double) document.get( "rankCostMultiplierPerRank" ); -// setRankCostMultiplierPerRank( rankCostMultiplier == null ? 0 : rankCostMultiplier ); -// -// -//// getPermissions().clear(); -//// Object perms = document.get( "permissions" ); -//// if ( perms != null ) { -//// List permissions = (List) perms; -//// for ( String permission : permissions ) { -//// getPermissions().add( permission ); -//// } -//// } -//// -//// -//// getPermissionGroups().clear(); -//// Object permsGroups = document.get( "permissionGroups" ); -//// if ( perms != null ) { -//// List permissionGroups = (List) permsGroups; -//// for ( String permissionGroup : permissionGroups ) { -//// getPermissionGroups().add( permissionGroup ); -//// } -//// } -// -// if ( isDirty ) { -// PrisonRanks.getInstance().getLadderManager().save( this ); -// } -// -// } public Document toDocument() { Document ret = new Document(); - ret.put("id", this.id); + + if ( this.id != -1 ) { + ret.put("id", this.id); + } ret.put("name", this.name); List cmds = new ArrayList<>(); for ( String cmd : getRankUpCommands() ) { - // Filters out possible nulls: + // Filters out possible nulls: if ( cmd != null ) { cmds.add( cmd ); } @@ -229,46 +104,39 @@ public Document toDocument() { List> ranksLocal = new ArrayList>(); for ( Rank rank : getRanks() ) { - LinkedTreeMap rnk = new LinkedTreeMap(); - -// rnk.put( "position", rank.getPosition() ); - rnk.put( "rankId", rank.getId() ); - rnk.put( "rankName", rank.getName()); - - ranksLocal.add( rnk ); + LinkedTreeMap rnk = new LinkedTreeMap(); + + + rnk.put( "rankName", rank.getName()); + + ranksLocal.add( rnk ); } ret.put("ranks", ranksLocal); -// ret.put("ranks", this.ranks); ret.put( "rankCostMultiplierPerRank", getRankCostMultiplierPerRank() ); ret.put( "applyRankCostMultiplierToLadder", isApplyRankCostMultiplierToLadder() ); -// ret.put("maxPrestige", this.maxPrestige); - -// ret.put( "permissions", getPermissions() ); -// ret.put( "permissionGroups", getPermissionGroups() ); - return ret; } @Override public String toString() { - return "Ladder: " + name + " ranks: " + (ranks == null ? 0 : ranks.size()); + return "Ladder: " + name + " ranks: " + (ranks == null ? 0 : ranks.size()); } public List getRanks() { - return ranks; + return ranks; } @Override public int compareTo( RankLadder rl ) { - int results = -1; - if ( rl != null ) { - results = getName().compareTo( rl.getName() ); - } + int results = -1; + if ( rl != null ) { + results = getName().compareTo( rl.getName() ); + } return results; } @@ -281,16 +149,41 @@ public int compareTo( RankLadder rl ) * @return */ public Rank getRank( String rank ) { - Rank results = null; - - for ( Rank r : ranks ) { + Rank results = null; + + for ( Rank r : ranks ) { if ( r.getName().equalsIgnoreCase( rank ) ) { results = r; break; } } - return results; + return results; + } + + + /** + * This function should never be used since magic numbers as used in + * the rank ID are no longer valid. This function is ONLY used when loading + * old player file data so it can be converted to the newer format. + * + * @param rankId + * @return + */ + public Rank getRank( int rankId ) { + Rank results = null; + + if ( rankId != -1 ) { + + for ( Rank r : ranks ) { + if ( r.getId() != -1 && r.getId() == rankId ) { + results = r; + break; + } + } + } + + return results; } /** @@ -302,17 +195,17 @@ public Rank getRank( String rank ) { */ public void addRank(int position, Rank rank) { - if ( position < 0 ) { - position = 0; - } - else if ( position > getRanks().size() ) { - getRanks().add( rank ); - } - else { - getRanks().add( position, rank ); - } - - rank.setLadder( this ); + if ( position < 0 ) { + position = 0; + } + else if ( position > getRanks().size() ) { + getRanks().add( rank ); + } + else { + getRanks().add( position, rank ); + } + + rank.setLadder( this ); // Update the rank positions along with next and prior: connectRanks(); @@ -329,33 +222,27 @@ else if ( position > getRanks().size() ) { * @param rank The {@link Rank} to add. */ public void addRank(Rank rank) { -// int position = getRanks().size(); -// rank.setPosition( position ); - rank.setLadder( this ); - - getRanks().add( rank ); - - // Update the rank positions along with next and prior: - connectRanks(); - -// ranks.add(new PositionRank(getNextAvailablePosition(), rank.getId(), rank.getName(), rank)); - -// // Reset the rank relationships: -// PrisonRanks.getInstance().getRankManager().connectRanks(); + rank.setLadder( this ); + + getRanks().add( rank ); + + // Update the rank positions along with next and prior: + connectRanks(); + } public void removeRank( Rank rank ) { - boolean success = getRanks().remove( rank ); - - if ( success ) { - rank.setLadder( null ); - - // Update the rank positions along with next and prior: - connectRanks(); - } + boolean success = getRanks().remove( rank ); + + if ( success ) { + rank.setLadder( null ); + + // Update the rank positions along with next and prior: + connectRanks(); + } } /** @@ -372,52 +259,29 @@ public void removeRank( Rank rank ) { */ private void connectRanks() { - Rank rankLast = null; - - // The inserted rank may not be at the end of ranks, so go through all ranks and - // update their position value: - for ( int i = 0; i < getRanks().size(); i++ ) { - Rank rank = getRanks().get( i ); - - rank.resetPosition(); - -// if ( rank.getPosition() != i ) { -// rank.setPosition( i ); -// } - - // reset the rankPrior and rankNext in case there are no hookups: - // Important if ranks are removed, or inserted, or moved: - rank.setRankPrior( null ); - rank.setRankNext( null ); - - if ( rankLast != null ) { - rank.setRankPrior( rankLast ); - rankLast.setRankNext( rank ); - } - rankLast = rank; - -// String message = "Ladder " + getName() + " " + rank.getName() + -// " position=" + rank.getPosition(); -// Output.get().logInfo( message ); - } + Rank rankLast = null; + + // The inserted rank may not be at the end of ranks, so go through all ranks and + // update their position value: + for ( int i = 0; i < getRanks().size(); i++ ) { + Rank rank = getRanks().get( i ); + + rank.resetPosition(); + + // reset the rankPrior and rankNext in case there are no hookups: + // Important if ranks are removed, or inserted, or moved: + rank.setRankPrior( null ); + rank.setRankNext( null ); + + if ( rankLast != null ) { + rank.setRankPrior( rankLast ); + rankLast.setRankNext( rank ); + } + rankLast = rank; + + } } -// /** -// * Orders the ranks in the rank list of this ladder by their position, in ascending order. -// */ -// public void orderRanksByPosition() { -// -// // Do not sort here: -// //The ranks within a ladder will be sorted within the function connectRanks(): -// //ranks.sort(Comparator.comparingInt(PositionRank::getPosition)); -// -// // Reset the rank relationships: -// PrisonRanks.getInstance().getRankManager().connectRanks(); -// } - - /* - * Getters & Setters - */ /** * Returns true if this ladder contains the Rank. @@ -426,7 +290,7 @@ private void connectRanks() { * @return True if the rank was found, false otherwise. */ public boolean containsRank( Rank rank ) { - return ranks.contains( rank ); + return ranks.contains( rank ); } // This next method is sort of precautionary. Sure, positions start at 0, but if the user decides @@ -440,19 +304,13 @@ public boolean containsRank( Rank rank ) { * @return The rank option, or an empty optional if there are no ranks in this ladder. */ public Optional getLowestRank() { - Rank results = null; - - if ( getRanks().size() > 0 ) { - results = getRanks().get( 0 ); - } - -// for ( Rank r : getRanks() ) { -// if ( results == null || r.getPosition() < results.getPosition() ) { -// results = r; -// } -// } - - return results == null ? Optional.empty() : Optional.of( results ); + Rank results = null; + + if ( getRanks().size() > 0 ) { + results = getRanks().get( 0 ); + } + + return results == null ? Optional.empty() : Optional.of( results ); } @@ -477,47 +335,6 @@ public int hashCode() { return result; } - - -// /** -// *

    Identifies of the Ladder contains a permission. -// *

    -// * -// * @param permission -// * @return -// */ -// public boolean hasPermission( String permission ) { -// boolean results = false; -// -// for ( String perm : getPermissions() ) { -// if ( perm.equalsIgnoreCase( permission ) ) { -// results = true; -// break; -// } -// } -// -// return results; -// } - -// /** -// *

    Identifies if the Ladder contains a permission group. -// *

    -// * -// * @param permissionGroup -// * @return -// */ -// public boolean hasPermissionGroup( String permissionGroup ) { -// boolean results = false; -// -// for ( String perm : getPermissionGroups() ) { -// if ( perm.equalsIgnoreCase( permissionGroup ) ) { -// results = true; -// break; -// } -// } -// -// return results; -// } public int getId() { return id; @@ -533,12 +350,6 @@ public void setName( String name ) { this.name = name; } -// public int getMaxPrestige() { -// return maxPrestige; -// } -// public void setMaxPrestige( int maxPrestige ) { -// this.maxPrestige = maxPrestige; -// } public List getRankUpCommands() { if ( rankUpCommands == null ) { 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 230e24cee..3b74d19ad 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 @@ -17,6 +17,7 @@ package tech.mcprison.prison.ranks.data; +import java.io.File; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; @@ -56,17 +57,26 @@ public class RankPlayer public static final long DELAY_THREE_SECONDS = 20 * 3; // 3 seconds in ticks - // The cooldown time for when the rank score will be recalculated -// public static final long RANK_SCORE_COOLDOWN_MS = 1000 * 60 * 5; // 5 minutes -// public static final double RANK_SCORE_BALANCE_THRESHOLD_PERCENT = 0.05d; // 5% - - - /* - * Fields & Constants - */ private UUID uid; + private Player platformPlayer; + private long platformPlayerTimestamp = -1L; + + + private transient File filePlayer; + private transient File fileCache; + + + + private long totalBlocks; + + private long totalTokens; + private double currentBalance; + + private long lastSeenDate; + + // This is used to track if a RankPlayer was saved, or needs to be saved. private transient boolean enableDirty = false; @@ -75,16 +85,14 @@ public class RankPlayer private TreeMap ladderRanks; + // Obsolete: rank ids no longer are being used... + // except when loading old format data prior to being converted. // ranks is the storage structure used to save the player's ladder & ranks: private HashMap ranksRefs; // - // This prestige is not used. Current prestige is just another ladder. - //private HashMap prestige; // private List names; -// // Block name, count -// private HashMap blocksMined; // For tops processing. Need current balance. @@ -97,7 +105,6 @@ public class RankPlayer private Object unsavedBalanceLock = new Object(); private int ubTaskId = 0; -// private HashMap economyCustom = new HashMap<>();; @@ -113,159 +120,191 @@ public class RankPlayer private double rankScoreBalance = 0; private String rankScoreCurrency = null; -// private double rankScoreBalanceThreshold = 0; -// private long rankScoreCooldown = 0L; - private long economyCacheUpdateDelayTicks = -1; + + private long lastSaved = -1; + private long lastRefreshed = -1; + + private List permsSnapShot; + + private double sellallMultiplierValue; + private List sellallMultipliers; + + + private transient String miscText; + public RankPlayer() { - super(); - - this.ladderRanks = new TreeMap<>(); + super(); + + this.ladderRanks = new TreeMap<>(); this.ranksRefs = new HashMap<>(); - //this.prestige = new HashMap<>(); - -// this.blocksMined = new HashMap<>(); this.playerBalances = new TreeMap<>(); + + this.permsSnapShot = new ArrayList<>(); + + + this.sellallMultiplierValue = 1d; + this.sellallMultipliers = new ArrayList<>(); + + + this.filePlayer = null; + this.fileCache = null; } public RankPlayer( UUID uid ) { - this(); - - this.uid = uid; + this(); + + this.uid = uid; } public RankPlayer( UUID uid, String playerName ) { - this( uid ); - - checkName( playerName ); + this( uid ); + + checkName( playerName ); } -// public RankPlayer clone() { -// RankPlayer clone = new RankPlayer( getUUID() ); -// -// clone.setBalance( getBalance() ); -// -// Set keys = getLadderRanks().keySet(); -// for (RankLadder key : keys) { -// -// clone.ladderRanks.put( key, getLadderRanks().get( key ) ); -// } -// -// return clone; -// } - -// @SuppressWarnings( "unchecked" ) -// public RankPlayer(Document document) { -// this(); -// -// this.uid = UUID.fromString((String) document.get("uid")); -// LinkedTreeMap ranksLocal = -// (LinkedTreeMap) document.get("ranks"); -//// LinkedTreeMap prestigeLocal = -//// (LinkedTreeMap) document.get("prestige"); -// -// LinkedTreeMap blocksMinedLocal = -// (LinkedTreeMap) document.get("blocksMined"); -// -// Object namesListObject = document.get( "names" ); -// -// -// for (String key : ranksLocal.keySet()) { -// ranksRefs.put(key, ConversionUtil.doubleToInt(ranksLocal.get(key))); -// } -// -//// for (String key : prestigeLocal.keySet()) { -//// prestige.put(key, RankUtil.doubleToInt(prestigeLocal.get(key))); -//// } -// -// this.blocksMined = new HashMap<>(); -// if ( blocksMinedLocal != null ) { -// for (String key : blocksMinedLocal.keySet()) { -// blocksMined.put(key, ConversionUtil.doubleToInt(blocksMinedLocal.get(key))); -// } -// } -// -// if ( namesListObject != null ) { -// -// for ( Object rankPlayerNameMap : (ArrayList) namesListObject ) { -// LinkedTreeMap rpnMap = (LinkedTreeMap) rankPlayerNameMap; -// -// if ( rpnMap.size() > 0 ) { -// String name = (String) rpnMap.get( "name" ); -// long date = ConversionUtil.doubleToLong( rpnMap.get( "date" ) ); -// -// RankPlayerName rankPlayerName = new RankPlayerName( name, date ); -// getNames().add( rankPlayerName ); -//// Output.get().logInfo( "RankPlayer: uuid: " + uid + " RankPlayerName: " + rankPlayerName.toString() ); -// } -// -// } -// } -// -// } -// -// public Document toDocument() { -// Document ret = new Document(); -// ret.put("uid", this.uid); -// ret.put("ranks", this.ranksRefs); -//// ret.put("prestige", this.prestige); -// -// ret.put("names", this.names); -// -// ret.put("blocksMined", this.blocksMined); -// return ret; -// } -// + @Override public String toString() { - return getName() + " " + getRanks(); + return getName() + " " + getRanks(); } - - /** - *

    This constructs a player file named based upon the UUID followed - * by the player's name. This format is used so it's easier to identify - * the correct player. - *

    - * - *

    The format should be UUID-PlayerName.json. The UUID is a shortened - * format, which should still produce a unique id. The name, when read, - * is based upon the UUID and not the player's name, which may change. - * This format includes the player's name to make it easier to identify - * who's record is whom's. - *

    - * - * @return - */ - public String getPlayerFileName() { - - return JsonFileIO.getPlayerFileName( this ); - } + public String getRanks() { - StringBuilder sb = new StringBuilder(); - - for ( PlayerRank rank : getLadderRanks().values() ) { - + StringBuilder sb = new StringBuilder(); + + for ( PlayerRank rank : getLadderRanks().values() ) { + sb.append( rank.getRank().getLadder() == null ? "--" : rank.getRank().getLadder().getName() ) .append( ":" ).append( rank.getRank().getName() ).append( " " ); } - - return sb.toString(); + + return sb.toString(); } public UUID getUUID() { - return uid; + return uid; } - public boolean isEnableDirty() { + /** + *

    Note that this is a passive field that is actually maintained in the + * player cache. Use that instead of this field. This field is intended to + * be used within TopN stats when the player is offline so the player cache + * does not need to be loaded. + *

    + * + * @return + */ + public long getTotalBlocksTemp() { + return totalBlocks; + } + public void setTotalBlocksTemp(long totalBlocks) { + this.totalBlocks = totalBlocks; + } + + /** + *

    Note that this is a passive field that is actually maintained in the + * player cache. Use that instead of this field. This field is intended to + * be used within TopN stats when the player is offline so the player cache + * does not need to be loaded. + *

    + * + * @return + */ + public long getTotalTokensTemp() { + return totalTokens; + } + public void setTotalTokensTemp(long currentTokens) { + this.totalTokens = currentTokens; + } + + /** + *

    Note that this is a passive field that is actually maintained in the + * player cache. Use that instead of this field. This field is intended to + * be used within TopN stats when the player is offline so the player cache + * does not need to be loaded. + *

    + * + * @return + */ + public double getCurrentBalanceTemp() { + return currentBalance; + } + public void setCurrentBalanceTemp(double currentBalance) { + this.currentBalance = currentBalance; + } + + /** + *

    Note that this is a passive field that is actually maintained in the + * player cache. Use that instead of this field. This field is intended to + * be used within TopN stats when the player is offline so the player cache + * does not need to be loaded. + *

    + * + * @return + */ + public long getLastSeenDateTemp() { + return lastSeenDate; + } + public void setLastSeenDateTemp(long lastSeenDate) { + this.lastSeenDate = lastSeenDate; + } + /** + * Returns the bukkit's last seen date as a long. + * + * Returns the save value as getLastSeenDateTemp(). + * @return + */ + public long getLastSeenDate() { + return lastSeenDate; + } + + + + public void updateTotalLastValues( PlayerCachePlayerData cacheData ) { + updateTotalLastValues( cacheData, true ); + } + + public void updateTotalLastValues( PlayerCachePlayerData cacheData, boolean update ) { + + if ( cacheData != null ) { + + if ( cacheData.getBlocksTotal() != getTotalBlocksTemp() ) { + + setTotalBlocksTemp( cacheData.getBlocksTotal() ); + setDirty( true ); + } + + if ( cacheData.getLastSeenDate() != getLastSeenDateTemp() ) { + + setLastSeenDateTemp( cacheData.getLastSeenDate() ); + setDirty( true ); + } + + if ( cacheData.getTokensTotal() != getTotalTokensTemp() ) { + + setTotalTokensTemp( cacheData.getTokensTotal() ); + setDirty( true ); + } + + if ( update ) { + + // Save if dirty: + Prison.get().getPlatform().saveRankPlayer( this ); + } + } + } + + + public boolean isEnableDirty() { return enableDirty; } public void setEnableDirty(boolean enableDirty) { @@ -285,15 +324,15 @@ public void setDirty(boolean dirty) { * a null. */ public String getDisplayName() { - return getLastName(); + return getLastName(); } public void setDisplayName(String newDisplayName) { - checkName( newDisplayName ); + checkName( newDisplayName ); } public boolean isOnline() { - return false; + return false; } /** @@ -307,55 +346,91 @@ public boolean isOnline() { * @return */ public boolean checkName( String playerName ) { - boolean added = false; - - // If the playerName is not valid, don't try to add it: - if ( playerName != null && playerName.trim().length() > 0 && - !"CONSOLE".equalsIgnoreCase( playerName ) ) { - - String name = getLastName(); - - // Check if the last name in the list is not the same as the name passed: - if ( name == null || - name != null && !name.equalsIgnoreCase( playerName ) ) { - - RankPlayerName rpn = new RankPlayerName( playerName, System.currentTimeMillis() ); - getNames().add( rpn ); - - dirty = true; - - added = true; - } - } - - return added; + boolean added = false; + + // If the playerName is not valid, don't try to add it: + if ( playerName != null && playerName.trim().length() > 0 && + !"CONSOLE".equalsIgnoreCase( playerName ) ) { + + String name = getLastName(); + + // Check if the last name in the list is not the same as the name passed: + if ( name == null || + name != null && !name.equalsIgnoreCase( playerName ) ) { + + RankPlayerName rpn = new RankPlayerName( playerName, System.currentTimeMillis() ); + getNames().add( rpn ); + + dirty = true; + + added = true; + } + } + + return added; } private String getLastName() { - String name = getNames().size() == 0 ? - null : - getNames().get( getNames().size() - 1 ).getName(); - - return name; + String name = getNames().size() == 0 ? + null : + getNames().get( getNames().size() - 1 ).getName(); + + return name; } public List getNames() { - if ( names == null ) { - names = new ArrayList<>(); - } + if ( names == null ) { + names = new ArrayList<>(); + } return names; } public void setNames( List names ) { this.names = names; } -// public HashMap getBlocksMined() { -// return blocksMined; -// } -// public void setBlocksMined( HashMap blocksMined ) { -// this.blocksMined = blocksMined; -// } + + + /** + *

    This constructs a player file named based upon the UUID followed + * by the player's name. This format is used so it's easier to identify + * the correct player. + *

    + * + *

    The format should be UUID-PlayerName.json. The UUID is a shortened + * format, which should still produce a unique id. The name, when read, + * is based upon the UUID and not the player's name, which may change. + * This format includes the player's name to make it easier to identify + * who's record is whom's. + *

    + * + * @return + */ + public String getPlayerFileName() { + + return filenamePlayer(); + } + + + public File getFilePlayer() { + if ( filePlayer == null ) { + filePlayer = JsonFileIO.filePlayer( this );; + } + return filePlayer; + } + public void setFilePlayer(File filePlayer) { + this.filePlayer = filePlayer; + } + + public File getFileCache() { + if ( fileCache == null ) { + fileCache = JsonFileIO.fileCache( this ); + } + return fileCache; + } + public void setFileCache(File fileCache) { + this.fileCache = fileCache; + } /** *

    This is a helper function to ensure that the given file name is @@ -364,50 +439,16 @@ public void setNames( List names ) { * * @return "player_" plus the least significant bits of the UID */ - public String filename() + public String filenamePlayer() { - return "player_" + uid.getLeastSignificantBits(); + return getFilePlayer().getName(); } + public String filenameCache() + { + return getFileCache().getName(); + } -// /** -// *

    This function will check to see if the player is on the default rank on -// * the default ladder. If not, then it will add them. -// *

    -// * -// *

    This is safe to run on anyone, even if they already are on the default ladder. -// *

    -// * -// *

    Note, this will not save the player's new rank. The save function must be -// * managed and called outside of this. -// *

    -// */ -// public void firstJoin() { -// -// RankLadder defaultLadder = PrisonRanks.getInstance().getDefaultLadder(); -// -// if ( !getLadderRanks().containsKey( defaultLadder ) ) { -// -// Optional firstRank = defaultLadder.getLowestRank(); -// -// if ( firstRank.isPresent() ) { -// Rank rank = firstRank.get(); -// -// addRank( rank ); -// -// Prison.get().getEventBus().post(new FirstJoinEvent( this )); -// -// FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); -// Output.get().logWarn( messages.firstJoinSuccess( getName() ) ); -// -// } else { -// -// FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); -// Output.get().logWarn( messages.firstJoinWarningNoRanksOnServer() ); -// } -// } -// -// } /** * Add a rank to this player. @@ -418,7 +459,7 @@ public String filename() */ public void addRank( Rank rank) { if ( rank.getLadder() == null ) { - throw new IllegalArgumentException("Rank must be on ladder."); + throw new IllegalArgumentException("Rank must be on ladder."); } String ladderName = rank.getLadder().getName(); @@ -430,11 +471,11 @@ public void addRank( Rank rank) { if ( ladderRanks.containsKey( rank.getLadder() ) ) { - // Remove the player from the old rank: - PlayerRank oldRank = ladderRanks.get( rank.getLadder() ); - oldRank.getRank().getPlayers().remove( this ); - - ladderRanks.remove( rank.getLadder() ); + // Remove the player from the old rank: + PlayerRank oldRank = ladderRanks.get( rank.getLadder() ); + oldRank.getRank().getPlayers().remove( this ); + + ladderRanks.remove( rank.getLadder() ); } ranksRefs.put(ladderName, rank.getId()); @@ -460,9 +501,9 @@ public void addRank( Rank rank) { * @return */ public PlayerRank createPlayerRank( Rank rank ) { - PlayerRank pRank = new PlayerRank( rank, 1.0 ); - - return pRank; + PlayerRank pRank = new PlayerRank( rank, 1.0 ); + + return pRank; } /** @@ -474,7 +515,7 @@ public PlayerRank createPlayerRank( Rank rank ) { */ public void recalculateRankMultipliers() { - recalculateRankMultipliers( getLadderRanks() ); + recalculateRankMultipliers( getLadderRanks() ); } @@ -492,25 +533,24 @@ public void recalculateRankMultipliers() { */ public void recalculateRankMultipliers( TreeMap targetLadderRanks ) { - double multiplier = 0; - - // First gather and calculate the multipliers: - Set keys = targetLadderRanks.keySet(); - for ( RankLadder rankLadder : keys ) - { - PlayerRank pRank = targetLadderRanks.get( rankLadder ); - - double rankMultiplier = pRank.getLadderBasedRankMultiplier(); - multiplier += rankMultiplier; + double multiplier = 0; + + // First gather and calculate the multipliers: + Set keys = targetLadderRanks.keySet(); + for ( RankLadder rankLadder : keys ) + { + PlayerRank pRank = targetLadderRanks.get( rankLadder ); + + double rankMultiplier = pRank.getLadderBasedRankMultiplier(); + multiplier += rankMultiplier; } - - // We now have the multipliers, so apply them to all ranks: - for ( RankLadder rankLadder : keys ) - { - PlayerRank pRank = targetLadderRanks.get( rankLadder ); - - pRank.applyMultiplier( multiplier ); -// pRank.setRankCost( pRank.getRank().getCost() * (1.0 + multiplier) ); + + // We now have the multipliers, so apply them to all ranks: + for ( RankLadder rankLadder : keys ) + { + PlayerRank pRank = targetLadderRanks.get( rankLadder ); + + pRank.applyMultiplier( multiplier ); } } @@ -528,43 +568,43 @@ public void recalculateRankMultipliers( * @return */ public PlayerRank calculateTargetPlayerRank( Rank targetRank ) { - PlayerRank targetPlayerRank = null; - - // Can only process if the target rank is not null and it has a ladder: - if ( targetRank != null && targetRank.getLadder() != null ) { - - // Need to get the targetRank's ladder. Not all ranks have ladders. - RankLadder targetLadder = targetRank.getLadder(); - - // Create a new PlayerRank object for this target rank. - // Ignore rank cost multipliers since that will be applied later. - targetPlayerRank = new PlayerRank( targetRank ); - - // Create a new temp targetLadderRanks TreeMap: - TreeMap targetLadderRanks = new TreeMap<>(); - - // Copy the player's actual ladderRanks to the targetLadderRanks: - Set keys = getLadderRanks().keySet(); - for (RankLadder key : keys) { - PlayerRank pRank = getLadderRanks().get( key ); - - targetLadderRanks.put( key, pRank ); - } - - // Now add our targetPlayerRank to the targetLadderRanks: - targetLadderRanks.put( targetLadder, targetPlayerRank ); - - - // Now recalculate all multipliers and the rank costs for the targetPlayerRank: - recalculateRankMultipliers( targetLadderRanks ); - - } - - // The targetPlayerRank now has the correct total multiplier from all - // ladders, and it's Rank Cost is based upon those multipliers and if - // the ladder should apply the multipliers or not: - - return targetPlayerRank; + PlayerRank targetPlayerRank = null; + + // Can only process if the target rank is not null and it has a ladder: + if ( targetRank != null && targetRank.getLadder() != null ) { + + // Need to get the targetRank's ladder. Not all ranks have ladders. + RankLadder targetLadder = targetRank.getLadder(); + + // Create a new PlayerRank object for this target rank. + // Ignore rank cost multipliers since that will be applied later. + targetPlayerRank = new PlayerRank( targetRank ); + + // Create a new temp targetLadderRanks TreeMap: + TreeMap targetLadderRanks = new TreeMap<>(); + + // Copy the player's actual ladderRanks to the targetLadderRanks: + Set keys = getLadderRanks().keySet(); + for (RankLadder key : keys) { + PlayerRank pRank = getLadderRanks().get( key ); + + targetLadderRanks.put( key, pRank ); + } + + // Now add our targetPlayerRank to the targetLadderRanks: + targetLadderRanks.put( targetLadder, targetPlayerRank ); + + + // Now recalculate all multipliers and the rank costs for the targetPlayerRank: + recalculateRankMultipliers( targetLadderRanks ); + + } + + // The targetPlayerRank now has the correct total multiplier from all + // ladders, and it's Rank Cost is based upon those multipliers and if + // the ladder should apply the multipliers or not: + + return targetPlayerRank; } /** @@ -574,156 +614,41 @@ public PlayerRank calculateTargetPlayerRank( Rank targetRank ) { * @param rank The The {@link Rank} to remove. */ public void removeRank(Rank rank) { - - if ( rank != null && rank.getLadder() != null ) { - - ladderRanks.remove( rank.getLadder() ); - - ranksRefs.remove( rank.getLadder().getName() ); - } + + if ( rank != null && rank.getLadder() != null ) { + + ladderRanks.remove( rank.getLadder() ); + + ranksRefs.remove( rank.getLadder().getName() ); + } -// // When we loop through, we have to store our ladder name outside the loop to -// // avoid a concurrent modification exception. So, we'll retrieve the data we need... -// String ladderName = null; -// for (Map.Entry rankEntry : ranksRefs.entrySet()) { -// if (rankEntry.getValue() == rank.getId()) { // This is our rank! -// ladderName = rankEntry.getKey(); -// } -// } -// -// // ... and then remove it! -// ranksRefs.remove(ladderName); -// -// ladderRanks.remove( rank.getLadder() ); } public boolean hasLadder( String ladderName ) { - return ranksRefs.containsKey( ladderName ); + boolean results = false; + + Set ladders = getLadderRanks().keySet(); + + for (RankLadder ladder : ladders) { + if ( ladderName != null && ladder.getName().equalsIgnoreCase(ladderName) ) { + results = true; + break; + } + } + + return results; } -// /** -// * Removes a ladder from this player, including whichever rank this player had in it. -// * Cannot remove the default ladder. -// * -// * @param ladderName The ladder's name. -// */ -// public boolean removeLadder(String ladderName) { -// boolean results = false; -// if ( !ladderName.equalsIgnoreCase("default") ) { -// Integer id = ranksRefs.remove(ladderName); -// results = (id != null); -// -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); -// if ( ladder != null && !ladder.getName().equalsIgnoreCase( "default" ) ) { -// ladderRanks.remove( ladder ); -// } -// } -// -// return results; -// } - -// /** -// * Retrieves the rank that this player has in a certain ladder, if any. -// * -// * @param ladder The ladder to check. -// * @return An optional containing the {@link Rank} if found, or empty if there isn't a rank by that ladder for this player. -// */ -// public PlayerRank getRank(RankLadder ladder) { -// PlayerRank results = null; -// -// if ( ladder != null ) { -// -// Set keys = ladderRanks.keySet(); -// for ( RankLadder key : keys ) -// { -// if ( key != null && key.getName().equalsIgnoreCase( ladder.getName() ) ) { -// results = ladderRanks.get( key ); -// } -// } -// } -// -// return results; -// -//// if (!ranksRefs.containsKey(ladder.getName())) { -//// return null; -//// } -//// int id = ranksRefs.get(ladder.getName()); -//// return PrisonRanks.getInstance().getRankManager().getRank(id); -// } -// -// /** -// * Retrieves the rank that this player has the specified ladder. -// * -// * @param ladder The ladder name to check. -// * @return The {@link Rank} if found, otherwise null; -// */ -// public PlayerRank getRank( String ladderName ) { -// -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); -// return getRank( ladder ); -// -//// Rank results = null; -//// if (ladder != null && ranksRefs.containsKey(ladder)) { -//// int id = ranksRefs.get(ladder); -//// results = PrisonRanks.getInstance().getRankManager().getRank(id); -//// } -//// return results; -// } - - -// public HashMap getPrestige() { -// return prestige; -// } -// public void setPrestige( HashMap prestige ) { -// this.prestige = prestige; -// } public void setRanks( HashMap ranks ) { this.ranksRefs = ranks; } -// /** -// * Returns all ladders this player is a part of, along with each rank the player has in that ladder. -// * -// * @return The map containing this data. -// */ -// public Map getLadderRanks( RankPlayer rankPlay) { -// -// if ( ladderRanks.isEmpty() && !ranksRefs.isEmpty() ) { -// -// //Map ret = new HashMap<>(); -// -// for (Map.Entry entry : rankPlay.getRanksRefs().entrySet()) { -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(entry.getKey()); -// -// if ( ladder == null ) { -// continue; // Skip it -// } -// -// Rank rank = PrisonRanks.getInstance().getRankManager().getRank(entry.getValue()); -// if ( rank == null ) { -// continue; // Skip it -// } -// -// PlayerRank pRank = new PlayerRank( rank ); -// -// ladderRanks.put(ladder, pRank); -// } -// -// // Need to recalculate all rank multipliers: -// recalculateRankMultipliers(); -// } -// -// return ladderRanks; -// } public TreeMap getLadderRanks() { return ladderRanks; } -// public void setLadderRanks( TreeMap ladderRanks ) { -// this.ladderRanks = ladderRanks; -// } private RankLadder getRankLadder( String ladderName ) { RankLadder results = null; @@ -827,45 +752,41 @@ public void setRanksRefs( HashMap ranksRefs ) { * @return */ public boolean hasAccessToRank( Rank targetRank ) { - boolean hasAccess = false; - - if ( targetRank != null && targetRank.getLadder() != null ) { - - PlayerRank pRank = getLadderRanks().get( targetRank.getLadder() ); - -// PlayerRank pRank = getRank( targetRank.getLadder() ); - if ( pRank != null ) { - - Rank rank = pRank.getRank(); - if ( rank != null && - rank.getLadder().equals( targetRank.getLadder() ) ) { - - hasAccess = rank.equals( targetRank ); - - // If access-to-prior-mines is enabled (defaults to true if does not exist), - // then search prior ranks on this ladder until a match with target is found. - if ( Prison.get().getPlatform() - .getConfigBooleanTrue( "prison-mines.access-to-prior-mines" ) ) { - - Rank priorRank = rank.getRankPrior(); - - while ( !hasAccess && priorRank != null ) { - - hasAccess = priorRank.equals( targetRank ); - priorRank = priorRank.getRankPrior(); - } - } - - } - } - } - return hasAccess; + boolean hasAccess = false; + + if ( targetRank != null && targetRank.getLadder() != null ) { + + PlayerRank pRank = getLadderRanks().get( targetRank.getLadder() ); + + if ( pRank != null ) { + + Rank rank = pRank.getRank(); + if ( rank != null && + rank.getLadder().equals( targetRank.getLadder() ) ) { + + hasAccess = rank.equals( targetRank ); + + // If access-to-prior-mines is enabled (defaults to true if does not exist), + // then search prior ranks on this ladder until a match with target is found. + if ( !hasAccess && Prison.get().getPlatform() + .getConfigBooleanTrue( "prison-mines.access-to-prior-mines" ) ) { + + Rank priorRank = rank.getRankPrior(); + + while ( !hasAccess && priorRank != null ) { + + hasAccess = priorRank.equals( targetRank ); + priorRank = priorRank.getRankPrior(); + } + } + + } + } + } + return hasAccess; } - /* - * equals() and hashCode() - */ @Override public boolean equals(Object o) { @@ -959,8 +880,9 @@ public List getLineOfSightBlocks() { @Override - public void teleport( Location location ) { + public boolean teleport( Location location ) { // Output.get().logError( "RankPlayer.teleport: Offline players cannot be teleported." ); + return false; } @Override @@ -999,8 +921,8 @@ public boolean isOp() { */ @Override public boolean isPlayer() { - Player player = getPlatformPlayer(); - return (player != null ? player.isPlayer() : false ); + Player player = getPlatformPlayer(); + return (player != null ? player.isPlayer() : false ); } @@ -1026,23 +948,36 @@ public Inventory getInventory() { return results; } -// @Override -// public void printDebugInventoryInformationToConsole() { -// -// } + /** + *

    This function will use the platform to get the platform player, which is tied to the + * platform's player object. So on Spigot, the platformPlayer will be a SpigotPlayer object, + * with this instance of RankPlayer attached to it. + *

    + * + *

    Every five minutes, this function will refresh the platformPlayer since the instances + * may actually change, such as if the player logged off and back on quickly. It's never + * good to have a stale player object because then the wrong inventory gets updated. But + * at least if that ever happens, then this will 'fix it', at worse, in 5 minutes. + * Getting the platform player is expensive, so we do need to cache it. + *

    + * + */ @Override public Player getPlatformPlayer() { - Player player = null; - Optional oPlayer = Prison.get().getPlatform().getPlayer( uid ); + long now = System.currentTimeMillis(); + long fiveMin = 1000 * 60* 5; - if ( oPlayer.isPresent() ) { - player = oPlayer.get(); + if ( platformPlayer == null || platformPlayerTimestamp + fiveMin < now ) { + + platformPlayer = Prison.get().getPlatform().getPlatformPlayer( this ); + + platformPlayerTimestamp = now; } - return player; + return platformPlayer; } @@ -1061,25 +996,38 @@ public void recalculatePermissions() { @Override public List getPermissions() { - Player player = getPlatformPlayer(); - return (player == null ? new ArrayList<>() : player.getPermissions() ); + Player player = getPlatformPlayer(); + return (player == null ? new ArrayList<>() : player.getPermissions() ); } @Override public List getPermissions( String prefix ) { - Player player = getPlatformPlayer(); - return (player == null ? new ArrayList<>() : player.getPermissions( prefix ) ); + + return getPermissions( prefix, getPermissions() ); } + @Override + public List getPermissions( String prefix, List perms ) { + Player player = getPlatformPlayer(); + return (player == null ? new ArrayList<>() : + player.getPermissions( prefix, perms ) ); - + } /** *

    This will called by the placeholders, so need to get the actual * multipliers that exists in the SpigotPlayer object. *

    * - *

    If the player is offline, then just set to a value of 1.0 so as + *

    If the player is offline, then it will try to use the + * getSellallMultiplierValue() which may not be their current + * sellallMulitiplier, but it's the value when they were last + * online and when it was updated and saved within their + * RankPlayer object. + *

    + * + *

    Otherwise, if the player is offline, then + * just set to a value of 1.0 so as * not to change any other value that may be used with this function. * If the player is offline, then there will be no inventory that can be * accessed and hence, none to sell, so a value of 1.0 should be fine. @@ -1088,20 +1036,36 @@ public List getPermissions( String prefix ) { */ @Override public double getSellAllMultiplier() { - double results = 1.0; - - Player player = getPlatformPlayer(); - if ( player != null ) { - results = player.getSellAllMultiplier(); - } -// -// Optional player = Prison.get().getPlatform().getPlayer( uid ); -// -// if ( player.isPresent() ) { -// results = player.get().getSellAllMultiplier(); -// } - - return results; + double results = 1.0; + + Player player = getPlatformPlayer(); + if ( player != null ) { + results = player.getSellAllMultiplier(); + + if ( results != getSellallMultiplierValue() ) { + + setSellallMultiplierValue( results ); + setDirty( true ); + } + } + else { + results = getSellallMultiplierValue(); + } + + return results; + } + + @Override + public double getSellAllMultiplierDebug() { + double results = 1.0; + + Player player = getPlatformPlayer(); + if ( player != null ) { + results = player.getSellAllMultiplierDebug(); + + } + + return results; } @@ -1116,22 +1080,22 @@ public void setPlayerBalances( TreeMap playerBalances private void addCachedRankPlayerBalance( String currency, double amount ) { - // Since the cache will be updated, do not allow it fetch the player's balance: - RankPlayerBalance balance = getCachedRankPlayerBalance( currency, false ); - - balance.addBalance( amount ); + // Since the cache will be updated, do not allow it fetch the player's balance: + RankPlayerBalance balance = getCachedRankPlayerBalance( currency, false ); + + balance.addBalance( amount ); } private void setCachedRankPlayerBalance( String currency, double amount ) { - // Since the cache will be updated, do not allow it fetch the player's balance: - RankPlayerBalance balance = getCachedRankPlayerBalance( currency, false ); - - balance.setBalance( amount ); + // Since the cache will be updated, do not allow it fetch the player's balance: + RankPlayerBalance balance = getCachedRankPlayerBalance( currency, false ); + + balance.setBalance( amount ); } public RankPlayerBalance getCachedRankPlayerBalance( String currency ) { - return getCachedRankPlayerBalance( currency, true ); + return getCachedRankPlayerBalance( currency, true ); } /** @@ -1194,6 +1158,9 @@ public double getBalance() { } setCachedRankPlayerBalance( null, results ); + + // Store player's balance for stats such as TopN: + setCurrentBalanceTemp(results); } return results; @@ -1251,6 +1218,8 @@ private boolean addBalanceEconomy( double amount ) { if ( economy != null ) { results = economy.addBalance( this, amount ); addCachedRankPlayerBalance( null, amount ); + + setCurrentBalanceTemp( economy.getBalance( this ) ); } return results; } @@ -1261,12 +1230,6 @@ public void removeBalance( double amount ) { addBalance( targetAmount ); addCachedRankPlayerBalance( null, targetAmount ); -// EconomyIntegration economy = getEconomy(); -// -// if ( economy != null ) { -// economy.removeBalance( this, amount ); -// addCachedRankPlayerBalance( null, -1 * amount ); -// } } public void setBalance( double amount ) { @@ -1280,12 +1243,6 @@ public void setBalance( double amount ) { addBalance( targetAmount ); addCachedRankPlayerBalance( null, targetAmount ); -// EconomyIntegration economy = getEconomy(); -// -// if ( economy != null ) { -// economy.setBalance( this, amount ); -// setCachedRankPlayerBalance( null, amount ); -// } } @@ -1474,7 +1431,12 @@ public PlayerCache getPlayerCache() { @Override public PlayerCachePlayerData getPlayerCachePlayerData() { - return PlayerCache.getInstance().getOnlinePlayer( this ); + PlayerCachePlayerData cacheData = PlayerCache.getInstance().getOnlinePlayer( this ); + + // Do not update here... it gets called too many times: + //updateTotalLastValues( cacheData ); + + return cacheData; } @Override @@ -1534,6 +1496,7 @@ public PlayerRank getNextPlayerRank() { "Please try restarting the server to see if that fixes the problem before contacting " + "prison's support team. Thanks!" )); + return null; } Rank nRank = rankCurrent.getRank().getRankNext(); @@ -1549,7 +1512,6 @@ public PlayerRank getNextPlayerRank() { // If the player does not have a presetige rank, the getRankLadder will return null. -// RankLadder rLadder = getRankLadder( RankLadder.PRESTIGES ); nRank = rLadder == null ? null : rLadder.getLowestRank().orElse(null); } @@ -1561,7 +1523,6 @@ public PlayerRank getNextPlayerRank() { } PlayerRank pRankNext = calculateTargetPlayerRank( nRank ); -// PlayerRank pRankNext = rankCurrent.getTargetPlayerRankForPlayer( this, nRank ); return pRankNext; } @@ -1582,68 +1543,7 @@ public void calculateRankScore() { double balance = getBalance( rankNextCurrency ); -// RankPlayerBalance cachedBalance = getCachedRankPlayerBalance( rankNextCurrency, true ); -// -// double balance = cachedBalance.getBalance(); - calculateRankScore( rankNextCurrency, cost, balance ); - - -// PlayerRank rankCurrent = getPlayerRankDefault(); - -// Rank nRank = rankCurrent.getRank().getRankNext(); -// -// // If player does not have a next rank, then try to use the next prestige rank: -// if ( nRank == null ) { -// PlayerRank prestigeRankCurrent = getPlayerRankPrestiges(); -// -// // if they don't have a current prestige rank, then use the lowest rank: -// if ( prestigeRankCurrent == null ) { -// RankLadder rLadder = getRankLadder( RankLadder.PRESTIGES ); -// nRank = rLadder == null ? null : rLadder.getLowestRank().orElse(null); -// } -// -// if ( prestigeRankCurrent != null ) { -// nRank = prestigeRankCurrent.getRank() == null ? -// null : prestigeRankCurrent.getRank().getRankNext(); -// } -// -// } -// -// -// PlayerRank pRankNext = rankCurrent.getTargetPlayerRankForPlayer( this, nRank ); - -// String rankNextCurrency = nRank == null ? "" : nRank.getCurrency(); -// double balance = getBalance( rankNextCurrency ); - - -// double balance = getBalance( rankNextCurrency ); -// double score = balance; -// double penalty = 0d; -// -// // Do not apply the penalty if cost is zero: -// if ( cost > 0 && isHesitancyDelayPenaltyEnabled() ) { -// score = balance > cost ? cost : score; -// -// double excess = balance > cost ? balance - cost : 0d; -// penalty = excess * 0.2d; -// } -// -// score = (score - penalty); -// -// if ( cost > 0 ) { -// score /= cost * 100.0d; -// } -// -//// double balanceThreshold = cost * RANK_SCORE_BALANCE_THRESHOLD_PERCENT; -// -//// setRankScoreBalance( balance ); -//// setRankScoreCurrency( rankNextCurrency ); -//// setRankScoreBalanceThreshold( balanceThreshold ); -// setRankScore( score ); -// setRankScorePenalty( penalty ); -// -//// setRankScoreCooldown( System.currentTimeMillis() + RANK_SCORE_COOLDOWN_MS ); } private void calculateRankScore( String currency, double cost, double playerBalance ) { @@ -1672,56 +1572,12 @@ private void calculateRankScore( String currency, double cost, double playerBala setRankScoreCurrency( currency ); } -// private void checkRecalculateRankScore() { -// -// calculateRankScore(); -// -//// if ( getRankScoreCooldown() == 0L || -//// System.currentTimeMillis() > getRankScoreCooldown() -//// ) { -//// -//// double currentBalance = getBalance( getRankScoreCurrency() ); -//// -//// if ( getRankScoreBalance() != 0 && ( -//// currentBalance == getRankScoreBalance() || -//// currentBalance >= (getRankScoreBalance() - getRankScoreBalanceThreshold()) || -//// currentBalance <= (getRankScoreBalance() + getRankScoreBalanceThreshold() ) )) { -//// -//// // increment the cooldown since the balance is either the same, or still -//// // within the threshold range: -//// setRankScoreCooldown( System.currentTimeMillis() + RANK_SCORE_COOLDOWN_MS ); -//// } -//// else { -//// calculateRankScore( currentBalance ); -//// } -//// } -// } - -// /** -// *

    By setting rankScoreCooldown to zero, it will force that player to have it's -// * rank score to be recalculated. The most expensive part is getting the player's -// * balance from Vault. -// *

    -// * -// */ -// public void forcePlayerToRecalculateRankScore() { -// rankScoreCooldown = 0L; -// } + public static String printRankScoreLine1Header() { String header = coreTopNLine1HeaderMsg(); -// String header = String.format( -// "Rank %-16s %-9s %-6s %-9s %-9s %-9s", -// "Player", -// "Prestiges", -// "Rank", -// "Balance", -// "Rank-Score", -// "Penalty" -// -// ); return header; } @@ -1768,16 +1624,6 @@ public String printRankScoreLine1( int rankPostion ) { balanceMetricStr ); -// String message = String.format( -// " %-3s %-18s %-7s %-7s %9s %9s %9s", -// rankScoreStr, -// getName(), -// prestRankTagNc, -// defRankTagNc, -// balanceKmbtStr, -// dFmt.format( getRankScore() ), -// sPenaltyStr -// ); message = message .replace(prestRankTagNc, prestRankTag + "&r") @@ -1789,14 +1635,6 @@ public String printRankScoreLine1( int rankPostion ) { public static String printRankScoreLine2Header() { String header = coreTopNLine2HeaderMsg(); -// String header = String.format( -// "Rank %s %s %-15s %9s", -// "Ranks", -// "Rank-Score", -// "Player", -// "Balance" -// -// ); return header; } @@ -1826,21 +1664,6 @@ public String printRankScoreLine2( int rankPostion ) { String playerName = getName(); -// DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); -// -// PlayerRank prestRank = getPlayerRankPrestiges(); -// PlayerRank defRank = getPlayerRankDefault(); -// -// String prestRankTag = prestRank == null ? "---" : prestRank.getRank().getTag(); -// String defRankTag = defRank == null ? "---" : defRank.getRank().getTag(); -// -// String prestRankTagNc = Text.stripColor(prestRankTag); -// String defRankTagNc = Text.stripColor(defRankTag); -// -// String balanceKmbtStr = PlaceholdersUtil.formattedKmbtSISize( getRankScoreBalance(), dFmt, " " ); -//// String sPenaltyStr = PlaceholdersUtil.formattedKmbtSISize( getRankScorePenalty(), dFmt, " " ); -// -// String ranks = prestRankTagNc + defRankTagNc; String message = coreTopNLine2DetailMsg( playerName, @@ -1851,19 +1674,6 @@ public String printRankScoreLine2( int rankPostion ) { prestRankTagNc, defRankTagNc, balanceFmtStr, balanceKmbtStr, balanceMetricStr ); -// String message = String.format( -// " %-3s %-9s %6s %-17s %9s", -// (rankPostion > 0 ? Integer.toString(rankPostion) : ""), -// ranks, -// dFmt.format( getRankScore() ), -// getName(), -// balanceKmbtStr -// ); -// -// message = message -// .replace(prestRankTagNc, prestRankTag + "&r") -// .replace(defRankTagNc, defRankTag + "&r"); - return message; } @@ -1886,18 +1696,9 @@ public void setRankScoreCurrency( String rankScoreCurrency ) { this.rankScoreCurrency = rankScoreCurrency; } -// public double getRankScoreBalanceThreshold() { -// return rankScoreBalanceThreshold; -// } -// public void setRankScoreBalanceThreshold( double rankScoreBalanceThreshold ) { -// this.rankScoreBalanceThreshold = rankScoreBalanceThreshold; -// } public double getRankScore() { - // check if the rankScore needs to be reset: -// checkRecalculateRankScore(); - return rankScore; } public void setRankScore( double rankScore ) { @@ -1911,12 +1712,26 @@ public void setRankScorePenalty( double rankScorePenalty ) { this.rankScorePenalty = rankScorePenalty; } + /** + *

    Returns the player's current sellallMultipliers listing if they are + * online. If they are not online, then this returns their last saved + * listing, which will not be their current listing since they could have + * changed since the player was last online. + *

    + * + */ @Override public List getSellAllMultiplierListings() { Player player = Prison.get().getPlatform().getPlayer(getUUID()).orElse(null); - return player == null ? new ArrayList<>() : player.getSellAllMultiplierListings(); + return player == null ? + + // NOTE: player is offline, so use the saved sellall multiplier list: + getSellallMultipliers() : + + // Online player: The actual live multiplier listings: + player.getSellAllMultiplierListings(); } @@ -2034,10 +1849,98 @@ private String applySecondaryPlaceholdersCheck( String placeholder, String value public void doNothing() { } -// public long getRankScoreCooldown() { -// return rankScoreCooldown; -// } -// public void setRankScoreCooldown( long rankScoreCooldown ) { -// this.rankScoreCooldown = rankScoreCooldown; -// } + + + public long getLastSaved() { + return lastSaved; + } + public void setLastSaved(long lastSaved) { + this.lastSaved = lastSaved; + } + + + /** + * Notice: This last refreshed timestamp refers to when the permsSnapShot + * and sellallMultipliers were last updated. It maybe be older than the + * last time the players were seen? + * @return + */ + public long getLastRefreshed() { + return lastRefreshed; + } + public void setLastRefreshed(long lastRefreshed) { + this.lastRefreshed = lastRefreshed; + } + + /** + * DO NOT USE! + * + * This is just temporary and unofficial list of permissions + * to be used when the player is offline. These are only accurate + * when they are extracted when the player is online and the player's + * RankPlayer object is saved. + * + * @return + */ + public List getPermsSnapShot() { + return permsSnapShot; + } + public void setPermsSnapShot(List permsSnapShot) { + this.permsSnapShot = permsSnapShot; + } + + + /** + * DO NOT USE! + * + * This is just a temporary and unofficial storage of the multiplier. + * This is not the current multiplier. And as such, should never be + * used as the current multiplier. + * + * This could be used in the same way that the + * getSellallMultipliers() listing is used... for references only + * when the player is offline. + * + * @return + */ + public double getSellallMultiplierValue() { + return sellallMultiplierValue; + } + public void setSellallMultiplierValue(double sellallMultiplierValue) { + this.sellallMultiplierValue = sellallMultiplierValue; + } + + /** + * DO NOT USE! + * + * This is just temporary and unofficial list of sellall multipliers + * to be used when the player is offline. These are only accurate + * when they are extracted when the player is online and the player's + * RankPlayer object is saved. + * + * @return + */ + public List getSellallMultipliers() { + return sellallMultipliers; + } + public void setSellallMultipliers(List sellallMultipliers) { + this.sellallMultipliers = sellallMultipliers; + } + + + /** + * This miscText is not used for any specific purpose other than to hold a String + * value. It can be used to return a message from a function, but it should always + * be cleared when done using it. + * + * @return + */ + @Override + public String getMiscText() { + return miscText; + } + @Override + public void setMiscText( String text ) { + miscText = text; + } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java index 94cf3440e..f2195849d 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/ranks/data/StatsRankPlayerBalanceData.java @@ -45,12 +45,9 @@ public void recalc( boolean isPenaltyEnabled ) { // This calculates the target rank, and takes in to consideration the player's existing rank: PlayerRank pRankNext = player.calculateTargetPlayerRank( rank.getRankNext() ); -// PlayerRank pRankNext = pRank.getTargetPlayerRankForPlayer( player, rank.getRankNext() ); - //PlayerRank pRankNext = new PlayerRank( rank.getRankNext(), pRank.getRankMultiplier() ); cost = pRankNext.getRankCost(); } -// double cost = rank.getRankNext() == null ? rank.getCost() : rank.getRankNext().getCost(); double penalty = 0d; // Do not apply the penalty if cost is zero: diff --git a/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionListener.java b/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionListener.java index 3b9a2f756..08b59a56a 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionListener.java +++ b/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionListener.java @@ -37,7 +37,7 @@ public void init() { @Subscribe public void onPlayerInteract(PrisonPlayerInteractEvent e) { ItemStack ourItem = e.getItemInHand(); - ItemStack toolItem = SelectionManager.SELECTION_TOOL; + ItemStack toolItem = ItemStack.SELECTION_WAND; if ( ourItem == null || !ourItem.equals(toolItem)) { return; @@ -53,7 +53,8 @@ public void onPlayerInteract(PrisonPlayerInteractEvent e) { .sendMessage("&7First position set to &8" + e.getClicked().toBlockCoordinates()); checkForEvent(e.getPlayer(), sel); - } else if (e.getAction() == PrisonPlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { + } + else if (e.getAction() == PrisonPlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { // Set second position Selection sel = Prison.get().getSelectionManager().getSelection(e.getPlayer()); sel.setMax(e.getClicked()); diff --git a/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionManager.java b/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionManager.java index 7d8aea24e..4d8ba5f7f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/selection/SelectionManager.java @@ -23,7 +23,6 @@ import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.Player; -import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.inventory.Inventory; import tech.mcprison.prison.output.Output; @@ -32,9 +31,6 @@ */ public class SelectionManager { - public static final ItemStack SELECTION_TOOL = - new ItemStack("&6Selection Wand", 1, PrisonBlock.BLAZE_ROD, "&7Corner 1 - Left click", - "&7Corner 2 - Right click"); private Map selectionMap; public SelectionManager() { @@ -51,7 +47,7 @@ public SelectionManager() { public void bestowSelectionTool(Player player) { int countBefore = selectionWandCount( player ); - player.give(SELECTION_TOOL); + player.give( ItemStack.SELECTION_WAND ); int countAfter = selectionWandCount( player ); @@ -66,9 +62,8 @@ private int selectionWandCount( Player player) { for (ItemStack is : inv.getItems()) { if ( is != null && - // is.getName().toLowerCase().contains( "selection wand" ) && - // is.getDisplayName().toLowerCase().contains( "selection wand" ) && - is.getMaterial().compareTo( PrisonBlock.BLAZE_ROD ) == 0 ) { + is.getMaterial().compareTo( ItemStack.SELECTION_WAND.getMaterial() ) == 0 + ) { count += is.getAmount(); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/spatial/CoordinateKey.java b/prison-core/src/main/java/tech/mcprison/prison/spatial/CoordinateKey.java index 2a0f9e6fe..15fa80119 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/spatial/CoordinateKey.java +++ b/prison-core/src/main/java/tech/mcprison/prison/spatial/CoordinateKey.java @@ -1,62 +1,68 @@ package tech.mcprison.prison.spatial; +/** + * @deprecated Not used + */ public class CoordinateKey - implements Comparable { +// implements Comparable +{ - private int x; - private int y; - private int z; + // NOTE This class is not used, so it has been commented out before removal. - public CoordinateKey( int x, int y, int z ) { - super(); - - this.x = x; - this.y = y; - this.z = z; - } - - @Override - public int compareTo( CoordinateKey skey ) - { - int results = 0; - - if ( skey == null ) { - results = -1; - } - else { - results = Integer.compare( x, skey.getX() ); - - if ( results == 0 ) { - results = Integer.compare( z, skey.getZ() ); - - if ( results == 0 ) { - results = Integer.compare( y, skey.getY() ); - } - } - } - - return results; - } - - public int getX() { - return x; - } - public void setX( int x ) { - this.x = x; - } - - public int getY() { - return y; - } - public void setY( int y ) { - this.y = y; - } - - public int getZ() { - return z; - } - public void setZ( int z ) { - this.z = z; - } +// private int x; +// private int y; +// private int z; +// +// public CoordinateKey( int x, int y, int z ) { +// super(); +// +// this.x = x; +// this.y = y; +// this.z = z; +// } +// +// @Override +// public int compareTo( CoordinateKey skey ) +// { +// int results = 0; +// +// if ( skey == null ) { +// results = -1; +// } +// else { +// results = Integer.compare( x, skey.getX() ); +// +// if ( results == 0 ) { +// results = Integer.compare( z, skey.getZ() ); +// +// if ( results == 0 ) { +// results = Integer.compare( y, skey.getY() ); +// } +// } +// } +// +// return results; +// } +// +// public int getX() { +// return x; +// } +// public void setX( int x ) { +// this.x = x; +// } +// +// public int getY() { +// return y; +// } +// public void setY( int y ) { +// this.y = y; +// } +// +// public int getZ() { +// return z; +// } +// public void setZ( int z ) { +// this.z = z; +// } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/spatial/SpatialIndex.java b/prison-core/src/main/java/tech/mcprison/prison/spatial/SpatialIndex.java index 4d3749df6..c87cc4f28 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/spatial/SpatialIndex.java +++ b/prison-core/src/main/java/tech/mcprison/prison/spatial/SpatialIndex.java @@ -1,13 +1,16 @@ package tech.mcprison.prison.spatial; -import java.util.NavigableMap; - +/** + * @deprecated + */ public class SpatialIndex { - public static final int SPATIAL_INDEX_GRANULARIT = 25; + // NOTE: This class is not used. Contents has been commented out before removal. - private NavigableMap idxX; - private NavigableMap idxY; - private NavigableMap idxZ; +// public static final int SPATIAL_INDEX_GRANULARIT = 25; +// +// private NavigableMap idxX; +// private NavigableMap idxY; +// private NavigableMap idxZ; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/spatial/SpatialIndexData.java b/prison-core/src/main/java/tech/mcprison/prison/spatial/SpatialIndexData.java index dcfb9f601..ade59eda4 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/spatial/SpatialIndexData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/spatial/SpatialIndexData.java @@ -1,11 +1,17 @@ package tech.mcprison.prison.spatial; + +/** + * @deprecated + */ public class SpatialIndexData { - private int x; - private int y; - private int z; + // NOTE: class is not used and has been commented out before removal. + +// private int x; +// private int y; +// private int z; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/store/Collection.java b/prison-core/src/main/java/tech/mcprison/prison/store/Collection.java index 49b8aee74..192919312 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/store/Collection.java +++ b/prison-core/src/main/java/tech/mcprison/prison/store/Collection.java @@ -32,10 +32,12 @@ public interface Collection { public Optional get(String key); - public void save(Document document); - public void save(String filename, Document document); + public void save(String filename, Document document, + String oldFilename, String fileType); + boolean exists(String name); + public boolean delete(String name); public File backup(String name); diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTaskData.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTaskData.java index 3c4c20f8d..d2fb697bb 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTaskData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTaskData.java @@ -82,7 +82,12 @@ public enum CommandEnvironment { ; } - public enum CustomPlaceholders { + + /** + *

    These are placeholders used within Block Events. + *

    + */ + public enum BlockEventCustomPlaceholders { player(CommandEnvironment.all_commands, "{player} provides a player's name."), @@ -108,6 +113,20 @@ public enum CustomPlaceholders { "{syncPlayer} runs the command as the payer in a new sync task."), + range(CommandEnvironment.all_commands, + "{range: } inserts a randomly choosen number within the " + + "range specified, all inclusive."), + + ifPerm(CommandEnvironment.all_commands, + "{ifPerm:} Continues executing commands in the chain if " + + "the player has the perm ''.", + "ifPerm:" ), + ifNotPerm(CommandEnvironment.all_commands, + "{ifNotPerm:} Stops executing commands in the chain if " + + "the player has the perm ''.", + "ifNotPerm:" ), + + firstJoin(CommandEnvironment.rank_commands, "{firstJoin} runs the command on first join events for new players"), promote(CommandEnvironment.rank_commands, @@ -203,14 +222,23 @@ public enum CustomPlaceholders { private final CommandEnvironment environment; private final String description; + private final String exampleUsage; - private CustomPlaceholders( CommandEnvironment environment ) { + private BlockEventCustomPlaceholders( CommandEnvironment environment ) { this.environment = environment; this.description = null; + this.exampleUsage = null; } - private CustomPlaceholders( CommandEnvironment environment, String description ) { + private BlockEventCustomPlaceholders( CommandEnvironment environment, String description ) { this.environment = environment; this.description = description; + this.exampleUsage = null; + } + private BlockEventCustomPlaceholders( CommandEnvironment environment, String description, + String exampleUsage ) { + this.environment = environment; + this.description = description; + this.exampleUsage = exampleUsage; } public static String listPlaceholders( CommandEnvironment environment ) { @@ -218,7 +246,7 @@ public static String listPlaceholders( CommandEnvironment environment ) { if ( environment != null ) { - for ( CustomPlaceholders cp : values() ) { + for ( BlockEventCustomPlaceholders cp : values() ) { if ( environment.equals( cp.getEnvironment() ) ) { if ( sb.length() > 0 ) { @@ -240,7 +268,11 @@ public static String listPlaceholders( CommandEnvironment environment ) { * @return */ public String getPlaceholder() { - return "{" + name() + "}"; + return "{" + + ( getExampleUsage() != null ? + getExampleUsage() : + name() ) + + "}"; } public CommandEnvironment getEnvironment() { @@ -250,6 +282,10 @@ public CommandEnvironment getEnvironment() { public String getDescription() { return description; } + + public String getExampleUsage() { + return exampleUsage; + } } @@ -291,11 +327,60 @@ public PrisonCommandTaskData( String errorMessagePrefix, command = command.replace( "{syncPlayer}", "" ); } + if ( command.contains( "{range:") ) { + command = taskInsertRange( command ); + } + this.cmd = command; this.taskMode = taskMode; } + protected String taskInsertRange(String command) { + + int idx = command.indexOf("{range:"); + if ( idx != -1 ) { + + int idxEnd = command.indexOf("}", idx ); + if ( idxEnd != -1 ) { + try { + String oValue = command.substring( idx, idxEnd + 1); + String results = ""; + + String nValues = oValue.replace( "{range:", "").replace( "}", "" ).trim(); + String[] lowHigh = nValues.split( " " ); + + int low = Integer.parseInt( lowHigh[0] ); + int high = Integer.parseInt( lowHigh[1] ); + + if ( high < low ) { + int temp = low; + low = high; + high = temp; + } + + if ( low == high ) { + results = Integer.toString( low ); + } + else { + int range = high - low; + int rnd = ((int) Math.round(Math.random() * range)); + results = Integer.toString( low + rnd ); + } + + command = command.replace( oValue, results ); + } + catch (NumberFormatException e) { + // ignore: invalid numbers + } + + } + + } + + return command; + } + public String getDebugDetails() { StringBuilder sb = new StringBuilder(); @@ -350,26 +435,6 @@ public void runCommandTask() { public void runCommandTask( Player player ) { -// if ( command.contains( "{inline}" ) ) { -// taskMode = TaskMode.inline; -// command = command.replace( "{inline}", "" ); -// } -// -// if ( command.contains( "{inlinePlayer}" ) ) { -// taskMode = TaskMode.inlinePlayer; -// command = command.replace( "{inlinePlayer}", "" ); -// } -// -// if ( command.contains( "{sync}" ) ) { -// taskMode = TaskMode.sync; -// command = command.replace( "{sync}", "" ); -// } -// -// if ( command.contains( "{syncPlayer}" ) ) { -// taskMode = TaskMode.syncPlayer; -// command = command.replace( "{syncPlayer}", "" ); -// } -// String commandTranslated = translateCommand( player, getCmd() ); // Split multiple commands in to a List of individual tasks: @@ -386,37 +451,6 @@ public void runCommandTask( Player player ) { runTask( player ); -// PrisonDispatchCommandTask task = -// new PrisonDispatchCommandTask( tasks, errorMessage, -// player, taskMode.isPlayerTask() ); - - - // Ignore taskMode since it's already running in a new sync task: -// task.run(); - - - // NOTE: taskMode is no longer used, since all tasks are being ran - // within a sync task that has already been submitted. -// switch ( taskMode ) -// { -// case inline: -// case inlinePlayer: -// // Don't submit, but run it here within this thread: -// task.run(); -// break; -// -// case sync: -// case syncPlayer: -// //case "async": // async will cause failures so run as sync: -// -// // submit task: -// setTaskId( PrisonTaskSubmitter.runTaskLater(task, 0) ); -// break; -// -// default: -// break; -// } - } } @@ -432,6 +466,28 @@ public void runTask( Player player ) { // was failing with leading spaces after spliting after a ";" so trim to fix it: task = task == null ? "" : task.trim(); + + + // If the task is '{ifPerm:}' then the player must have the perm to + // continue: + if ( task.toLowerCase().startsWith( "{ifperm:" ) ) { + String perm = task.substring( 8, task.length() - 1 ); + + boolean hasPerm = player.hasPermission( perm ); + + if ( !hasPerm ) { + break; + } + } + if ( task.toLowerCase().startsWith( "{ifnotperm:" ) ) { + String perm = task.substring( 11, task.length() - 1 ); + + boolean hasPerm = player.hasPermission( perm ); + + if ( hasPerm ) { + break; + } + } // Apply the custom placeholders: @@ -514,7 +570,7 @@ private String translateCommand( Player player, String command ) { * characters. * @param value The value that is used to replace the placeholder. */ - public void addCustomPlaceholder( CustomPlaceholders placeholder, String value ) { + public void addCustomPlaceholder( BlockEventCustomPlaceholders placeholder, String value ) { PrisonCommandTaskPlaceholderData cph = new PrisonCommandTaskPlaceholderData( placeholder, value); getCustomPlaceholders().add( cph ); } diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTaskPlaceholderData.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTaskPlaceholderData.java index 407441a20..a9d884db5 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTaskPlaceholderData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonCommandTaskPlaceholderData.java @@ -1,13 +1,13 @@ package tech.mcprison.prison.tasks; -import tech.mcprison.prison.tasks.PrisonCommandTaskData.CustomPlaceholders; +import tech.mcprison.prison.tasks.PrisonCommandTaskData.BlockEventCustomPlaceholders; public class PrisonCommandTaskPlaceholderData { - private CustomPlaceholders placeholder; + private BlockEventCustomPlaceholders placeholder; private String value; - public PrisonCommandTaskPlaceholderData( CustomPlaceholders placeholder, String value ) { + public PrisonCommandTaskPlaceholderData( BlockEventCustomPlaceholders placeholder, String value ) { super(); this.placeholder = placeholder; @@ -27,10 +27,10 @@ public String replace( String text ) { return results; } - public CustomPlaceholders getPlaceholder() { + public BlockEventCustomPlaceholders getPlaceholder() { return placeholder; } - public void setPlaceholder( CustomPlaceholders placeholder ) { + public void setPlaceholder( BlockEventCustomPlaceholders placeholder ) { this.placeholder = placeholder; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonDispatchCommandTask.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonDispatchCommandTask.java index f041c6c12..6d67c3b34 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonDispatchCommandTask.java +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonDispatchCommandTask.java @@ -44,6 +44,27 @@ public void run() { long start = System.nanoTime(); + // If the task is '{ifPerm:}' then the player must have the perm to + // continue: + if ( task.toLowerCase().startsWith( "{ifperm:" ) ) { + String perm = task.substring( 8, task.length() - 1 ); + + boolean hasPerm = player.hasPermission( perm ); + + if ( !hasPerm ) { + break; + } + } + if ( task.toLowerCase().startsWith( "{ifnotperm:" ) ) { + String perm = task.substring( 11, task.length() - 1 ); + + boolean hasPerm = player.hasPermission( perm ); + + if ( hasPerm ) { + break; + } + } + // Apply the custom placeholders: for ( PrisonCommandTaskPlaceholderData cPlaceholder : getCustomPlaceholders() ) { if ( cPlaceholder.contains( task ) ) { @@ -52,6 +73,7 @@ public void run() { } try { + if ( playerTask && player != null ) { // double start = System.currentTimeMillis(); diff --git a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonTaskSubmitter.java b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonTaskSubmitter.java index cc22ab101..72370f7f9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonTaskSubmitter.java +++ b/prison-core/src/main/java/tech/mcprison/prison/tasks/PrisonTaskSubmitter.java @@ -27,9 +27,9 @@ public static int runTaskLater( PrisonRunnable task, long delayInTicks ) { * @return The task ID. */ public static int runTaskLaterAsync(Runnable task, long delayInTicks) { - int taskId = Prison.get().getPlatform().getScheduler().runTaskLaterAsync(task, delayInTicks); - - return taskId; + int taskId = Prison.get().getPlatform().getScheduler().runTaskLaterAsync(task, delayInTicks); + + return taskId; } /** @@ -41,10 +41,10 @@ public static int runTaskLaterAsync(Runnable task, long delayInTicks) { * @return The task ID. */ public static int runTaskTimer(Runnable task, long delayInTicks, long intervalInTicks){ - int taskId = Prison.get().getPlatform().getScheduler().runTaskTimer(task, delayInTicks, - intervalInTicks); - - return taskId; + int taskId = Prison.get().getPlatform().getScheduler().runTaskTimer(task, delayInTicks, + intervalInTicks); + + return taskId; } /** @@ -56,10 +56,10 @@ public static int runTaskTimer(Runnable task, long delayInTicks, long intervalIn * @return The task ID. */ public static int runTaskTimerAsync(Runnable task, long delayInTicks, long intervalInTicks){ - int taskId = Prison.get().getPlatform().getScheduler().runTaskTimerAsync(task, delayInTicks, - intervalInTicks); - - return taskId; + int taskId = Prison.get().getPlatform().getScheduler().runTaskTimerAsync(task, delayInTicks, + intervalInTicks); + + return taskId; } /** @@ -68,14 +68,14 @@ public static int runTaskTimerAsync(Runnable task, long delayInTicks, long inter * @param taskId The task's ID. */ public static void cancelTask(int taskId) { - Prison.get().getPlatform().getScheduler().cancelTask( taskId ); + Prison.get().getPlatform().getScheduler().cancelTask( taskId ); } /** * Cancels all tasks registered through this scheduler. */ public static void cancelAll(){ - Prison.get().getPlatform().getScheduler().cancelAll(); + Prison.get().getPlatform().getScheduler().cancelAll(); } /** @@ -85,7 +85,7 @@ public static void cancelAll(){ * @return */ public static boolean isPrimaryThread() { - return Prison.get().getPlatform().getScheduler().isPrimaryThread(); + return Prison.get().getPlatform().getScheduler().isPrimaryThread(); } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/troubleshoot/inbuilt/ItemTroubleshooter.java b/prison-core/src/main/java/tech/mcprison/prison/troubleshoot/inbuilt/ItemTroubleshooter.java index d11e77076..b76ae86c7 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/troubleshoot/inbuilt/ItemTroubleshooter.java +++ b/prison-core/src/main/java/tech/mcprison/prison/troubleshoot/inbuilt/ItemTroubleshooter.java @@ -4,39 +4,14 @@ * Inbuilt troubleshooter to scan the 'items.csv' file to ensure it's valid. * * @author Faizaan A. Datoo + * + * @deprecated */ public class ItemTroubleshooter -// extends Troubleshooter - { +{ + + // NOTE: The commented out source in this class has been removed. See git's history to view it. + // This class was related to the old block model and would search through the old block + // text file to find something that may have matched a key phrase. -// public ItemTroubleshooter() { -// super("item_scan", "Run this if you have trouble with the items.csv file."); -// } -// -// @Override public TroubleshootResult invoke(CommandSender invoker) { -// -// // Let's do our own test of initializing the ItemManager. -// try { -// ItemManager ourManager = new ItemManager(); -// ourManager.getItems(); -// } catch (Exception e) { -// // OK, so something's wrong -// // Let's try deleting the file and telling the user to relaunch. -// -// File itemsCsv = new File(PrisonAPI.getPluginDirectory(), "items.csv"); -// boolean deleted = itemsCsv.delete(); -// if (deleted) { -// return new TroubleshootResult(TroubleshootResult.Result.USER_ACTION, -// "We've found a problem with your items.csv file. We deleted it so that a new and non-corrupted one is generated. Please restart your server for the changes to take effect."); -// } else { -// // We can only hot delete on *NIX systems. -// return new TroubleshootResult(TroubleshootResult.Result.FAILURE, -// "We've found a problem with your items.csv file. We tried deleting it, but it could not be successfully deleted. Please stop your server, delete '/plugins/Prison/items.csv', and start your server again."); -// } -// } -// -// // Nothing is wrong. -// return new TroubleshootResult(TroubleshootResult.Result.SUCCESS, -// "No problems were found with your item manager or items.csv file."); -// } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/BluesSemanticVersionComparator.java b/prison-core/src/main/java/tech/mcprison/prison/util/BluesSemanticVersionComparator.java new file mode 100644 index 000000000..f28c54565 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/util/BluesSemanticVersionComparator.java @@ -0,0 +1,160 @@ +package tech.mcprison.prison.util; + +import tech.mcprison.prison.Prison; + +/** + *

    This class provides a real comparator for semantic versioning + * for spiget. This addresses issues seen with incorrect notifications. + * Extensive unit tests back the correct functionality of this code base. + *

    + * + *

    Spiget's versions have totally failed on so many levels that they + * should not imply it has anything to do with semVer at all. + * The inherent problems with the solutions provided by spiget, is that they may work + * some of the time, but then fail once certain incorrect assumptions about semVers + * are realized. Intermittent failures are to be expected. For example, if someone + * is using version 2.3.11 and 2.4.0 is released, spiget's SEM_VER + * comparator will think the older version is newer than the current release. + * Why does that fail? Because they just remove the periods and take the remainder + * characters and then parse them all as one integer, then they compare integers. The + * context of major, minor, and patch is completely lost, plus it does not factor + * in prerelease tagging as semVer supports. + *

    + * + *

    To provide a product that actually works with real semVers, the website + * https://semver.org/ was used as the + * "standard" to base this functionality upon, and to which our tests are + * measured against. + *

    + * + *

    The result of the new architecture is a solution that ends up being very + * simple for this class. + *

    + * + * @author RoyalBlueRanger 2020-01-28 + * @return + */ +public class BluesSemanticVersionComparator +// extends VersionComparator +{ + + public boolean isNewer(String currentVersion, String checkVersion) { + return performComparisons( currentVersion, checkVersion); + } + + /** + *

    This function will take two String values and convert both to a + * SemanticVersioningData objects, that in turn, will parse the string + * and encapsulate the full representation as an object. Since this object + * implements comparable, its then as simple as comparing the new semVer to the + * current semVer to find out if it is actually newer. + *

    + * + *

    The semantic versions must be valid. At a minimum they have to + * have a format such as 1.0.0. If one is invalid, then compareTo will + * favor the valid semVer. If both are invalid then compareTo will return + * a negative -1000, which will equate to false result. + *

    + * + * @param currentVersion A String value representing the current semVer + * @param checkVersion A String value representing the checked semVer + * @return True if the checkVersion is a higher semVer than the current version + */ + public boolean performComparisons( String currentVersion, String checkVersion ) { + + BluesSemanticVersionData currentSemVer = new BluesSemanticVersionData(currentVersion); + BluesSemanticVersionData checkSemVer = new BluesSemanticVersionData(checkVersion); + + return (checkSemVer.compareTo( currentSemVer ) > 0); + } + + /** + *

    Example how to use: + *

    + * + *
    +	 * String ver = Bukkit.getVersion().trim();
    +	 * ver = ver.substring( ver.indexOf("(MC: ") + 5, ver.length() -1 );
    +	 * if ( new BluesSpigetSemVerComparator().compareTo(ver, "1.9.0") ) {
    +	 *     // if mc version is less than 1.9.0
    +	 * }
    +	 * 
    + * + * @param currentVersion + * @param checkVersion + * @return + */ + public int compareTo( String currentVersion, String checkVersion ) { + + BluesSemanticVersionData currentSemVer = new BluesSemanticVersionData(currentVersion); + BluesSemanticVersionData checkSemVer = new BluesSemanticVersionData(checkVersion); + + return currentSemVer.compareTo( checkSemVer ); + } + + /** + *

    This uses the minecraft version of the server to compare to the provided version. + *

    + * + *

    Samples of what a bukkit, spigot, and paper version would look like. Notice + * they all have the version at the end between (MC: and ). + *

    + * + *
      + *
    • Spigot 1.8.8: git-Spigot-21fe707-e1ebe52 (MC: 1.8.8)
    • + *
    • Spigot 1.10.2: git-Spigot-de459a2-51263e9 (MC: 1.10.2)
    • + *
    • Spigot 1.12.2: git-Spigot-79a30d7-acbc348 (MC: 1.12.2)
    • + *
    • Spigot 1.15.2: git-Spigot-2040c4c-893ad93 (MC: 1.15.2)
    • + *
    • Paper 1.10.2: git-Paper-916.2 (MC: 1.10.2)
    • + *
    • Paper 1.14.2: git-Paper-234 (MC: 1.14.4)
    • + *
    + * + * *

    Example how to use: + *

    + * + *
    +	 * if ( new BluesSpigetSemVerComparator().compareMCVersionTo("1.9.0") < 0 ) {
    +	 *     // if mc version is less than 1.9.0
    +	 * }
    +	 * 
    + * + * @param checkVersion + * @return + */ + public int compareMCVersionTo( String checkVersion ) { + int results = -1; + String currentVersion = getBukkitVersion(); + if ( currentVersion != null ) { + + results = compareTo( currentVersion, checkVersion ); + } + return results; + } + + public String getBukkitVersion() { + // Minecraft version: git-Paper-21 (MC: 1.15) + + return getBukkitVersion( getBukkitVersionRaw() ); + } + + + private String getBukkitVersionRaw() { + return Prison.get().getMinecraftVersion(); + } + + public String getBukkitVersion( String currentVersion ) { + String results = null; + + if ( currentVersion != null ) { + currentVersion = currentVersion.trim().toLowerCase(); + int i = currentVersion.indexOf("(mc:"); + int len = currentVersion.length(); + if ( i >= 0 && (i+4 < len)) { + results = currentVersion.substring( i + 4, len - 1 ).trim(); + } + } + + return results; + } + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/spiget/BluesSemanticVersionData.java b/prison-core/src/main/java/tech/mcprison/prison/util/BluesSemanticVersionData.java similarity index 99% rename from prison-spigot/src/main/java/tech/mcprison/prison/spigot/spiget/BluesSemanticVersionData.java rename to prison-core/src/main/java/tech/mcprison/prison/util/BluesSemanticVersionData.java index 87e06f588..510b3cd00 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/spiget/BluesSemanticVersionData.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/BluesSemanticVersionData.java @@ -1,4 +1,4 @@ -package tech.mcprison.prison.spigot.spiget; +package tech.mcprison.prison.util; import java.util.ArrayList; import java.util.List; diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/Bounds.java b/prison-core/src/main/java/tech/mcprison/prison/util/Bounds.java index 707f2b3bf..91a4af970 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/Bounds.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/Bounds.java @@ -18,6 +18,8 @@ package tech.mcprison.prison.util; +import java.util.Optional; + import tech.mcprison.prison.Prison; import tech.mcprison.prison.internal.World; @@ -298,16 +300,49 @@ public Bounds( Bounds bounds, Edges edge, int amount ) { } + + /** + *

    This function should be called after loading a mine from + * storage, and this function should reconnect all dynamic objects + * that could not be stored with the core Mine data. + *

    + * + *

    Examples: World objects. + *

    + */ + public void reconnectObjects() { + + if ( getMin() != null && getMin().getWorld() == null ) { + String worldName = getMin().getWorldName(); + + Optional worldOpt = Prison.get().getPlatform().getWorld(worldName); + + if ( worldOpt.isPresent() ) { + World world = worldOpt.get(); + + setWorld( world ); + } + } + } + + /** + *

    Sets the world on the min, max, and center objects. + * If the other locations have a different world set, it + * will be replaced with this new world. + *

    + * + * @param world + */ public void setWorld( World world ) { if ( world != null ) { - if ( getMin().getWorld() == null ) { + if ( getMin() != null ) { getMin().setWorld( world ); } - if ( getMax().getWorld() == null ) { + if ( getMax() != null ) { getMax().setWorld( world ); } - if ( getCenter().getWorld() == null ) { + if ( getCenter() != null ) { getCenter().setWorld( world ); } } @@ -355,11 +390,11 @@ public double getArea() { } public boolean within(Location location) { - return within( location, false, false ); + return within( location, false, false ); } public boolean withinIncludeTopBottomOfMine(Location location) { - return within( location, true, true ); + return within( location, true, true ); } /** @@ -374,27 +409,27 @@ public boolean withinIncludeTopBottomOfMine(Location location) { * @return true if the location is within the bounds, false otherwise. */ private boolean within(Location location, boolean includeTopOfMine, boolean includeOneBelowMine ) { - boolean results = false; - - if ( withinSameWorld( location )) { - - double ourX = Math.floor(location.getX()); - double ourY = Math.floor(location.getY()); - double ourZ = Math.floor(location.getZ()); - - results = ourX >= getxMin() && ourX <= getxMax() // Within X - && ourY >= (getyMin() - (includeOneBelowMine ? 1 : 0)) && - ourY <= (getyMax() + (includeTopOfMine ? 1 : 0)) // Within Y - && ourZ >= getzMin() && ourZ <= getzMax(); // Within Z - } + boolean results = false; + + if ( withinSameWorld( location )) { + + double ourX = Math.floor(location.getX()); + double ourY = Math.floor(location.getY()); + double ourZ = Math.floor(location.getZ()); + + results = ourX >= getxMin() && ourX <= getxMax() // Within X + && ourY >= (getyMin() - (includeOneBelowMine ? 1 : 0)) && + ourY <= (getyMax() + (includeTopOfMine ? 1 : 0)) // Within Y + && ourZ >= getzMin() && ourZ <= getzMax(); // Within Z + } return results; } public boolean withinSameWorld(Location location) { - return getCenter().getWorld() != null && location.getWorld() != null && - getCenter().getWorld().getName().equalsIgnoreCase( - location.getWorld().getName() ); + return getCenter().getWorld() != null && location.getWorld() != null && + getCenter().getWorld().getName().equalsIgnoreCase( + location.getWorld().getName() ); } /** @@ -413,17 +448,17 @@ public boolean withinSameWorld(Location location) { * @return */ public boolean within(Location location, long radius) { - boolean results = false; - - if ( withinSameWorld( location ) ) { + boolean results = false; + + if ( withinSameWorld( location ) ) { - // Ignore y since this is radius from the center axis of the mine: - double distance = getDistance(location); - - results = distance <= radius; - } + // Ignore y since this is radius from the center axis of the mine: + double distance = getDistance(location); + + results = distance <= radius; + } - return results; + return results; } /** @@ -432,38 +467,38 @@ public boolean within(Location location, long radius) { * @return */ public double getDistance() { - double deltaX = getMin().getX() - getMax().getX(); - double deltaZ = getMin().getZ() - getMax().getZ(); - double distance = Math.sqrt( (deltaX * deltaX) + (deltaZ * deltaZ) ); - return Math.round( distance ); + double deltaX = getMin().getX() - getMax().getX(); + double deltaZ = getMin().getZ() - getMax().getZ(); + double distance = Math.sqrt( (deltaX * deltaX) + (deltaZ * deltaZ) ); + return Math.round( distance ); } public double getDistance3d() { - double deltaX = getMin().getX() - getMax().getX(); - double deltaY = getMin().getY() - getMax().getY(); - double deltaZ = getMin().getZ() - getMax().getZ(); - double distance = Math.sqrt( (deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ) ); - return Math.round( distance ); + double deltaX = getMin().getX() - getMax().getX(); + double deltaY = getMin().getY() - getMax().getY(); + double deltaZ = getMin().getZ() - getMax().getZ(); + double distance = Math.sqrt( (deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ) ); + return Math.round( distance ); } public double getDistance(Location location) { - double deltaX = getCenter().getX() - location.getX(); - double deltaZ = getCenter().getZ() - location.getZ(); - double distance = Math.sqrt( (deltaX * deltaX) + (deltaZ * deltaZ) ); + double deltaX = getCenter().getX() - location.getX(); + double deltaZ = getCenter().getZ() - location.getZ(); + double distance = Math.sqrt( (deltaX * deltaX) + (deltaZ * deltaZ) ); return Math.round( distance ); } public double getDistance3d(Location location) { - double deltaX = getCenter().getX() - location.getX(); - double deltaY = getCenter().getY() - location.getY(); - double deltaZ = getCenter().getZ() - location.getZ(); - double distance = Math.sqrt( (deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ) ); - return distance; + double deltaX = getCenter().getX() - location.getX(); + double deltaY = getCenter().getY() - location.getY(); + double deltaZ = getCenter().getZ() - location.getZ(); + double distance = Math.sqrt( (deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ) ); + return distance; } public String getDimensions() { - return "&7" + Math.round(getWidth()) + "&8x&7" + - Math.round(getHeight()) + "&8x&7" + Math.round(getLength()); + return "&7" + Math.round(getWidth()) + "&8x&7" + + Math.round(getHeight()) + "&8x&7" + Math.round(getLength()); } public Location getMin() { @@ -478,12 +513,28 @@ public Location getCenter() { return center; } + - @Override public String toString() { + public double getRadius() { + double radius = getDistance3d() / 2.0; + return radius; + } + + + @Override + public String toString() { return "Bounds{" + "min=" + min.toCoordinates() + ", max=" + max.toCoordinates() + '}'; } - @Override public boolean equals(Object o) { + + /** + *

    This will check to see if two Bounds are equal. + * If any point is null, then this should always return + * false. + *

    + */ + @Override + public boolean equals(Object o) { if (this == o) { return true; } @@ -492,9 +543,16 @@ public Location getCenter() } Bounds bounds = (Bounds) o; - return min != null ? - min.equals(bounds.min) : - bounds.min == null && (max != null ? max.equals(bounds.max) : bounds.max == null); + + // If any point is null, then this must return false: + if ( getMin() == null || getMax() == null || + bounds.getMin() == null || bounds.getMax() == null ) { + return false; + } + + return getMin().equals(bounds.getMin()) && + getMax().equals(bounds.getMax()); + } @Override public int hashCode() { diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/ChatColor.java b/prison-core/src/main/java/tech/mcprison/prison/util/ChatColor.java index cba2bd4c1..5820a7fb1 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/ChatColor.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/ChatColor.java @@ -32,70 +32,64 @@ * @since API 1.0 */ public enum ChatColor { + BLACK('0', 0x00), + + DARK_BLUE('1', 0x1), + + DARK_GREEN('2', 0x2), + + DARK_AQUA('3', 0x3), + + DARK_RED('4', 0x4), + + DARK_PURPLE('5', 0x5), + + GOLD('6', 0x6), + + GRAY('7', 0x7), + + DARK_GRAY('8', 0x8), + + BLUE('9', 0x9), + + GREEN('a', 0xA), + + AQUA('b', 0xB), + + RED('c', 0xC), + + LIGHT_PURPLE('d', 0xD), + + YELLOW('e', 0xE), + + WHITE('f', 0xF), + /** - * Represents black - */ - BLACK('0', 0x00), /** - * Represents dark blue - */ - DARK_BLUE('1', 0x1), /** - * Represents dark green - */ - DARK_GREEN('2', 0x2), /** - * Represents dark blue (aqua) - */ - DARK_AQUA('3', 0x3), /** - * Represents dark red - */ - DARK_RED('4', 0x4), /** - * Represents dark purple - */ - DARK_PURPLE('5', 0x5), /** - * Represents gold - */ - GOLD('6', 0x6), /** - * Represents gray - */ - GRAY('7', 0x7), /** - * Represents dark gray - */ - DARK_GRAY('8', 0x8), /** - * Represents blue - */ - BLUE('9', 0x9), /** - * Represents green - */ - GREEN('a', 0xA), /** - * Represents aqua - */ - AQUA('b', 0xB), /** - * Represents red - */ - RED('c', 0xC), /** - * Represents light purple - */ - LIGHT_PURPLE('d', 0xD), /** - * Represents yellow - */ - YELLOW('e', 0xE), /** - * Represents white - */ - WHITE('f', 0xF), /** * Represents magical characters that change around randomly */ - MAGIC('k', 0x10, true), /** + MAGIC('k', 0x10, true), + + /** * Makes the text bold. */ - BOLD('l', 0x11, true), /** + BOLD('l', 0x11, true), + + /** * Makes a line appear through the text. */ - STRIKETHROUGH('m', 0x12, true), /** + STRIKETHROUGH('m', 0x12, true), + + /** * Makes the text appear underlined. */ - UNDERLINE('n', 0x13, true), /** + UNDERLINE('n', 0x13, true), + + /** * Makes the text italic. */ - ITALIC('o', 0x14, true), /** + ITALIC('o', 0x14, true), + + /** * Resets all previous chat colors or formats. */ RESET('r', 0x15); @@ -106,7 +100,7 @@ public enum ChatColor { */ public static final char COLOR_CHAR = '\u00A7'; private static final Pattern STRIP_COLOR_PATTERN = - Pattern.compile("(?i)" + String.valueOf(COLOR_CHAR) + "|&[0-9A-FK-OR]"); + Pattern.compile("(?i)" + String.valueOf(COLOR_CHAR) + "|&[0-9A-FK-OR]"); private final static Map BY_ID = Maps.newHashMap(); private final static Map BY_CHAR = Maps.newHashMap(); diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/CollectionUtil.java b/prison-core/src/main/java/tech/mcprison/prison/util/CollectionUtil.java index bc66ecbec..1486b4e1b 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/CollectionUtil.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/CollectionUtil.java @@ -31,16 +31,9 @@ */ public class CollectionUtil { - /* - * Constructor - */ - private CollectionUtil() { } - /* - * Methods - */ /** * Creates a map out of an infinite amount of parameters. Every odd parameter (1, 3, 5, etc.) is a diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/ConversionUtil.java b/prison-core/src/main/java/tech/mcprison/prison/util/ConversionUtil.java index b70e97444..1a09e5934 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/ConversionUtil.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/ConversionUtil.java @@ -4,11 +4,11 @@ public class ConversionUtil { public static int doubleToInt(Object d) { - return Math.toIntExact(Math.round((double) d)); + return d == null ? -1 : Math.toIntExact(Math.round((double) d)); } public static long doubleToLong(Object d) { - return Math.round((double) d); + return d == null ? -1 : Math.round((double) d); } } 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 b3cd94e07..92805762e 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 @@ -55,7 +55,6 @@ private ArrayList runSample() { sb.append( ".111111" ); DecimalFormat dFmt = new DecimalFormat( "#,##0.000000" ); -// DecimalFormat iFmt = new DecimalFormat( "#,##0.00000" ); for ( int i = 1; i < 35; i++ ) { sb.insert( 0, "1" ); diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/ItemManager.java b/prison-core/src/main/java/tech/mcprison/prison/util/ItemManager.java index 2d72b97aa..3a1aba47f 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/ItemManager.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/ItemManager.java @@ -26,60 +26,6 @@ */ public class ItemManager { -// private Multimap items; - + // This commented out code has been purged. See git for the history. - /** - * This has not been used for a while. Will need to provide an alternative way to - * add custom blocks. - * - * @throws Exception - */ -// @Deprecated -// public ItemManager() throws Exception { -// items = ArrayListMultimap.create(); -// /* -// File file = new File(Prison.get().getDataFolder(), "/items.csv"); -// -// if (!file.exists()) { -// try ( -// // make sure the InputStream is properly closed. May not be 100% needed here: -// InputStream inputStream = getClass().getResourceAsStream("/items.csv"); -// ) -// { -// Files.copy(inputStream, Paths.get(file.getPath())); -// } -// catch (Exception e) { -// throw new IOException("Error while copying items.csv from the jar resource to a " + -// "file within the plugins directory:", e); -// } -// } -// try ( -// // Was a memory leak... always must be closed, so the try with resource ensures that it is: -// BufferedReader in = new BufferedReader(new FileReader(file)); -// ) -// { -// String inputLine; -// -// while ((inputLine = in.readLine()) != null) { -// if (!inputLine.startsWith("#")) { -// String[] array = inputLine.split(","); -// String itemName = array[0]; -// int id = Integer.parseInt(array[1]); -// short data = Short.parseShort(array[2]); -// items.put(BlockType.getBlockWithData(id, data), itemName.toLowerCase()); -// } -// } -// -// } -// catch (Exception e) { -// throw new IOException("Error while reading items.csv -- it's probably invalid", e); -// } -// */ -// } -// -// public Map> getItems() { -// return items.asMap(); -// } - } 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 734a63a81..3921ff741 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 @@ -18,7 +18,14 @@ package tech.mcprison.prison.util; +import java.text.DecimalFormat; +import java.util.Optional; + import tech.mcprison.prison.Prison; +import tech.mcprison.prison.bombs.MineBombs.AnimationArmorStandItemLocation; +import tech.mcprison.prison.internal.ArmorStand; +import tech.mcprison.prison.internal.Entity; +import tech.mcprison.prison.internal.EntityType; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.block.PrisonBlock; @@ -31,7 +38,9 @@ */ public class Location { - private World world; + private transient World world; + private String worldName; + private double x, y, z; private float pitch, yaw; @@ -41,34 +50,65 @@ public class Location { private boolean isCorner; public Location(World world, double x, double y, double z, float pitch, float yaw, Vector direction) { - this.world = world; - this.x = x; - this.y = y; - this.z = z; - this.pitch = pitch; - this.yaw = yaw; - this.direction = direction; + this.world = world; + this.worldName = world == null ? null : world.getName(); + + this.x = x; + this.y = y; + this.z = z; + this.pitch = pitch; + this.yaw = yaw; + this.direction = direction; } + public Location(World world, double x, double y, double z, float pitch, float yaw) { - this( world, x, y, z, pitch, yaw, new Vector() ); + this( world, x, y, z, pitch, yaw, new Vector() ); } public Location(World world, double x, double y, double z) { - this( world, x, y, z, 0.0f, 0.0f); + this( world, x, y, z, 0.0f, 0.0f); } public Location(String worldName, int x, int y, int z) { - this( Prison.get().getPlatform().getWorld( worldName ).orElse( null ), (double) x, (double) y, (double) z ); + this( Prison.get().getPlatform().getWorld( worldName ).orElse( null ), (double) x, (double) y, (double) z ); } public Location(Location clone) { - this( clone.getWorld(), clone.getX(), clone.getY(), clone.getZ(), + this( clone.getWorld(), clone.getX(), clone.getY(), clone.getZ(), clone.getPitch(), clone.getYaw(), clone.getDirection()); } public Location() { } + public Location clone() { + return new Location( this ); + } + + + /** + *

    This function should be called after loading a mine from + * storage, and this function should reconnect all dynamic objects + * that could not be stored with the core Mine data. + *

    + * + *

    Examples: World objects. + *

    + */ + public void reconnectObects() { + if ( getWorld() == null ) { + String worldName = getWorldName(); + + Optional worldOpt = Prison.get().getPlatform().getWorld(worldName); + + if ( worldOpt.isPresent() ) { + World world = worldOpt.get(); + + setWorld( world ); + } + } + } + public World getWorld() { return world; } @@ -77,7 +117,14 @@ public void setWorld(World world) { this.world = world; } - public double getX() { + public String getWorldName() { + return worldName; + } + public void setWorldName(String worldName) { + this.worldName = worldName; + } + + public double getX() { return x; } @@ -121,20 +168,34 @@ public Vector getDirection() { return direction; } + /** + * Sets the {@link #getYaw() yaw} and {@link #getPitch() pitch} to point + * in the direction of the vector. + * + * @param vector the direction vector + * @return the same location + */ public void setDirection( Vector direction ) { this.direction = direction; } + /** + *

    Return the integer part of the double, which means + * it should not be rounded; use floor instead. + *

    + * + * @return + */ public int getBlockX() { - return Math.toIntExact(Math.round(getX())); + return (int) Math.floor(getX()); } public int getBlockY() { - return Math.toIntExact(Math.round(getY())); + return (int) Math.floor(getY()); } public int getBlockZ() { - return Math.toIntExact(Math.round(getZ())); + return (int) Math.floor(getZ()); } public Block getBlockAt() { @@ -142,11 +203,11 @@ public Block getBlockAt() { } public Block getBlockAt( boolean containsCustomBlocks ) { - return world.getBlockAt( this, containsCustomBlocks ); + return world.getBlockAt( this, containsCustomBlocks ); } public void setBlockAsync( PrisonBlock prisonBlock ) { - world.setBlockAsync( prisonBlock, this ); + world.setBlockAsync( prisonBlock, this ); } /** @@ -171,7 +232,42 @@ public void setCorner(boolean isCorner) { this.isCorner = isCorner; } - @Override public boolean equals(Object o) { + /** + *

    This compares to see if two different locations are the same. + *

    + * + *

    There are a few problems with this function. First we need to + * figure out if we want to check to see if we have exactly the same + * object or not, of which we shouldn't expect it to be the same object + * or we could just use the "==" equality test on the two objects. + * Therefore, we know it's not going to be the same object, but we want + * to determine if two objects are at the same location. This is + * yet another problem. What does it mean to be in the same location? + * If item A has an x value of 3.84928 and item B has 3.1489203 should + * that be the same location? Yes, it should. Because the two items + * are within the same "block" for that x value (ignoring y and z axis + * for this example). + *

    + * + *

    Therefore, this should check to see if two locations are within + * the same block or not. Likewise, where the "item" is looking should + * never be a factor since two items can be looking off in to different + * directions and still be in the same block. In other words, this + * check of having the same location is for the physical block, and not + * where they are looking. + *

    + * + *

    There may be situations were the pitch and yaw must match, but + * in general, it should not be used for this function. Also, the float + * values should NOT be used either since an x value of 3.123456 will not + * be considered in the same block if it has a value of 3.123450 since + * the block is not what that is checking. So integer values must + * be used in this method. + *

    + * + */ + @Override + public boolean equals(Object o) { if (this == o) { return true; } @@ -181,15 +277,21 @@ public void setCorner(boolean isCorner) { Location location = (Location) o; - return Double.compare(location.x, x) == 0 && Double.compare(location.y, y) == 0 - && Double.compare(location.z, z) == 0 && Float.compare(location.pitch, pitch) == 0 - && Float.compare(location.yaw, yaw) == 0 && (world != null ? - world.getName().equals(location.world.getName()) : - location.world == null); + // Must be in the same world: + if ( world == null || location.world == null || + !getWorld().getName().equalsIgnoreCase( location.getWorld().getName()) ) { + return false; + } + + + return location.getBlockX() == getBlockX() && + location.getBlockY() == getBlockY() && + location.getBlockZ() == getBlockZ(); } - @Override public int hashCode() { + @Override + public int hashCode() { int result; long temp; result = world != null ? world.hashCode() : 0; @@ -204,13 +306,26 @@ public void setCorner(boolean isCorner) { return result; } - @Override public String toString() { - return "Location{" + "world=" + world + ", x=" + x + ", y=" + y + ", z=" + z + ", pitch=" - + pitch + ", yaw=" + yaw + '}'; + @Override + public String toString() { + + DecimalFormat dFmt = new DecimalFormat( "0.00" ); + + return "Location{" + "world=" + world.getName() + ", " + + "x=" + dFmt.format(x) + ", " + + "y=" + dFmt.format(y) + ", " + + "z=" + dFmt.format(z) + ", " + + "pitch=" + dFmt.format(pitch) + ", " + + "yaw=" + dFmt.format(yaw) + '}'; } /** - * Returns the values in coordinate (x, y, z) format. + *

    Returns the values in coordinate '(x, y, z)' format. + * Uses doubles with no rounding. Has spaces after the commas. + *

    + * + *

    Example: (-15.1, 35.666667, 124.000325) + *

    * * @return The {@link String} containing coordinates. */ @@ -218,29 +333,51 @@ public String toCoordinates() { return "(" + x + ", " + y + ", " + z + ")"; } - + /** + *

    Returns the values in coordinate '(worldName, x, y, z)' format. + * Uses only the integer part of the doubles with no rounding. Has spaces after the commas. + *

    + * + *

    Example: (PrisonWorld, -15, 35, 124) + *

    + * @return + */ public String toWorldCoordinates() { - return "(" + world.getName() + "," + ((int) x) + "," + ((int) y) + "," + ((int) z) + ")"; + return "(" + world.getName() + "," + ((int) x) + "," + ((int) y) + "," + ((int) z) + ")"; } + /** + *

    Using a String value of the WorldCoordinates, decodes the string value + * to a Location object. + *

    + * + * @param worldCoordinats such as '(PrisonWorld, -15, 35, 124)' + * @return + */ public static Location decodeWorldCoordinates( String worldCoordinats ) { - Location results = null; - String[] d = worldCoordinats.replaceAll( "\\(|\\)", "" ).split( "," ); - - if ( d != null && d.length == 4 ) { - results = new Location( d[0], Integer.parseInt( d[1] ), Integer.parseInt( d[2] ), Integer.parseInt( d[3] ) ); - } - return results; + Location results = null; + String[] d = worldCoordinats.replaceAll( "\\(|\\)", "" ).split( "," ); + + if ( d != null && d.length == 4 ) { + results = new Location( d[0], Integer.parseInt( d[1] ), Integer.parseInt( d[2] ), Integer.parseInt( d[3] ) ); + } + return results; } /** - * Returns the values in coordinate (x, y, z) format, to the nearest block (i.e. no decimals). - * + *

    Returns the values in coordinate '(x, y, z)' format, to the nearest + * block (i.e. no decimals, rounded, spaces after commas). + *

    + * + *

    Example: (-15, 35, 124) + *

    + * * @return The {@link String} containing coordinates. */ public String toBlockCoordinates() { return "(" + Math.round(x) + ", " + Math.round(y) + ", " + Math.round(z) + ")"; } + public Location add( Vector direction ) { Location results = new Location( this ); @@ -253,6 +390,19 @@ public Location add( Vector direction ) return results; } + /** + * This returns a vector based upon the current location. + * + * Note that this is based upon org.bucket.location.Location.toVector() and + * it does not use yaw. + * + * @return + */ + public Vector toVector() { + Vector results = new Vector( getX(), getY(), getZ() ); + return results; + } + /** *

    This function will clone the current location object and then add/subtract the amount of * x, y, and/or z to that location. To keep the same value for one or more of these coordinates @@ -290,5 +440,21 @@ public Block getBlockAtDelta( int x, int y, int z ) return getWorld().getBlockAt( results ); } + + public Entity spawnEntity( EntityType entityType ) { + return getWorld().spawnEntity( this, entityType ); + } + + public ArmorStand spawnArmorStand() { + return getWorld().spawnArmorStand( this ); + } + + public ArmorStand spawnArmorStand( String itemName, AnimationArmorStandItemLocation asLocation ) { + + return getWorld().spawnArmorStand( this, itemName, asLocation ); + } + + + } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/MaterialType.java b/prison-core/src/main/java/tech/mcprison/prison/util/MaterialType.java index 7776831f4..d2c1051a9 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/MaterialType.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/MaterialType.java @@ -2,11 +2,14 @@ public enum MaterialType { - BLOCK, - ITEM, + // NOTE: This is no longer used. This was used with the old block system. + not_used; - NOT_SET, - - INVALID; +// BLOCK, +// ITEM, +// +// NOT_SET, +// +// INVALID; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/MaterialVersion.java b/prison-core/src/main/java/tech/mcprison/prison/util/MaterialVersion.java index 2374c5a27..7dba2bac4 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/MaterialVersion.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/MaterialVersion.java @@ -2,17 +2,20 @@ public enum MaterialVersion { - v1_8, + // NOTE: This is no longer used. This was used with the old block system. + not_used; - v1_9, - v1_10, - - v1_11, - v1_12, - v1_13, - - v1_14, - v1_15, - v1_16 - ; +// v1_8, +// +// v1_9, +// v1_10, +// +// v1_11, +// v1_12, +// v1_13, +// +// v1_14, +// v1_15, +// v1_16 +// ; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/ObsoleteBlockType.java b/prison-core/src/main/java/tech/mcprison/prison/util/ObsoleteBlockType.java index cbf4e6c34..dcc24c53e 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/ObsoleteBlockType.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/ObsoleteBlockType.java @@ -18,10 +18,6 @@ package tech.mcprison.prison.util; -import java.util.ArrayList; -import java.util.List; - - /** *

    All of the old blocks in the game. This list is obsolete, and was used in * v3.2.0 and earlier. It because obsolete with the new block model which was @@ -54,1267 +50,7 @@ @Deprecated public enum ObsoleteBlockType { - /** - * Identifying a block as a MaterialType.BLOCK will allow the - * block search to only show entries that will be placable within a mine. - * - * Cannot dynamically check for blocks at run time since each major version - * has slightly different sets and the names of this enum do not match the names - * of the Material. - */ - - IGNORE( -1, "prison:ignore", -1, MaterialType.BLOCK ), - NULL_BLOCK( -2, "prison:null_block", -1, MaterialType.INVALID ), - - - // This was auto-generated from WorldEdit's blocks.json - // @formatter:off - - - // NOTE: Double slabs are ones that players cannot naturally place, and they are - // similar to the main block type. It appears like they have been replaced, - // but not sure with what. I suspect no one will use them anyway, and if they - // do, then mapping them to their counter part block. There are a few doubles - // that have been mapped to "smooth" in the later versions, so they are used when - // possible. - - - DOUBLE_STONE_SLAB( 43, "minecraft:double_stone_slab", 0, MaterialType.BLOCK, "smooth_stone" ), - DOUBLE_SANDSTONE_SLAB( 43, "minecraft:double_stone_slab", 1, MaterialType.BLOCK, "smooth_sandstone_slab" ), - DOUBLE_WOODEN_SLAB( 43, "minecraft:double_stone_slab", 2, MaterialType.BLOCK, "OAK_PLANKS" ), - DOUBLE_COBBLESTONE_SLAB( 43, "minecraft:double_stone_slab", 3, MaterialType.BLOCK, "COBBLESTONE" ), - DOUBLE_BRICK_SLAB( 43, "minecraft:double_stone_slab", 4, MaterialType.BLOCK, "BRICKS" ), - DOUBLE_STONE_BRICK_SLAB( 43, "minecraft:double_stone_slab", 5, MaterialType.BLOCK, "STONE_BRICKS" ), - DOUBLE_NETHER_BRICK_SLAB( 43, "minecraft:double_stone_slab", 6, MaterialType.BLOCK, "NETHER_BRICKS" ), - DOUBLE_QUARTZ_SLAB( 43, "minecraft:double_stone_slab", 7, MaterialType.BLOCK, "SMOOTH_QUARTZ" ), - - DOUBLE_OAK_WOOD_SLAB( 125, "minecraft:double_wooden_slab", 0, MaterialType.BLOCK, "OAK_PLANKS" ), - DOUBLE_SPRUCE_WOOD_SLAB( 125, "minecraft:double_wooden_slab", 1, MaterialType.BLOCK, "SPRUCE_PLANKS" ), - DOUBLE_BIRCH_WOOD_SLAB( 125, "minecraft:double_wooden_slab", 2, MaterialType.BLOCK, "BIRCH_PLANKS" ), - DOUBLE_JUNGLE_WOOD_SLAB( 125, "minecraft:double_wooden_slab", 3, MaterialType.BLOCK, "JUNGLE_PLANKS" ), - DOUBLE_ACACIA_WOOD_SLAB( 125, "minecraft:double_wooden_slab", 4, MaterialType.BLOCK, "ACACIA_PLANKS" ), - DOUBLE_DARK_OAK_WOOD_SLAB( 125, "minecraft:double_wooden_slab", 5, MaterialType.BLOCK, "DARK_OAK_PLANKS" ), - - DOUBLE_RED_SANDSTONE_SLAB( 181, "minecraft:double_stone_slab2", 0, MaterialType.BLOCK, "RED_SANDSTONE" ), - PURPUR_DOUBLE_SLAB( 204, "minecraft:purpur_double_slab", 0, MaterialType.BLOCK, "PURPUR_BLOCK" ), - - - - AIR( 0, "minecraft:air", 0, MaterialType.BLOCK ), - STONE( 1, "minecraft:stone", 0, MaterialType.BLOCK ), - GRANITE( 1, "minecraft:stone", 1, MaterialType.BLOCK ), - POLISHED_GRANITE( 1, "minecraft:stone", 2, MaterialType.BLOCK ), - DIORITE( 1, "minecraft:stone", 3, MaterialType.BLOCK ), - POLISHED_DIORITE( 1, "minecraft:stone", 4, MaterialType.BLOCK ), - ANDESITE( 1, "minecraft:stone", 5, MaterialType.BLOCK ), - POLISHED_ANDESITE( 1, "minecraft:stone", 6, MaterialType.BLOCK ), - - GRASS( 2, "minecraft:grass", 0, MaterialType.BLOCK ), - GRASS_BLOCK( 2, "minecraft:grass_block", 0, MaterialType.BLOCK ), - - DIRT( 3, "minecraft:dirt", 0, MaterialType.BLOCK ), - COARSE_DIRT( 3, "minecraft:dirt", 1, MaterialType.BLOCK ), - PODZOL( 3, "minecraft:dirt", 2, MaterialType.BLOCK ), - COBBLESTONE( 4, "minecraft:cobblestone", 0, MaterialType.BLOCK ), - - OAK_WOOD_PLANK( 5, "minecraft:planks", 0, MaterialType.BLOCK, "OAK_PLANKS" ), - SPRUCE_WOOD_PLANK( 5, "minecraft:planks", 1, MaterialType.BLOCK, "SPRUCE_PLANKS" ), - BIRCH_WOOD_PLANK( 5, "minecraft:planks", 2, MaterialType.BLOCK, "BIRCH_PLANKS" ), - JUNGLE_WOOD_PLANK( 5, "minecraft:planks", 3, MaterialType.BLOCK, "JUNGLE_PLANKS" ), - ACACIA_WOOD_PLANK( 5, "minecraft:planks", 4, MaterialType.BLOCK, "ACACIA_PLANKS" ), - DARK_OAK_WOOD_PLANK( 5, "minecraft:planks", 5, MaterialType.BLOCK, "DARK_OAK_PLANKS" ), - - OAK_SAPLING( 6, "minecraft:sapling", 0, MaterialType.BLOCK ), - SPRUCE_SAPLING( 6, "minecraft:sapling", 1, MaterialType.BLOCK ), - BIRCH_SAPLING( 6, "minecraft:sapling", 2, MaterialType.BLOCK ), - JUNGLE_SAPLING( 6, "minecraft:sapling", 3, MaterialType.BLOCK ), - ACACIA_SAPLING( 6, "minecraft:sapling", 4, MaterialType.BLOCK ), - DARK_OAK_SAPLING( 6, "minecraft:sapling", 5, MaterialType.BLOCK ), - BEDROCK( 7, "minecraft:bedrock", 0, MaterialType.BLOCK ), - - FLOWING_WATER( 8, "minecraft:flowing_water", 0, MaterialType.BLOCK, "WATER" ), - - STILL_WATER( 9, "minecraft:water", 0, MaterialType.BLOCK, "STATIONARY_WATER"), - - STATIONARY_WATER_01( 9, "minecraft:water", 1, MaterialType.BLOCK, "STATIONARY_WATER"), - STATIONARY_WATER_02( 9, "minecraft:water", 2, MaterialType.BLOCK, "STATIONARY_WATER"), - STATIONARY_WATER_03( 9, "minecraft:water", 3, MaterialType.BLOCK, "STATIONARY_WATER"), - STATIONARY_WATER_04( 9, "minecraft:water", 4, MaterialType.BLOCK, "STATIONARY_WATER"), - STATIONARY_WATER_05( 9, "minecraft:water", 5, MaterialType.BLOCK, "STATIONARY_WATER"), - STATIONARY_WATER_06( 9, "minecraft:water", 6, MaterialType.BLOCK, "STATIONARY_WATER"), - STATIONARY_WATER_07( 9, "minecraft:water", 7, MaterialType.BLOCK, "STATIONARY_WATER"), - STATIONARY_WATER_08( 9, "minecraft:water", 8, MaterialType.BLOCK, "STATIONARY_WATER"), - STATIONARY_WATER_09( 9, "minecraft:water", 9, MaterialType.BLOCK, "STATIONARY_WATER"), - STATIONARY_WATER_10( 9, "minecraft:water", 10, MaterialType.BLOCK, "STATIONARY_WATER"), - - - FLOWING_LAVA( 10, "minecraft:flowing_lava", 0, MaterialType.BLOCK, "LAVA" ), - STILL_LAVA( 11, "minecraft:lava", 0, MaterialType.BLOCK ), - - SAND( 12, "minecraft:sand", 0, MaterialType.BLOCK ), - RED_SAND( 12, "minecraft:sand", 1, MaterialType.BLOCK ), - GRAVEL( 13, "minecraft:gravel", 0, MaterialType.BLOCK ), - GOLD_ORE( 14, "minecraft:gold_ore", 0, MaterialType.BLOCK ), - IRON_ORE( 15, "minecraft:iron_ore", 0, MaterialType.BLOCK ), - COAL_ORE( 16, "minecraft:coal_ore", 0, MaterialType.BLOCK ), - - OAK_WOOD( 17, "minecraft:log", 0, MaterialType.BLOCK ), - SPRUCE_WOOD( 17, "minecraft:log", 1, MaterialType.BLOCK ), - BIRCH_WOOD( 17, "minecraft:log", 2, MaterialType.BLOCK ), - JUNGLE_WOOD( 17, "minecraft:log", 3, MaterialType.BLOCK, "jungle_planks" ), - - OAK_LEAVES( 18, "minecraft:leaves", 0, MaterialType.BLOCK ), - SPRUCE_LEAVES( 18, "minecraft:leaves", 1, MaterialType.BLOCK ), - BIRCH_LEAVES( 18, "minecraft:leaves", 2, MaterialType.BLOCK ), - JUNGLE_LEAVES( 18, "minecraft:leaves", 3, MaterialType.BLOCK ), - - SPONGE( 19, "minecraft:sponge", 0, MaterialType.BLOCK ), - WET_SPONGE( 19, "minecraft:sponge", 1, MaterialType.BLOCK ), - GLASS( 20, "minecraft:glass", 0, MaterialType.BLOCK ), - - - LAPIS_ORE( 21, "minecraft:lapis_ore", 0, MaterialType.BLOCK, "LAPIS_LAZULI_ORE" ), - LAPIS_LAZULI_ORE( 21, "minecraft:lapis_ore", 0, MaterialType.BLOCK ), // obsolete... - - LAPIS_BLOCK( 22, "minecraft:lapis_block", 0, MaterialType.BLOCK, "LAPIS_LAZULI_BLOCK" ), - LAPIS_LAZULI_BLOCK( 22, "minecraft:lapis_block", 0, MaterialType.BLOCK ), // obsolete... - - DISPENSER( 23, "minecraft:dispenser", 0, MaterialType.BLOCK ), - SANDSTONE( 24, "minecraft:sandstone", 0, MaterialType.BLOCK ), - CHISELED_SANDSTONE( 24, "minecraft:sandstone", 1, MaterialType.BLOCK ), - SMOOTH_SANDSTONE( 24, "minecraft:sandstone", 2, MaterialType.BLOCK ), - NOTE_BLOCK( 25, "minecraft:noteblock", 0, MaterialType.BLOCK ), - BED( 26, "minecraft:bed", 0 ), - POWERED_RAIL( 27, "minecraft:golden_rail", 0, MaterialType.BLOCK ), - DETECTOR_RAIL( 28, "minecraft:detector_rail", 0, MaterialType.BLOCK ), - STICKY_PISTON( 29, "minecraft:sticky_piston", 0, MaterialType.BLOCK ), - COBWEB( 30, "minecraft:web", 0, MaterialType.BLOCK ), - DEAD_SHRUB( 31, "minecraft:tallgrass", 0, MaterialType.BLOCK, "DEAD_BUSH" ), - TALL_GRASS( 31, "minecraft:tallgrass", 1, MaterialType.BLOCK ), - FERN( 31, "minecraft:tallgrass", 2, MaterialType.BLOCK ), - DEAD_BUSH( 32, "minecraft:deadbush", 0, MaterialType.BLOCK, "DEAD_BUSH" ), - PISTON( 33, "minecraft:piston", 0, MaterialType.BLOCK ), - PISTON_HEAD( 34, "minecraft:piston_head", 0, MaterialType.BLOCK ), - WHITE_WOOL( 35, "minecraft:wool", 0, MaterialType.BLOCK ), - ORANGE_WOOL( 35, "minecraft:wool", 1, MaterialType.BLOCK ), - MAGENTA_WOOL( 35, "minecraft:wool", 2, MaterialType.BLOCK ), - LIGHT_BLUE_WOOL( 35, "minecraft:wool", 3, MaterialType.BLOCK ), - YELLOW_WOOL( 35, "minecraft:wool", 4, MaterialType.BLOCK ), - LIME_WOOL( 35, "minecraft:wool", 5, MaterialType.BLOCK ), - PINK_WOOL( 35, "minecraft:wool", 6, MaterialType.BLOCK ), - GRAY_WOOL( 35, "minecraft:wool", 7, MaterialType.BLOCK ), - LIGHT_GRAY_WOOL( 35, "minecraft:wool", 8, MaterialType.BLOCK ), - CYAN_WOOL( 35, "minecraft:wool", 9, MaterialType.BLOCK ), - PURPLE_WOOL( 35, "minecraft:wool", 10, MaterialType.BLOCK ), - BLUE_WOOL( 35, "minecraft:wool", 11, MaterialType.BLOCK ), - BROWN_WOOL( 35, "minecraft:wool", 12, MaterialType.BLOCK ), - GREEN_WOOL( 35, "minecraft:wool", 13, MaterialType.BLOCK ), - RED_WOOL( 35, "minecraft:wool", 14, MaterialType.BLOCK ), - BLACK_WOOL( 35, "minecraft:wool", 15, MaterialType.BLOCK ), - - DANDELION( 37, "minecraft:yellow_flower", 0, MaterialType.BLOCK ), - POPPY( 38, "minecraft:red_flower", 0, MaterialType.BLOCK, "RED_ROSE" ), - BLUE_ORCHID( 38, "minecraft:red_flower", 1, MaterialType.BLOCK ), - ALLIUM( 38, "minecraft:red_flower", 2, MaterialType.BLOCK ), - AZURE_BLUET( 38, "minecraft:red_flower", 3, MaterialType.BLOCK, "AZURE_BLUET" ), - RED_TULIP( 38, "minecraft:red_flower", 4, MaterialType.BLOCK ), - ORANGE_TULIP( 38, "minecraft:red_flower", 5, MaterialType.BLOCK ), - WHITE_TULIP( 38, "minecraft:red_flower", 6, MaterialType.BLOCK ), - PINK_TULIP( 38, "minecraft:red_flower", 7, MaterialType.BLOCK ), - OXEYE_DAISY( 38, "minecraft:red_flower", 8, MaterialType.BLOCK ), - BROWN_MUSHROOM( 39, "minecraft:brown_mushroom", 0, MaterialType.BLOCK ), - RED_MUSHROOM( 40, "minecraft:red_mushroom", 0, MaterialType.BLOCK ), - GOLD_BLOCK( 41, "minecraft:gold_block", 0, MaterialType.BLOCK ), - IRON_BLOCK( 42, "minecraft:iron_block", 0, MaterialType.BLOCK ), - - - STONE_SLAB( 44, "minecraft:stone_slab", 0, MaterialType.BLOCK ), - SANDSTONE_SLAB( 44, "minecraft:stone_slab", 1, MaterialType.BLOCK ), - WOODEN_SLAB( 44, "minecraft:stone_slab", 2, MaterialType.BLOCK ), - COBBLESTONE_SLAB( 44, "minecraft:stone_slab", 3, MaterialType.BLOCK ), - BRICK_SLAB( 44, "minecraft:stone_slab", 4, MaterialType.BLOCK, "STONE_BRICK_SLAB" ), - STONE_BRICK_SLAB( 44, "minecraft:stone_slab", 5, MaterialType.BLOCK ), - NETHER_BRICK_SLAB( 44, "minecraft:stone_slab", 6, MaterialType.BLOCK ), - QUARTZ_SLAB( 44, "minecraft:stone_slab", 7, MaterialType.BLOCK ), - BRICKS( 45, "minecraft:brick_block", 0, MaterialType.BLOCK ), - TNT( 46, "minecraft:tnt", 0, MaterialType.BLOCK ), - BOOKSHELF( 47, "minecraft:bookshelf", 0, MaterialType.BLOCK ), - - MOSSY_COBBLESTONE( 48, "minecraft:mossy_cobblestone", 0, MaterialType.BLOCK, "MOSSY_COBBLESTONE" ), - MOSS_STONE( 48, "minecraft:mossy_cobblestone", 0, MaterialType.BLOCK, "MOSSY_COBBLESTONE", "MOSS_STONE" ), - - OBSIDIAN( 49, "minecraft:obsidian", 0, MaterialType.BLOCK ), - TORCH( 50, "minecraft:torch", 0, MaterialType.BLOCK ), - FIRE( 51, "minecraft:fire", 0, MaterialType.BLOCK ), - MONSTER_SPAWNER( 52, "minecraft:mob_spawner", 0, MaterialType.BLOCK ), - OAK_WOOD_STAIRS( 53, "minecraft:oak_stairs", 0, MaterialType.BLOCK ), - CHEST( 54, "minecraft:chest", 0, MaterialType.BLOCK ), - REDSTONE_WIRE( 55, "minecraft:redstone_wire", 0, MaterialType.BLOCK ), - DIAMOND_ORE( 56, "minecraft:diamond_ore", 0, MaterialType.BLOCK ), - DIAMOND_BLOCK( 57, "minecraft:diamond_block", 0, MaterialType.BLOCK ), - CRAFTING_TABLE( 58, "minecraft:crafting_table", 0, MaterialType.BLOCK ), - WHEAT_CROPS( 59, "minecraft:wheat", 0, MaterialType.BLOCK ), - FARMLAND( 60, "minecraft:farmland", 0, MaterialType.BLOCK ), - FURNACE( 61, "minecraft:furnace", 0, MaterialType.BLOCK ), - BURNING_FURNACE( 62, "minecraft:lit_furnace", 0, MaterialType.BLOCK ), - STANDING_SIGN_BLOCK( 63, "minecraft:standing_sign", 0, MaterialType.BLOCK, "OAK_SIGN" ), - OAK_DOOR_BLOCK( 64, "minecraft:wooden_door", 0, MaterialType.BLOCK ), - LADDER( 65, "minecraft:ladder", 0, MaterialType.BLOCK ), - RAIL( 66, "minecraft:rail", 0, MaterialType.BLOCK ), - COBBLESTONE_STAIRS( 67, "minecraft:stone_stairs", 0, MaterialType.BLOCK ), - WALL_MOUNTED_SIGN_BLOCK( 68, "minecraft:wall_sign", 0 ), - LEVER( 69, "minecraft:lever", 0, MaterialType.BLOCK ), - STONE_PRESSURE_PLATE( 70, "minecraft:stone_pressure_plate", 0, MaterialType.BLOCK ), - IRON_DOOR_BLOCK( 71, "minecraft:iron_door", 0, MaterialType.BLOCK ), - - WOODEN_PRESSURE_PLATE( 72, "minecraft:wooden_pressure_plate", 0, MaterialType.BLOCK, - "OAK_PRESSURE_PLATE", "WOOD_PLATE" ), - REDSTONE_ORE( 73, "minecraft:redstone_ore", 0, MaterialType.BLOCK ), - - GLOWING_REDSTONE_ORE( 74, "minecraft:lit_redstone_ore", 0, MaterialType.BLOCK ), - REDSTONE_TORCH_OFF( 75, "minecraft:unlit_redstone_torch", 0, MaterialType.BLOCK ), - REDSTONE_TORCH_ON( 76, "minecraft:redstone_torch", 0, MaterialType.BLOCK ), - STONE_BUTTON( 77, "minecraft:stone_button", 0, MaterialType.BLOCK ), - - SNOW( 78, "minecraft:snow_layer", 0, MaterialType.BLOCK ), - ICE( 79, "minecraft:ice", 0, MaterialType.BLOCK ), - SNOW_BLOCK( 80, "minecraft:snow", 0, MaterialType.BLOCK ), - - CACTUS( 81, "minecraft:cactus", 0, MaterialType.BLOCK ), - - CLAY( 82, "minecraft:clay", 0, MaterialType.BLOCK, "HARD_CLAY" ), - SUGAR_CANES( 83, "minecraft:reeds", 0, MaterialType.BLOCK, "SUGAR_CANE", "SUGAR_CANE_BLOCK" ), - JUKEBOX( 84, "minecraft:jukebox", 0, MaterialType.BLOCK ), - OAK_FENCE( 85, "minecraft:fence", 0, MaterialType.BLOCK ), - PUMPKIN( 86, "minecraft:pumpkin", 0, MaterialType.BLOCK ), - NETHERRACK( 87, "minecraft:netherrack", 0, MaterialType.BLOCK ), - - SOUL_SAND( 88, "minecraft:soul_sand", 0, MaterialType.BLOCK ), - GLOWSTONE( 89, "minecraft:glowstone", 0, MaterialType.BLOCK ), - NETHER_PORTAL( 90, "minecraft:portal", 0, MaterialType.BLOCK ), - - JACK_OLANTERN( 91, "minecraft:lit_pumpkin", 0, MaterialType.BLOCK, "jack_o_lantern" ), - - CAKE_BLOCK( 92, "minecraft:cake", 0, MaterialType.BLOCK ), - - REDSTONE_REPEATER_BLOCK_OFF( 93, "minecraft:unpowered_repeater", 0, MaterialType.BLOCK, "REPEATER" ), - REDSTONE_REPEATER_BLOCK_ON( 94, "minecraft:powered_repeater", 0, MaterialType.BLOCK, "REPEATER" ), - - WHITE_STAINED_GLASS( 95, "minecraft:stained_glass", 0, MaterialType.BLOCK ), - ORANGE_STAINED_GLASS( 95, "minecraft:stained_glass", 1, MaterialType.BLOCK ), - MAGENTA_STAINED_GLASS( 95, "minecraft:stained_glass", 2, MaterialType.BLOCK ), - LIGHT_BLUE_STAINED_GLASS( 95, "minecraft:stained_glass", 3, MaterialType.BLOCK ), - YELLOW_STAINED_GLASS( 95, "minecraft:stained_glass", 4, MaterialType.BLOCK ), - LIME_STAINED_GLASS( 95, "minecraft:stained_glass", 5, MaterialType.BLOCK ), - PINK_STAINED_GLASS( 95, "minecraft:stained_glass", 6, MaterialType.BLOCK ), - GRAY_STAINED_GLASS( 95, "minecraft:stained_glass", 7, MaterialType.BLOCK ), - LIGHT_GRAY_STAINED_GLASS( 95, "minecraft:stained_glass", 8, MaterialType.BLOCK ), - CYAN_STAINED_GLASS( 95, "minecraft:stained_glass", 9, MaterialType.BLOCK ), - PURPLE_STAINED_GLASS( 95, "minecraft:stained_glass", 10, MaterialType.BLOCK ), - BLUE_STAINED_GLASS( 95, "minecraft:stained_glass", 11, MaterialType.BLOCK ), - BROWN_STAINED_GLASS( 95, "minecraft:stained_glass", 12, MaterialType.BLOCK ), - GREEN_STAINED_GLASS( 95, "minecraft:stained_glass", 13, MaterialType.BLOCK ), - RED_STAINED_GLASS( 95, "minecraft:stained_glass", 14, MaterialType.BLOCK ), - BLACK_STAINED_GLASS( 95, "minecraft:stained_glass", 15, MaterialType.BLOCK ), - WOODEN_TRAPDOOR( 96, "minecraft:trapdoor", 0, MaterialType.BLOCK, "oak_trapdoor" ), - - STONE_MONSTER_EGG( 97, "minecraft:monster_egg", 0, MaterialType.BLOCK, "INFESTED_STONE" ), - COBBLESTONE_MONSTER_EGG( 97, "minecraft:monster_egg", 1, MaterialType.BLOCK, "INFESTED_COBBLESTONE" ), - STONE_BRICK_MONSTER_EGG( 97, "minecraft:monster_egg", 2, MaterialType.BLOCK, "INFESTED_STONE_BRICKS" ), - MOSSY_STONE_BRICK_MONSTER_EGG( 97, "minecraft:monster_egg", 3, MaterialType.BLOCK, "INFESTED_MOSSY_STONE_BRICKS" ), - CRACKED_STONE_BRICK_MONSTER_EGG( 97, "minecraft:monster_egg", 4, MaterialType.BLOCK, "INFESTED_CRACKED_STONE_BRICKS" ), - CHISELED_STONE_BRICK_MONSTER_EGG( 97, "minecraft:monster_egg", 5, MaterialType.BLOCK, "INFESTED_CHISELED_STONE_BRICKS" ), - - STONE_BRICKS( 98, "minecraft:stonebrick", 0, MaterialType.BLOCK, "STONE_BRICKS" ), - MOSSY_STONE_BRICKS( 98, "minecraft:stonebrick", 1, MaterialType.BLOCK, "MOSSY_STONE_BRICKS" ), - CRACKED_STONE_BRICKS( 98, "minecraft:stonebrick", 2, MaterialType.BLOCK, "CRACKED_STONE_BRICKS" ), - CHISELED_STONE_BRICKS( 98, "minecraft:stonebrick", 3, MaterialType.BLOCK, "CHISELED_STONE_BRICKS" ), - - BROWN_MUSHROOM_BLOCK( 99, "minecraft:brown_mushroom_block", 0, MaterialType.BLOCK ), - HUGE_MUSHROOM_1( 99, "minecraft:brown_mushroom_block", 14, MaterialType.BLOCK ), - RED_MUSHROOM_BLOCK( 100, "minecraft:red_mushroom_block", 0, MaterialType.BLOCK ), - HUGE_MUSHROOM_2( 100, "minecraft:red_mushroom_block", 14, MaterialType.BLOCK ), - - IRON_BARS( 101, "minecraft:iron_bars", 0, MaterialType.BLOCK ), - GLASS_PANE( 102, "minecraft:glass_pane", 0, MaterialType.BLOCK ), - MELON_BLOCK( 103, "minecraft:melon_block", 0, MaterialType.BLOCK ), - PUMPKIN_STEM( 104, "minecraft:pumpkin_stem", 0, MaterialType.BLOCK ), - MELON_STEM( 105, "minecraft:melon_stem", 0, MaterialType.BLOCK ), - VINES( 106, "minecraft:vine", 0, MaterialType.BLOCK ), - OAK_FENCE_GATE( 107, "minecraft:fence_gate", 0, MaterialType.BLOCK ), - BRICK_STAIRS( 108, "minecraft:brick_stairs", 0, MaterialType.BLOCK ), - STONE_BRICK_STAIRS( 109, "minecraft:stone_brick_stairs", 0, MaterialType.BLOCK ), - MYCELIUM( 110, "minecraft:mycelium", 0, MaterialType.BLOCK ), - LILY_PAD( 111, "minecraft:waterlily", 0, MaterialType.ITEM ), - - NETHER_BRICK( 112, "minecraft:nether_brick", 0, MaterialType.ITEM ), - NETHER_BRICK_FENCE( 113, "minecraft:nether_brick_fence", 0, MaterialType.BLOCK ), - NETHER_BRICK_STAIRS( 114, "minecraft:nether_brick_stairs", 0, MaterialType.BLOCK ), - NETHER_WART( 115, "minecraft:nether_wart", 0, MaterialType.ITEM ), - ENCHANTMENT_TABLE( 116, "minecraft:enchanting_table", 0, MaterialType.BLOCK ), - BREWING_STAND( 117, "minecraft:brewing_stand", 0, MaterialType.BLOCK ), - CAULDRON( 118, "minecraft:cauldron", 0, MaterialType.BLOCK), - END_PORTAL( 119, "minecraft:end_portal", 0 ), - END_PORTAL_FRAME( 120, "minecraft:end_portal_frame", 0, MaterialType.BLOCK ), - END_STONE( 121, "minecraft:end_stone", 0, MaterialType.BLOCK ), - DRAGON_EGG( 122, "minecraft:dragon_egg", 0, MaterialType.ITEM ), - - REDSTONE_LAMP_INACTIVE( 123, "minecraft:redstone_lamp", 0, MaterialType.BLOCK, "REDSTONE_LAMP_OFF" ), - REDSTONE_LAMP_ACTIVE( 124, "minecraft:lit_redstone_lamp", 0, MaterialType.BLOCK, "REDSTONE_LAMP", "REDSTONE_LAMP_ON" ), - - - OAK_WOOD_SLAB( 126, "minecraft:wooden_slab", 0, MaterialType.BLOCK ), - SPRUCE_WOOD_SLAB( 126, "minecraft:wooden_slab", 1, MaterialType.BLOCK ), - BIRCH_WOOD_SLAB( 126, "minecraft:wooden_slab", 2, MaterialType.BLOCK ), - JUNGLE_WOOD_SLAB( 126, "minecraft:wooden_slab", 3, MaterialType.BLOCK ), - ACACIA_WOOD_SLAB( 126, "minecraft:wooden_slab", 4, MaterialType.BLOCK ), - DARK_OAK_WOOD_SLAB( 126, "minecraft:wooden_slab", 5, MaterialType.BLOCK ), - COCOA( 127, "minecraft:cocoa", 0, MaterialType.BLOCK ), - SANDSTONE_STAIRS( 128, "minecraft:sandstone_stairs", 0, MaterialType.BLOCK ), - EMERALD_ORE( 129, "minecraft:emerald_ore", 0, MaterialType.BLOCK ), - ENDER_CHEST( 130, "minecraft:ender_chest", 0, MaterialType.BLOCK ), - TRIPWIRE_HOOK( 131, "minecraft:tripwire_hook", 0, MaterialType.BLOCK ), - TRIPWIRE( 132, "minecraft:tripwire_hook", 0, MaterialType.BLOCK ), - EMERALD_BLOCK( 133, "minecraft:emerald_block", 0, MaterialType.BLOCK ), - SPRUCE_WOOD_STAIRS( 134, "minecraft:spruce_stairs", 0, MaterialType.BLOCK ), - BIRCH_WOOD_STAIRS( 135, "minecraft:birch_stairs", 0, MaterialType.BLOCK ), - JUNGLE_WOOD_STAIRS( 136, "minecraft:jungle_stairs", 0, MaterialType.BLOCK ), - COMMAND_BLOCK( 137, "minecraft:command_block", 0 ), - BEACON( 138, "minecraft:beacon", 0, MaterialType.BLOCK ), - COBBLESTONE_WALL( 139, "minecraft:cobblestone_wall", 0, MaterialType.BLOCK ), - MOSSY_COBBLESTONE_WALL( 139, "minecraft:cobblestone_wall", 1, MaterialType.BLOCK ), - FLOWER_POT( 140, "minecraft:flower_pot", 0, MaterialType.BLOCK ), - CARROTS( 141, "minecraft:carrots", 0, MaterialType.BLOCK ), - POTATOES( 142, "minecraft:potatoes", 0, MaterialType.BLOCK ), - WOODEN_BUTTON( 143, "minecraft:wooden_button", 0, MaterialType.BLOCK, "OAK_BUTTON", "wood_button" ), - MOB_HEAD( 144, "minecraft:skull", 0, MaterialType.BLOCK ), - ANVIL( 145, "minecraft:anvil", 0, MaterialType.BLOCK ), - TRAPPED_CHEST( 146, "minecraft:trapped_chest", 0, MaterialType.BLOCK ), - WEIGHTED_PRESSURE_PLATE_LIGHT( 147, "minecraft:light_weighted_pressure_plate", 0, MaterialType.BLOCK ), - WEIGHTED_PRESSURE_PLATE_HEAVY( 148, "minecraft:heavy_weighted_pressure_plate", 0, MaterialType.BLOCK ), - - REDSTONE_COMPARATOR_INACTIVE( 149, "minecraft:unpowered_comparator", 0, MaterialType.BLOCK, "COMPARATOR" ), - REDSTONE_COMPARATOR_ACTIVE( 150, "minecraft:powered_comparator", 0, MaterialType.BLOCK, "COMPARATOR" ), - - DAYLIGHT_SENSOR( 151, "minecraft:daylight_detector", 0, MaterialType.BLOCK ), - REDSTONE_BLOCK( 152, "minecraft:redstone_block", 0, MaterialType.BLOCK ), - NETHER_QUARTZ_ORE( 153, "minecraft:quartz_ore", 0, MaterialType.BLOCK ), - HOPPER( 154, "minecraft:hopper", 0, MaterialType.BLOCK ), - QUARTZ_BLOCK( 155, "minecraft:quartz_block", 0, MaterialType.BLOCK ), - CHISELED_QUARTZ_BLOCK( 155, "minecraft:quartz_block", 1, MaterialType.BLOCK ), - - PILLAR_QUARTZ_BLOCK( 155, "minecraft:quartz_block", 2, MaterialType.BLOCK, "QUARTZ_PILLAR" ), - - QUARTZ_STAIRS( 156, "minecraft:quartz_stairs", 0, MaterialType.BLOCK ), - ACTIVATOR_RAIL( 157, "minecraft:activator_rail", 0, MaterialType.BLOCK ), - DROPPER( 158, "minecraft:dropper", 0, MaterialType.BLOCK ), - - WHITE_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 0, MaterialType.BLOCK, "WHITE_TERRACOTTA" ), - ORANGE_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 1, MaterialType.BLOCK, "ORANGE_TERRACOTTA" ), - MAGENTA_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 2, MaterialType.BLOCK, "MAGENTA_TERRACOTTA" ), - LIGHT_BLUE_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 3, MaterialType.BLOCK, "LIGHT_BLUE_TERRACOTTA" ), - YELLOW_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 4, MaterialType.BLOCK, "YELLOW_TERRACOTTA" ), - LIME_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 5, MaterialType.BLOCK, "LIME_TERRACOTTA" ), - PINK_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 6, MaterialType.BLOCK, "PINK_TERRACOTTA" ), - GRAY_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 7, MaterialType.BLOCK, "GRAY_TERRACOTTA" ), - LIGHT_GRAY_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 8, MaterialType.BLOCK, "LIGHT_GRAY_TERRACOTTA" ), - CYAN_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 9, MaterialType.BLOCK, "CYAN_TERRACOTTA" ), - PURPLE_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 10, MaterialType.BLOCK, "PURPLE_TERRACOTTA" ), - BLUE_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 11, MaterialType.BLOCK, "BLUE_TERRACOTTA" ), - BROWN_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 12, MaterialType.BLOCK, "BROWN_TERRACOTTA" ), - GREEN_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 13, MaterialType.BLOCK, "GREEN_TERRACOTTA" ), - RED_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 14, MaterialType.BLOCK, "RED_TERRACOTTA" ), - BLACK_STAINED_CLAY( 159, "minecraft:stained_hardened_clay", 15, MaterialType.BLOCK, "BLACK_TERRACOTTA" ), - - WHITE_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 0, MaterialType.BLOCK ), - ORANGE_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 1, MaterialType.BLOCK ), - MAGENTA_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 2, MaterialType.BLOCK ), - LIGHT_BLUE_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 3, MaterialType.BLOCK ), - YELLOW_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 4, MaterialType.BLOCK ), - LIME_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 5, MaterialType.BLOCK ), - PINK_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 6, MaterialType.BLOCK ), - GRAY_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 7, MaterialType.BLOCK ), - LIGHT_GRAY_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 8, MaterialType.BLOCK ), - CYAN_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 9, MaterialType.BLOCK ), - PURPLE_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 10, MaterialType.BLOCK ), - BLUE_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 11, MaterialType.BLOCK ), - BROWN_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 12, MaterialType.BLOCK ), - GREEN_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 13, MaterialType.BLOCK ), - RED_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 14, MaterialType.BLOCK ), - BLACK_STAINED_GLASS_PANE( 160, "minecraft:stained_glass_pane", 15, MaterialType.BLOCK ), - - ACACIA_LEAVES( 161, "minecraft:leaves2", 0, MaterialType.BLOCK, "ACACIA_LEAVES" ), - DARK_OAK_LEAVES( 161, "minecraft:leaves2", 1, MaterialType.BLOCK ), - ACACIA_WOOD( 162, "minecraft:log2", 0, MaterialType.BLOCK ), - DARK_OAK_WOOD( 162, "minecraft:log2", 1, MaterialType.BLOCK ), - ACACIA_WOOD_STAIRS( 163, "minecraft:acacia_stairs", 0, MaterialType.BLOCK ), - DARK_OAK_WOOD_STAIRS( 164, "minecraft:dark_oak_stairs", 0, MaterialType.BLOCK ), - SLIME_BLOCK( 165, "minecraft:slime", 0, MaterialType.BLOCK ), - BARRIER( 166, "minecraft:barrier", 0, MaterialType.BLOCK ), - IRON_TRAPDOOR( 167, "minecraft:iron_trapdoor", 0, MaterialType.BLOCK ), - PRISMARINE( 168, "minecraft:prismarine", 0, MaterialType.BLOCK ), - PRISMARINE_BRICKS( 168, "minecraft:prismarine", 1, MaterialType.BLOCK ), - DARK_PRISMARINE( 168, "minecraft:prismarine", 2, MaterialType.BLOCK ), - SEA_LANTERN( 169, "minecraft:sea_lantern", 0, MaterialType.BLOCK ), - HAY_BALE( 170, "minecraft:hay_block", 0, MaterialType.BLOCK ), - WHITE_CARPET( 171, "minecraft:carpet", 0, MaterialType.BLOCK ), - ORANGE_CARPET( 171, "minecraft:carpet", 1, MaterialType.BLOCK ), - MAGENTA_CARPET( 171, "minecraft:carpet", 2, MaterialType.BLOCK ), - LIGHT_BLUE_CARPET( 171, "minecraft:carpet", 3, MaterialType.BLOCK ), - YELLOW_CARPET( 171, "minecraft:carpet", 4, MaterialType.BLOCK ), - LIME_CARPET( 171, "minecraft:carpet", 5, MaterialType.BLOCK ), - PINK_CARPET( 171, "minecraft:carpet", 6, MaterialType.BLOCK ), - GRAY_CARPET( 171, "minecraft:carpet", 7, MaterialType.BLOCK ), - LIGHT_GRAY_CARPET( 171, "minecraft:carpet", 8, MaterialType.BLOCK ), - CYAN_CARPET( 171, "minecraft:carpet", 9, MaterialType.BLOCK ), - PURPLE_CARPET( 171, "minecraft:carpet", 10, MaterialType.BLOCK ), - BLUE_CARPET( 171, "minecraft:carpet", 11, MaterialType.BLOCK ), - BROWN_CARPET( 171, "minecraft:carpet", 12, MaterialType.BLOCK ), - GREEN_CARPET( 171, "minecraft:carpet", 13, MaterialType.BLOCK ), - RED_CARPET( 171, "minecraft:carpet", 14, MaterialType.BLOCK ), - BLACK_CARPET( 171, "minecraft:carpet", 15, MaterialType.BLOCK ), - HARDENED_CLAY( 172, "minecraft:hardened_clay", 0, MaterialType.BLOCK, "TERRACOTTA" ), - - COAL_BLOCK( 173, "minecraft:coal_block", 0, MaterialType.BLOCK, "BLOCK_OF_COAL" ), - BLOCK_OF_COAL( 173, "minecraft:coal_block", 0, MaterialType.BLOCK ), // obsolete... - - PACKED_ICE( 174, "minecraft:packed_ice", 0, MaterialType.BLOCK ), - SUNFLOWER( 175, "minecraft:double_plant", 0, MaterialType.BLOCK ), - LILAC( 175, "minecraft:double_plant", 1, MaterialType.BLOCK ), - DOUBLE_TALLGRASS( 175, "minecraft:double_plant", 2, MaterialType.BLOCK ), - LARGE_FERN( 175, "minecraft:double_plant", 3, MaterialType.BLOCK ), - ROSE_BUSH( 175, "minecraft:double_plant", 4, MaterialType.BLOCK ), - PEONY( 175, "minecraft:double_plant", 5, MaterialType.BLOCK ), - FREE_STANDING_BANNER( 176, "minecraft:standing_banner", 0 ), - WALL_MOUNTED_BANNER( 177, "minecraft:wall_banner", 0 ), - INVERTED_DAYLIGHT_SENSOR( 178, "minecraft:daylight_detector_inverted", 0, MaterialType.BLOCK ), - RED_SANDSTONE( 179, "minecraft:red_sandstone", 0, MaterialType.BLOCK ), - CHISELED_RED_SANDSTONE( 179, "minecraft:red_sandstone", 1, MaterialType.BLOCK ), - SMOOTH_RED_SANDSTONE( 179, "minecraft:red_sandstone", 2, MaterialType.BLOCK ), - RED_SANDSTONE_STAIRS( 180, "minecraft:red_sandstone_stairs", 0, MaterialType.BLOCK ), - - RED_SANDSTONE_SLAB( 182, "minecraft:stone_slab2", 0, MaterialType.BLOCK ), - - SPRUCE_FENCE_GATE( 183, "minecraft:spruce_fence_gate", 0, MaterialType.BLOCK ), - BIRCH_FENCE_GATE( 184, "minecraft:birch_fence_gate", 0, MaterialType.BLOCK ), - JUNGLE_FENCE_GATE( 185, "minecraft:jungle_fence_gate", 0, MaterialType.BLOCK ), - DARK_OAK_FENCE_GATE( 186, "minecraft:dark_oak_fence_gate", 0, MaterialType.BLOCK ), - ACACIA_FENCE_GATE( 187, "minecraft:acacia_fence_gate", 0, MaterialType.BLOCK ), - SPRUCE_FENCE( 188, "minecraft:spruce_fence", 0, MaterialType.BLOCK ), - BIRCH_FENCE( 189, "minecraft:birch_fence", 0, MaterialType.BLOCK ), - JUNGLE_FENCE( 190, "minecraft:jungle_fence", 0, MaterialType.BLOCK ), - DARK_OAK_FENCE( 191, "minecraft:dark_oak_fence", 0, MaterialType.BLOCK ), - ACACIA_FENCE( 192, "minecraft:acacia_fence", 0, MaterialType.BLOCK ), - SPRUCE_DOOR_BLOCK( 193, "minecraft:spruce_door", 0, MaterialType.BLOCK ), - BIRCH_DOOR_BLOCK( 194, "minecraft:birch_door", 0, MaterialType.BLOCK ), - JUNGLE_DOOR_BLOCK( 195, "minecraft:jungle_door", 0, MaterialType.BLOCK ), - ACACIA_DOOR_BLOCK( 196, "minecraft:acacia_door", 0, MaterialType.BLOCK ), - DARK_OAK_DOOR_BLOCK( 197, "minecraft:dark_oak_door", 0, MaterialType.BLOCK ), - END_ROD( 198, "minecraft:end_rod", 0, MaterialType.BLOCK ), - CHORUS_PLANT( 199, "minecraft:chorus_plant", 0, MaterialType.BLOCK ), - CHORUS_FLOWER( 200, "minecraft:chorus_flower", 0, MaterialType.BLOCK ), - PURPUR_BLOCK( 201, "minecraft:purpur_block", 0, MaterialType.BLOCK ), - PURPUR_PILLAR( 202, "minecraft:purpur_pillar", 0, MaterialType.BLOCK ), - PURPUR_STAIRS( 203, "minecraft:purpur_stairs", 0, MaterialType.BLOCK ), - - PURPUR_SLAB( 205, "minecraft:purpur_slab", 0, MaterialType.BLOCK ), - END_STONE_BRICKS( 206, "minecraft:end_bricks", 0, MaterialType.BLOCK ), - BEETROOT_BLOCK( 207, "minecraft:beetroots", 0, MaterialType.BLOCK ), - GRASS_PATH( 208, "minecraft:grass_path", 0, MaterialType.BLOCK ), - END_GATEWAY( 209, "minecraft:end_gateway", 0, MaterialType.BLOCK ), - REPEATING_COMMAND_BLOCK( 210, "minecraft:repeating_command_block", 0 ), - CHAIN_COMMAND_BLOCK( 211, "minecraft:chain_command_block", 0 ), - FROSTED_ICE( 212, "minecraft:frosted_ice", 0, MaterialType.BLOCK ), - STRUCTURE_BLOCK( 255, "minecraft:structure_block", 0, MaterialType.BLOCK ), - IRON_SHOVEL( 256, "minecraft:iron_shovel", 0 ), - IRON_PICKAXE( 257, "minecraft:iron_pickaxe", 0 ), - IRON_AXE( 258, "minecraft:iron_axe", 0 ), - FLINT_AND_STEEL( 259, "minecraft:flint_and_steel", 0 ), - APPLE( 260, "minecraft:apple", 0 ), - BOW( 261, "minecraft:bow", 0 ), - ARROW( 262, "minecraft:arrow", 0 ), - COAL( 263, "minecraft:coal", 0 ), - CHARCOAL( 263, "minecraft:coal", 1 ), - DIAMOND( 264, "minecraft:diamond", 0 ), - IRON_INGOT( 265, "minecraft:iron_ingot", 0 ), - GOLD_INGOT( 266, "minecraft:gold_ingot", 0 ), - IRON_SWORD( 267, "minecraft:iron_sword", 0 ), - WOODEN_SWORD( 268, "minecraft:wooden_sword", 0 ), - WOODEN_SHOVEL( 269, "minecraft:wooden_shovel", 0 ), - WOODEN_PICKAXE( 270, "minecraft:wooden_pickaxe", 0 ), - WOODEN_AXE( 271, "minecraft:wooden_axe", 0 ), - STONE_SWORD( 272, "minecraft:stone_sword", 0 ), - STONE_SHOVEL( 273, "minecraft:stone_shovel", 0 ), - STONE_PICKAXE( 274, "minecraft:stone_pickaxe", 0 ), - STONE_AXE( 275, "minecraft:stone_axe", 0 ), - DIAMOND_SWORD( 276, "minecraft:diamond_sword", 0 ), - DIAMOND_SHOVEL( 277, "minecraft:diamond_shovel", 0 ), - DIAMOND_PICKAXE( 278, "minecraft:diamond_pickaxe", 0 ), - DIAMOND_AXE( 279, "minecraft:diamond_axe", 0 ), - STICK( 280, "minecraft:stick", 0 ), - BOWL( 281, "minecraft:bowl", 0 ), - MUSHROOM_STEW( 282, "minecraft:mushroom_stew", 0 ), - GOLDEN_SWORD( 283, "minecraft:golden_sword", 0 ), - GOLDEN_SHOVEL( 284, "minecraft:golden_shovel", 0 ), - GOLDEN_PICKAXE( 285, "minecraft:golden_pickaxe", 0 ), - GOLDEN_AXE( 286, "minecraft:golden_axe", 0 ), - STRING( 287, "minecraft:string", 0 ), - FEATHER( 288, "minecraft:feather", 0 ), - GUNPOWDER( 289, "minecraft:gunpowder", 0 ), - WOODEN_HOE( 290, "minecraft:wooden_hoe", 0 ), - STONE_HOE( 291, "minecraft:stone_hoe", 0 ), - IRON_HOE( 292, "minecraft:iron_hoe", 0 ), - DIAMOND_HOE( 293, "minecraft:diamond_hoe", 0 ), - GOLDEN_HOE( 294, "minecraft:golden_hoe", 0 ), - WHEAT_SEEDS( 295, "minecraft:wheat_seeds", 0 ), - WHEAT( 296, "minecraft:wheat", 0 ), - BREAD( 297, "minecraft:bread", 0 ), - LEATHER_HELMET( 298, "minecraft:leather_helmet", 0 ), - LEATHER_TUNIC( 299, "minecraft:leather_chestplate", 0 ), - LEATHER_PANTS( 300, "minecraft:leather_leggings", 0 ), - LEATHER_BOOTS( 301, "minecraft:leather_boots", 0 ), - CHAINMAIL_HELMET( 302, "minecraft:chainmail_helmet", 0 ), - CHAINMAIL_CHESTPLATE( 303, "minecraft:chainmail_chestplate", 0 ), - CHAINMAIL_LEGGINGS( 304, "minecraft:chainmail_leggings", 0 ), - CHAINMAIL_BOOTS( 305, "minecraft:chainmail_boots", 0 ), - IRON_HELMET( 306, "minecraft:iron_helmet", 0 ), - IRON_CHESTPLATE( 307, "minecraft:iron_chestplate", 0 ), - IRON_LEGGINGS( 308, "minecraft:iron_leggings", 0 ), - IRON_BOOTS( 309, "minecraft:iron_boots", 0 ), - DIAMOND_HELMET( 310, "minecraft:diamond_helmet", 0 ), - DIAMOND_CHESTPLATE( 311, "minecraft:diamond_chestplate", 0 ), - DIAMOND_LEGGINGS( 312, "minecraft:diamond_leggings", 0 ), - DIAMOND_BOOTS( 313, "minecraft:diamond_boots", 0 ), - GOLDEN_HELMET( 314, "minecraft:golden_helmet", 0 ), - GOLDEN_CHESTPLATE( 315, "minecraft:golden_chestplate", 0 ), - GOLDEN_LEGGINGS( 316, "minecraft:golden_leggings", 0 ), - GOLDEN_BOOTS( 317, "minecraft:golden_boots", 0 ), - FLINT( 318, "minecraft:flint", 0 ), - RAW_PORKCHOP( 319, "minecraft:porkchop", 0 ), - COOKED_PORKCHOP( 320, "minecraft:cooked_porkchop", 0 ), - PAINTING( 321, "minecraft:painting", 0 ), - GOLDEN_APPLE( 322, "minecraft:golden_apple", 0 ), - ENCHANTED_GOLDEN_APPLE( 322, "minecraft:golden_apple", 1 ), - SIGN( 323, "minecraft:sign", 0, MaterialType.BLOCK ), - OAK_DOOR( 324, "minecraft:wooden_door", 0, MaterialType.BLOCK ), - BUCKET( 325, "minecraft:bucket", 0 ), - WATER_BUCKET( 326, "minecraft:water_bucket", 0 ), - LAVA_BUCKET( 327, "minecraft:lava_bucket", 0 ), - MINECART( 328, "minecraft:minecart", 0 ), - SADDLE( 329, "minecraft:saddle", 0 ), - IRON_DOOR( 330, "minecraft:iron_door", 0, MaterialType.BLOCK ), - REDSTONE( 331, "minecraft:redstone", 0, MaterialType.ITEM ), - SNOWBALL( 332, "minecraft:snowball", 0 ), - OAK_BOAT( 333, "minecraft:boat", 0 ), - LEATHER( 334, "minecraft:leather", 0 ), - MILK_BUCKET( 335, "minecraft:milk_bucket", 0 ), - BRICK( 336, "minecraft:brick", 0, MaterialType.BLOCK ), - CLAY_BALL( 337, "minecraft:clay_ball", 0 ), - SUGAR_CANES_ITEM( 338, "minecraft:reeds", 0, MaterialType.BLOCK, "SUGAR_CANE" ), - PAPER( 339, "minecraft:paper", 0 ), - BOOK( 340, "minecraft:book", 0 ), - SLIMEBALL( 341, "minecraft:slime_ball", 0 ), - MINECART_WITH_CHEST( 342, "minecraft:chest_minecart", 0 ), - MINECART_WITH_FURNACE( 343, "minecraft:furnace_minecart", 0 ), - EGG( 344, "minecraft:egg", 0 ), - COMPASS( 345, "minecraft:compass", 0 ), - FISHING_ROD( 346, "minecraft:fishing_rod", 0 ), - CLOCK( 347, "minecraft:clock", 0 ), - GLOWSTONE_DUST( 348, "minecraft:glowstone_dust", 0 ), - RAW_FISH( 349, "minecraft:fish", 0 ), - RAW_SALMON( 349, "minecraft:fish", 1 ), - CLOWNFISH( 349, "minecraft:fish", 2 ), - PUFFERFISH( 349, "minecraft:fish", 3 ), - COOKED_FISH( 350, "minecraft:cooked_fish", 0 ), - COOKED_SALMON( 350, "minecraft:cooked_fish", 1 ), - - INK_SACK( 351, "minecraft:dye", 0 ), - ROSE_RED( 351, "minecraft:dye", 1 ), - CACTUS_GREEN( 351, "minecraft:dye", 2 ), - COCO_BEANS( 351, "minecraft:dye", 3 ), - - // NOTE: May actually be minecraft:ink_sack which is what XMaterial uses? - LAPIS_LAZULI( 351, "minecraft:dye", 4 ), - - PURPLE_DYE( 351, "minecraft:dye", 5 ), - CYAN_DYE( 351, "minecraft:dye", 6 ), - LIGHT_GRAY_DYE( 351, "minecraft:dye", 7 ), - GRAY_DYE( 351, "minecraft:dye", 8 ), - PINK_DYE( 351, "minecraft:dye", 9 ), - LIME_DYE( 351, "minecraft:dye", 10 ), - DANDELION_YELLOW( 351, "minecraft:dye", 11 ), - LIGHT_BLUE_DYE( 351, "minecraft:dye", 12 ), - MAGENTA_DYE( 351, "minecraft:dye", 13 ), - ORANGE_DYE( 351, "minecraft:dye", 14 ), - BONE_MEAL( 351, "minecraft:dye", 15 ), - - - BONE( 352, "minecraft:bone", 0 ), - SUGAR( 353, "minecraft:sugar", 0 ), - CAKE( 354, "minecraft:cake", 0 ), - BED_ITEM( 355, "minecraft:bed", 0 ), - REDSTONE_REPEATER( 356, "minecraft:repeater", 0, MaterialType.BLOCK ), - COOKIE( 357, "minecraft:cookie", 0 ), - MAP( 358, "minecraft:filled_map", 0 ), - SHEARS( 359, "minecraft:shears", 0 ), - MELON( 360, "minecraft:melon", 0, MaterialType.BLOCK ), - PUMPKIN_SEEDS( 361, "minecraft:pumpkin_seeds", 0 ), - MELON_SEEDS( 362, "minecraft:melon_seeds", 0 ), - RAW_BEEF( 363, "minecraft:beef", 0 ), - STEAK( 364, "minecraft:cooked_beef", 0 ), - RAW_CHICKEN( 365, "minecraft:chicken", 0 ), - COOKED_CHICKEN( 366, "minecraft:cooked_chicken", 0 ), - ROTTEN_FLESH( 367, "minecraft:rotten_flesh", 0 ), - ENDER_PEARL( 368, "minecraft:ender_pearl", 0 ), - BLAZE_ROD( 369, "minecraft:blaze_rod", 0 ), - GHAST_TEAR( 370, "minecraft:ghast_tear", 0 ), - GOLD_NUGGET( 371, "minecraft:gold_nugget", 0 ), - NETHER_WART_ITEM( 372, "minecraft:nether_wart", 0 ), - POTION( 373, "minecraft:potion", 0 ), - GLASS_BOTTLE( 374, "minecraft:glass_bottle", 0 ), - SPIDER_EYE( 375, "minecraft:spider_eye", 0 ), - FERMENTED_SPIDER_EYE( 376, "minecraft:fermented_spider_eye", 0 ), - BLAZE_POWDER( 377, "minecraft:blaze_powder", 0 ), - MAGMA_CREAM( 378, "minecraft:magma_cream", 0 ), - BREWING_STAND_ITEM( 379, "minecraft:brewing_stand", 0, MaterialType.BLOCK ), - CAULDRON_ITEM( 380, "minecraft:cauldron", 0, MaterialType.BLOCK ), - EYE_OF_ENDER( 381, "minecraft:ender_eye", 0 ), - GLISTERING_MELON( 382, "minecraft:speckled_melon", 0 ), - SPAWN_CREEPER( 383, "minecraft:spawn_egg", 50 ), - SPAWN_SKELETON( 383, "minecraft:spawn_egg", 51 ), - SPAWN_SPIDER( 383, "minecraft:spawn_egg", 52 ), - SPAWN_ZOMBIE( 383, "minecraft:spawn_egg", 54 ), - SPAWN_SLIME( 383, "minecraft:spawn_egg", 55 ), - SPAWN_GHAST( 383, "minecraft:spawn_egg", 56 ), - SPAWN_PIGMAN( 383, "minecraft:spawn_egg", 57 ), - SPAWN_ENDERMAN( 383, "minecraft:spawn_egg", 58 ), - SPAWN_CAVE_SPIDER( 383, "minecraft:spawn_egg", 59 ), - SPAWN_SILVERFISH( 383, "minecraft:spawn_egg", 60 ), - SPAWN_BLAZE( 383, "minecraft:spawn_egg", 61 ), - SPAWN_MAGMA_CUBE( 383, "minecraft:spawn_egg", 62 ), - SPAWN_BAT( 383, "minecraft:spawn_egg", 65 ), - SPAWN_WITCH( 383, "minecraft:spawn_egg", 66 ), - SPAWN_ENDERMITE( 383, "minecraft:spawn_egg", 67 ), - SPAWN_GUARDIAN( 383, "minecraft:spawn_egg", 68 ), - SPAWN_SHULKER( 383, "minecraft:spawn_egg", 69 ), - SPAWN_PIG( 383, "minecraft:spawn_egg", 90 ), - SPAWN_SHEEP( 383, "minecraft:spawn_egg", 91 ), - SPAWN_COW( 383, "minecraft:spawn_egg", 92 ), - SPAWN_CHICKEN( 383, "minecraft:spawn_egg", 93 ), - SPAWN_SQUID( 383, "minecraft:spawn_egg", 94 ), - SPAWN_WOLF( 383, "minecraft:spawn_egg", 95 ), - SPAWN_MOOSHROOM( 383, "minecraft:spawn_egg", 96 ), - SPAWN_OCELOT( 383, "minecraft:spawn_egg", 98 ), - SPAWN_HORSE( 383, "minecraft:spawn_egg", 100 ), - SPAWN_RABBIT( 383, "minecraft:spawn_egg", 101 ), - SPAWN_VILLAGER( 383, "minecraft:spawn_egg", 120 ), - BOTTLE_O_ENCHANTING( 384, "minecraft:experience_bottle", 0 ), - FIRE_CHARGE( 385, "minecraft:fire_charge", 0 ), - BOOK_AND_QUILL( 386, "minecraft:writable_book", 0 ), - WRITTEN_BOOK( 387, "minecraft:written_book", 0 ), - EMERALD( 388, "minecraft:emerald", 0 ), - ITEM_FRAME( 389, "minecraft:item_frame", 0, MaterialType.BLOCK ), - FLOWER_POT_ITEM( 390, "minecraft:flower_pot", 0, MaterialType.BLOCK ), - CARROT( 391, "minecraft:carrot", 0, MaterialType.BLOCK ), - POTATO( 392, "minecraft:potato", 0, MaterialType.BLOCK ), - BAKED_POTATO( 393, "minecraft:baked_potato", 0 ), - POISONOUS_POTATO( 394, "minecraft:poisonous_potato", 0 ), - EMPTY_MAP( 395, "minecraft:map", 0 ), - GOLDEN_CARROT( 396, "minecraft:golden_carrot", 0 ), - MOB_HEAD_SKELETON( 397, "minecraft:skull", 0 ), - MOB_HEAD_WITHER_SKELETON( 397, "minecraft:skull", 1 ), - MOB_HEAD_ZOMBIE( 397, "minecraft:skull", 2 ), - MOB_HEAD_HUMAN( 397, "minecraft:skull", 3 ), - MOB_HEAD_CREEPER( 397, "minecraft:skull", 4 ), - MOB_HEAD_DRAGON( 397, "minecraft:skull", 5 ), - CARROT_ON_A_STICK( 398, "minecraft:carrot_on_a_stick", 0 ), - NETHER_STAR( 399, "minecraft:nether_star", 0 ), - PUMPKIN_PIE( 400, "minecraft:pumpkin_pie", 0 ), - FIREWORK_ROCKET( 401, "minecraft:fireworks", 0 ), - FIREWORK_STAR( 402, "minecraft:firework_charge", 0 ), - ENCHANTED_BOOK( 403, "minecraft:enchanted_book", 0 ), - REDSTONE_COMPARATOR( 404, "minecraft:comparator", 0, MaterialType.BLOCK ), - NETHER_BRICK_ITEM( 405, "minecraft:netherbrick", 0, MaterialType.ITEM ), - NETHER_QUARTZ( 406, "minecraft:quartz", 0 ), - MINECART_WITH_TNT( 407, "minecraft:tnt_minecart", 0 ), - MINECART_WITH_HOPPER( 408, "minecraft:hopper_minecart", 0 ), - PRISMARINE_SHARD( 409, "minecraft:prismarine_shard", 0 ), - PRISMARINE_CRYSTALS( 410, "minecraft:prismarine_crystals", 0 ), - RAW_RABBIT( 411, "minecraft:rabbit", 0 ), - COOKED_RABBIT( 412, "minecraft:cooked_rabbit", 0 ), - RABBIT_STEW( 413, "minecraft:rabbit_stew", 0 ), - RABBITS_FOOT( 414, "minecraft:rabbit_foot", 0 ), - RABBIT_HIDE( 415, "minecraft:rabbit_hide", 0 ), - ARMOR_STAND( 416, "minecraft:armor_stand", 0, MaterialType.BLOCK ), - IRON_HORSE_ARMOR( 417, "minecraft:iron_horse_armor", 0 ), - GOLDEN_HORSE_ARMOR( 418, "minecraft:golden_horse_armor", 0 ), - DIAMOND_HORSE_ARMOR( 419, "minecraft:diamond_horse_armor", 0 ), - LEAD( 420, "minecraft:lead", 0 ), - NAME_TAG( 421, "minecraft:name_tag", 0 ), - MINECART_WITH_COMMAND_BLOCK( 422, "minecraft:command_block_minecart", 0 ), - RAW_MUTTON( 423, "minecraft:mutton", 0 ), - COOKED_MUTTON( 424, "minecraft:cooked_mutton", 0 ), - BANNER( 425, "minecraft:banner", 0, MaterialType.BLOCK ), - SPRUCE_DOOR( 427, "minecraft:spruce_door", 0, MaterialType.BLOCK ), - BIRCH_DOOR( 428, "minecraft:birch_door", 0, MaterialType.BLOCK ), - JUNGLE_DOOR( 429, "minecraft:jungle_door", 0, MaterialType.BLOCK ), - ACACIA_DOOR( 430, "minecraft:acacia_door", 0, MaterialType.BLOCK ), - DARK_OAK_DOOR( 431, "minecraft:dark_oak_door", 0, MaterialType.BLOCK ), - CHORUS_FRUIT( 432, "minecraft:chorus_fruit", 0, MaterialType.BLOCK ), - POPPED_CHORUS_FRUIT( 433, "minecraft:popped_chorus_fruit", 0 ), - BEETROOT( 434, "minecraft:beetroot", 0, MaterialType.BLOCK ), - BEETROOT_SEEDS( 435, "minecraft:beetroot_seeds", 0 ), - BEETROOT_SOUP( 436, "minecraft:beetroot_soup", 0 ), - DRAGONS_BREATH( 437, "minecraft:dragon_breath", 0, MaterialType.BLOCK ), - SPLASH_POTION( 438, "minecraft:splash_potion", 0 ), - SPECTRAL_ARROW( 439, "minecraft:spectral_arrow", 0 ), - TIPPED_ARROW( 440, "minecraft:tipped_arrow", 0 ), - LINGERING_POTION( 441, "minecraft:lingering_potion", 0 ), - SHIELD( 442, "minecraft:shield", 0 ), - ELYTRA( 443, "minecraft:elytra", 0 ), - SPRUCE_BOAT( 444, "minecraft:spruce_boat", 0 ), - BIRCH_BOAT( 445, "minecraft:birch_boat", 0 ), - JUNGLE_BOAT( 446, "minecraft:jungle_boat", 0 ), - ACACIA_BOAT( 447, "minecraft:acacia_boat", 0 ), - DARK_OAK_BOAT( 448, "minecraft:dark_oak_boat", 0 ), - DISC_13( 2256, "minecraft:record_13", 0 ), - CAT_DISC( 2257, "minecraft:record_cat", 0 ), - BLOCKS_DISC( 2258, "minecraft:record_blocks", 0 ), - CHIRP_DISC( 2259, "minecraft:record_chirp", 0 ), - FAR_DISC( 2260, "minecraft:record_far", 0 ), - MALL_DISC( 2261, "minecraft:record_mall", 0 ), - MELLOHI_DISC( 2262, "minecraft:record_mellohi", 0 ), - STAL_DISC( 2263, "minecraft:record_stal", 0 ), - STRAD_DISC( 2264, "minecraft:record_strad", 0 ), - WARD_DISC( 2265, "minecraft:record_ward", 0 ), - DISC_11( 2266, "minecraft:record_11", 0 ), - WAIT_DISC( 2267, "minecraft:record_wait", 0 ), - - - // Minecraft v1.10.x blocks: - - STRUCTURE_VOID( "minecraft:structure_void", MaterialType.BLOCK, MaterialVersion.v1_10 ), - MAGMA_BLOCK( "minecraft:magma_block", MaterialType.BLOCK, MaterialVersion.v1_10 ), - BONE_BLOCK( "minecraft:bone_block", MaterialType.BLOCK, MaterialVersion.v1_10 ), - - - // Minecraft v1.11.x blocks: - - SHULKER_BOX( "minecraft:shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - - WHITE_SHULKER_BOX( "minecraft:white_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - ORANGE_SHULKER_BOX( "minecraft:orange_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - MAGENTA_SHULKER_BOX( "minecraft:magenta_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - LIGHT_BLUE_SHULKER_BOX( "minecraft:light_blue_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - YELLOW_SHULKER_BOX( "minecraft:yellow_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - - LIME_SHULKER_BOX( "minecraft:lime_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - PINK_SHULKER_BOX( "minecraft:pink_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - GRAY_SHULKER_BOX( "minecraft:gray_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - LIGHT_GRAY_SHULKER_BOX( "minecraft:light_gray_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - CYAN_SHULKER_BOX( "minecraft:cyan_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - - PURPLE_SHULKER_BOX( "minecraft:purple_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - BLUE_SHULKER_BOX( "minecraft:blue_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - BROWN_SHULKER_BOX( "minecraft:brown_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - GREEN_SHULKER_BOX( "minecraft:green_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - RED_SHULKER_BOX( "minecraft:red_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - BLACK_SHULKER_BOX( "minecraft:black_shulker_box", MaterialType.BLOCK, MaterialVersion.v1_11 ), - - - - // Minecraft v1.12.x blocks: - - WHITE_GLAZED_TERRACOTTA( "minecraft:white_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - ORANGE_GLAZED_TERRACOTTA( "minecraft:orange_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - MAGENTA_GLAZED_TERRACOTTA( "minecraft:magenta_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - LIGHT_BLUE_GLAZED_TERRACOTTA( "minecraft:light_blue_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - YELLOW_GLAZED_TERRACOTTA( "minecraft:yellow_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - - LIME_GLAZED_TERRACOTTA( "minecraft:lime_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - PINK_GLAZED_TERRACOTTA( "minecraft:pink_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - GRAY_GLAZED_TERRACOTTA( "minecraft:gray_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - LIGHT_GRAY_GLAZED_TERRACOTTA( "minecraft:light_gray_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - CYAN_GLAZED_TERRACOTTA( "minecraft:cyan_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), + // NOTE: This obsolete source has been purged. See the history in git. - PURPLE_GLAZED_TERRACOTTA( "minecraft:purple_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - BLUE_GLAZED_TERRACOTTA( "minecraft:blue_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - BROWN_GLAZED_TERRACOTTA( "minecraft:brown_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - GREEN_GLAZED_TERRACOTTA( "minecraft:green_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - RED_GLAZED_TERRACOTTA( "minecraft:red_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - BLACK_GLAZED_TERRACOTTA( "minecraft:black_glazed_terracotta", MaterialType.BLOCK, MaterialVersion.v1_12 ), - - - WHITE_CONCRETE( "minecraft:white_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - ORANGE_CONCRETE( "minecraft:orange_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - MAGENTA_CONCRETE( "minecraft:magenta_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - LIGHT_BLUE_CONCRETE( "minecraft:light_blue_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - YELLOW_CONCRETE( "minecraft:yellow_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - - LIME_CONCRETE( "minecraft:lime_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - PINK_CONCRETE( "minecraft:pink_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - GRAY_CONCRETE( "minecraft:gray_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - LIGHT_GRAY_CONCRETE( "minecraft:light_gray_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - CYAN_CONCRETE( "minecraft:cyan_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - - PURPLE_CONCRETE( "minecraft:purple_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - BLUE_CONCRETE( "minecraft:blue_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - BROWN_CONCRETE( "minecraft:brown_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - GREEN_CONCRETE( "minecraft:green_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - RED_CONCRETE( "minecraft:red_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - BLACK_CONCRETE( "minecraft:black_concrete", MaterialType.BLOCK, MaterialVersion.v1_12 ), - - - WHITE_CONCRETE_POWDER( "minecraft:white_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - ORANGE_CONCRETE_POWDER( "minecraft:orange_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - MAGENTA_CONCRETE_POWDER( "minecraft:magenta_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - LIGHT_BLUE_CONCRETE_POWDER( "minecraft:light_blue_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - YELLOW_CONCRETE_POWDER( "minecraft:yellow_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - - LIME_CONCRETE_POWDER( "minecraft:lime_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - PINK_CONCRETE_POWDER( "minecraft:pink_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - GRAY_CONCRETE_POWDER( "minecraft:gray_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - LIGHT_GRAY_CONCRETE_POWDER( "minecraft:light_gray_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - CYAN_CONCRETE_POWDER( "minecraft:cyan_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - - PURPLE_CONCRETE_POWDER( "minecraft:purple_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - BLUE_CONCRETE_POWDER( "minecraft:blue_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - BROWN_CONCRETE_POWDER( "minecraft:brown_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - GREEN_CONCRETE_POWDER( "minecraft:green_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - RED_CONCRETE_POWDER( "minecraft:red_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - BLACK_CONCRETE_POWDER( "minecraft:black_concrete_powder", MaterialType.BLOCK, MaterialVersion.v1_12 ), - - - - - // Minecraft v1.13.x blocks: - - CAVE_AIR( "minecraft:cave_air", MaterialType.BLOCK, MaterialVersion.v1_13 ), - VOID_AIR( "minecraft:void_air", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - BLUE_ICE( "minecraft:blue_ice", MaterialType.BLOCK, MaterialVersion.v1_13 ), - BUBBLE_COLUMN( "minecraft:bubble_column", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - TUBE_CORAL( "minecraft:tube_coral", MaterialType.BLOCK, MaterialVersion.v1_13 ), - BRAIN_CORAL( "minecraft:brain_coral", MaterialType.BLOCK, MaterialVersion.v1_13 ), - BUBBLE_CORAL( "minecraft:bubble_coral", MaterialType.BLOCK, MaterialVersion.v1_13 ), - FIRE_CORAL( "minecraft:fire_coral", MaterialType.BLOCK, MaterialVersion.v1_13 ), - HORN_CORAL( "minecraft:horn_coral", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - DEAD_TUBE_CORAL( "minecraft:dead_tube_coral", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_BRAIN_CORAL( "minecraft:dead_brain_coral", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_BUBBLE_CORAL( "minecraft:dead_bubble_coral", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_FIRE_CORAL( "minecraft:dead_fire_coral", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_HORN_CORAL( "minecraft:dead_horn_coral", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - - TUBE_CORAL_BLOCK( "minecraft:tube_coral_block", MaterialType.BLOCK, MaterialVersion.v1_13 ), - BRAIN_CORAL_BLOCK( "minecraft:brain_coral_block", MaterialType.BLOCK, MaterialVersion.v1_13 ), - BUBBLE_CORAL_BLOCK( "minecraft:bubble_coral_block", MaterialType.BLOCK, MaterialVersion.v1_13 ), - FIRE_CORAL_BLOCK( "minecraft:fire_coral_block", MaterialType.BLOCK, MaterialVersion.v1_13 ), - HORN_CORAL_BLOCK( "minecraft:horn_coral_block", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - DEAD_TUBE_CORAL_BLOCK( "minecraft:dead_tube_coral_block", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_BRAIN_CORAL_BLOCK( "minecraft:dead_brain_coral_block", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_BUBBLE_CORAL_BLOCK( "minecraft:dead_bubble_coral_block", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_FIRE_CORAL_BLOCK( "minecraft:dead_fire_coral_block", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_HORN_CORAL_BLOCK( "minecraft:dead_horn_coral_block", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - - TUBE_CORAL_FAN( "minecraft:tube_coral_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - BRAIN_CORAL_FAN( "minecraft:brain_coral_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - BUBBLE_CORAL_FAN( "minecraft:bubble_coral_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - FIRE_CORAL_FAN( "minecraft:fire_coral_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - HORN_CORAL_FAN( "minecraft:horn_coral_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - DEAD_TUBE_CORAL_FAN( "minecraft:dead_tube_coral_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_BRAIN_CORAL_FAN( "minecraft:dead_brain_coral_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_BUBBLE_CORAL_FAN( "minecraft:dead_bubble_coral_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_FIRE_CORAL_FAN( "minecraft:dead_fire_coral_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_HORN_CORAL_FAN( "minecraft:dead_horn_coral_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - - TUBE_CORAL_WALL_FAN( "minecraft:tube_coral_wall_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - BRAIN_CORAL_WALL_FAN( "minecraft:brain_coral_wall_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - BUBBLE_CORAL_WALL_FAN( "minecraft:bubble_coral_wall_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - FIRE_CORAL_WALL_FAN( "minecraft:fire_coral_wall_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - HORN_CORAL_WALL_FAN( "minecraft:horn_coral_wall_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - DEAD_TUBE_CORAL_WALL_FAN( "minecraft:dead_tube_coral_wall_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_BRAIN_CORAL_WALL_FAN( "minecraft:dead_brain_coral_wall_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_BUBBLE_CORAL_WALL_FAN( "minecraft:dead_bubble_coral_wall_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_FIRE_CORAL_WALL_FAN( "minecraft:dead_fire_coral_wall_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DEAD_HORN_CORAL_WALL_FAN( "minecraft:dead_horn_coral_wall_fan", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - - - - ACACIA_LOG( "minecraft:acacia_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - BIRCH_LOG( "minecraft:birch_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - DARK_OAK_LOG( "minecraft:dark_oak_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - JUNGLE_LOG( "minecraft:jungle_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - OAK_LOG( "minecraft:oak_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - SPRUCE_LOG( "minecraft:spruce_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - - STRIPPED_ACACIA_LOG( "minecraft:stripped_acacia_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - STRIPPED_BIRCH_LOG( "minecraft:stripped_birch_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - STRIPPED_DARK_OAK_LOG( "minecraft:stripped_dark_oak_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - STRIPPED_JUNGLE_LOG( "minecraft:stripped_jungle_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - STRIPPED_OAK_LOG( "minecraft:stripped_oak_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - STRIPPED_SPRUCE_LOG( "minecraft:stripped_spruce_log", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - STRIPPED_ACACIA_WOOD( "minecraft:stripped_acacia_wood", MaterialType.BLOCK, MaterialVersion.v1_13 ), - STRIPPED_BIRCH_WOOD( "minecraft:stripped_birch_wood", MaterialType.BLOCK, MaterialVersion.v1_13 ), - STRIPPED_DARK_OAK_WOOD( "minecraft:stripped_dark_oak_wood", MaterialType.BLOCK, MaterialVersion.v1_13 ), - STRIPPED_JUNGLE_WOOD( "minecraft:stripped_jungle_wood", MaterialType.BLOCK, MaterialVersion.v1_13 ), - STRIPPED_OAK_WOOD( "minecraft:stripped_oak_wood", MaterialType.BLOCK, MaterialVersion.v1_13 ), - STRIPPED_SPRUCE_WOOD( "minecraft:stripped_spruce_wood", MaterialType.BLOCK, MaterialVersion.v1_13 ), - - - - // Minecraft v1.14.x blocks: - BAMBOO( "minecraft:bamboo", MaterialType.BLOCK, MaterialVersion.v1_14 ), - BAMBOO_SAPLING( "minecraft:bamboo_sapling", MaterialType.BLOCK, MaterialVersion.v1_14 ), - - BARREL( "minecraft:barrel", MaterialType.BLOCK, MaterialVersion.v1_14 ), - BELL( "minecraft:bell", MaterialType.BLOCK, MaterialVersion.v1_14 ), - BLAST_FURNACE( "minecraft:blast_furnace", MaterialType.BLOCK, MaterialVersion.v1_14 ), - - CAMPFIRE( "minecraft:campfire", MaterialType.BLOCK, MaterialVersion.v1_14 ), - CARTOGRAPHY_TABLE( "minecraft:cartography_table", MaterialType.BLOCK, MaterialVersion.v1_14 ), - COMPOSTER( "minecraft:composter", MaterialType.BLOCK, MaterialVersion.v1_14 ), - FLETCHING_TABLE( "minecraft:fletching_table", MaterialType.BLOCK, MaterialVersion.v1_14 ), - //FLOWERS( "minecraft:bee_nest", MaterialType.BLOCK, MaterialVersion.v1_14 ), - GRINDSTONE( "minecraft:grindstone", MaterialType.BLOCK, MaterialVersion.v1_14 ), - JIGSAW( "minecraft:jigsaw", MaterialType.BLOCK, MaterialVersion.v1_14 ), - LANTERN( "minecraft:lantern", MaterialType.BLOCK, MaterialVersion.v1_14 ), - LECTERN( "minecraft:lectern", MaterialType.BLOCK, MaterialVersion.v1_14 ), - - LOOM( "minecraft:loom", MaterialType.BLOCK, MaterialVersion.v1_14 ), - // Already exists: NOTE_BLOCK( "minecraft:note_block", MaterialType.BLOCK, MaterialVersion.v1_14 ), - SCAFFOLDING( "minecraft:scaffolding", MaterialType.BLOCK, MaterialVersion.v1_14 ), - //SIGNS( "minecraft:bee_nest", MaterialType.BLOCK, MaterialVersion.v1_14 ), - //SLABS( "minecraft:bee_nest", MaterialType.BLOCK, MaterialVersion.v1_14 ), - SMITHING_TABLE( "minecraft:smithing_table", MaterialType.BLOCK, MaterialVersion.v1_14 ), - SMOKER( "minecraft:smoker", MaterialType.BLOCK, MaterialVersion.v1_14 ), - //STAIRS( "minecraft:bee_nest", MaterialType.BLOCK, MaterialVersion.v1_14 ), - STONECUTTER( "minecraft:stonecutter", MaterialType.BLOCK, MaterialVersion.v1_14 ), - SWEET_BERRY_BUSH( "minecraft:sweet_berry_bush", MaterialType.BLOCK, MaterialVersion.v1_14 ), - //WALLS( "minecraft:bee_nest", MaterialType.BLOCK, MaterialVersion.v1_14 ), - - - - - // Minecraft v1.15.x blocks: - BEE_NEST( "minecraft:bee_nest", MaterialType.BLOCK, MaterialVersion.v1_15 ), - BEEHIVE( "minecraft:beehive", MaterialType.BLOCK, MaterialVersion.v1_15 ), - HONEY_BLOCK( "minecraft:honey_block", MaterialType.BLOCK, MaterialVersion.v1_15 ), - HONEYCOMB_BLOCK( "minecraft:honeycomb_block", MaterialType.BLOCK, MaterialVersion.v1_15 ), - - - - // Minecraft v1.16.x blocks: - ANCIENT_DEBRIS( "minecraft:ancient_debris", MaterialType.BLOCK, MaterialVersion.v1_16 ), - CRYING_OBSIDIAN( "minecraft:crying_obsidian", MaterialType.BLOCK, MaterialVersion.v1_16 ), - NETHER_GOLD_ORE( "minecraft:nether_gold_ore", MaterialType.BLOCK, MaterialVersion.v1_16 ), - - - BASALT( "minecraft:basal", MaterialType.BLOCK, MaterialVersion.v1_16 ), - POLISHED_BASALT( "minecraft:polished_basalt", MaterialType.BLOCK, MaterialVersion.v1_16 ), - NETHERITE_BLOCK( "minecraft:netherite_block", MaterialType.BLOCK, MaterialVersion.v1_16 ), - - - BLACKSTONE( "minecraft:base_stone_blackstone", MaterialType.BLOCK, MaterialVersion.v1_16 ), - POLISHED_BLACKSTONE( "minecraft:polished_blackstone", MaterialType.BLOCK, MaterialVersion.v1_16 ), - CHISELED_POLISHED_BLACKSTONE( "minecraft:chiseled_polished_blackstone", MaterialType.BLOCK, MaterialVersion.v1_16 ), - - - NETHER_BRICKS( "minecraft:nether_bricks", MaterialType.BLOCK, MaterialVersion.v1_8 ), - RED_NETHER_BRICKS( "minecraft:red_nether_bricks", MaterialType.BLOCK, MaterialVersion.v1_10, "RED_NETHER_BRICK" ), - CRACKED_NETHER_BRICKS( "minecraft:cracked_nether_bricks", MaterialType.BLOCK, MaterialVersion.v1_16 ), - CHISELED_NETHER_BRICKS( "minecraft:chiseled_nether_bricks", MaterialType.BLOCK, MaterialVersion.v1_16 ), - - - CRIMSON_PLANKS( "minecraft:crimson_planks", MaterialType.BLOCK, MaterialVersion.v1_16 ), - WARPED_PLANKS( "minecraft:warped_planks", MaterialType.BLOCK, MaterialVersion.v1_16 ), - STRIPPED_CRIMSON_HYPHAE( "minecraft:stripped_crimson_hyphae", MaterialType.BLOCK, MaterialVersion.v1_16 ), - STRIPPED_WARPED_HYPHAE( "minecraft:stripped_warped_hyphae", MaterialType.BLOCK, MaterialVersion.v1_16 ), - NETHER_WART_BLOCK( "minecraft:nether_wart_block", MaterialType.BLOCK, MaterialVersion.v1_16 ), - WARPED_WART_BLOCK( "minecraft:warped_wart_block", MaterialType.BLOCK, MaterialVersion.v1_16 ), - - - LODESTONE( "minecraft:lodestone", MaterialType.BLOCK, MaterialVersion.v1_16 ), - QUARTZ_BRICKS( "minecraft:quartz_bricks", MaterialType.BLOCK, MaterialVersion.v1_16 ), - RESPAWN_ANCHOR( "minecraft:respawn_anchor", MaterialType.BLOCK, MaterialVersion.v1_16 ), - - - SHROOMLIGHT( "minecraft:shroomlight", MaterialType.BLOCK, MaterialVersion.v1_16 ), - SOUL_CAMPFIRE( "minecraft:soul_campfire", MaterialType.BLOCK, MaterialVersion.v1_16 ), - - - SOUL_LANTERN( "minecraft:soul_lantern", MaterialType.BLOCK, MaterialVersion.v1_16 ), - SOUL_TORCH( "minecraft:soul_torch", MaterialType.BLOCK, MaterialVersion.v1_16 ), - SOUL_SOIL( "minecraft:soul_soil", MaterialType.BLOCK, MaterialVersion.v1_16 ), - TARGET( "minecraft:target", MaterialType.BLOCK, MaterialVersion.v1_16 ), - - - TWISTING_VINES( "minecraft:twisting_vines", MaterialType.BLOCK, MaterialVersion.v1_16 ), - WEEPING_VINES( "minecraft:weeping_vines", MaterialType.BLOCK, MaterialVersion.v1_16 ), - - - - - - ; - // @formatter:on - - private final int legacyId; - private final String id; - private final short data; - private final MaterialType materialType; - private final MaterialVersion materialVersion; - - private final List altNames; - - ObsoleteBlockType(int legacyId, String id, int data, MaterialType materialType) { - this.legacyId = legacyId; - this.id = (id != null ? id : "minecraft:" + this.name().toLowerCase()); - this.data = (short) data; - this.materialType = materialType; - this.materialVersion = MaterialVersion.v1_8; - - this.altNames = new ArrayList<>(); - } - - - ObsoleteBlockType(int legacyId, String id, int data, MaterialType materialType, String... altNames) { - this( legacyId, id, data, materialType ); - - for ( String altName : altNames ) { - this.altNames.add( altName ); - } - } - - - - ObsoleteBlockType(String id, MaterialType materialType, MaterialVersion materialVersion, String... altNames ) { - this( id, materialType, materialVersion ); - - for ( String altName : altNames ) { - this.altNames.add( altName ); - } - } - - ObsoleteBlockType(String id, MaterialType materialType, MaterialVersion materialVersion ) { - this.legacyId = -1; - this.id = (id != null ? id : "minecraft:" + this.name().toLowerCase()); - this.data = 0; - this.materialType = materialType; - this.materialVersion = materialVersion; - - this.altNames = new ArrayList<>(); - } - - ObsoleteBlockType(MaterialType materialType) { - this(0, null, 0, materialType); - } - - ObsoleteBlockType(int legacyId, String id) { - this(legacyId, id, 0, MaterialType.NOT_SET); - } - - ObsoleteBlockType(int legacyId, String id, int data) { - this(legacyId, id, data, MaterialType.NOT_SET); - } - - /** - *

    This function is for legacy versions of spigot that - * uses the data value. This function will returns a - * string value of a material name that - * XMaterial will be able to use to look up the correct - * bukkit material type. - *

    - * - *

    The way it needs to be constructed, is by taking the id, - * dropping the "minecraft:" prefix, then if data is non-zero, - * add a colon and the value of data. - *

    - * - * - * @return - */ - public String getXMaterialNameLegacy() { - String xMatName = getId().replace( "minecraft:", "" ) + - ( getData() > 0 ? ":" + getData() : "" ); - return xMatName; - } - - /** - *

    This function will return the lower case name of the BlockType. - * This should match - * @return - */ - public String getXMaterialName() { - return name().toLowerCase(); - } - - public List getXMaterialAltNames() { - return getAltNames(); - } - - public static ObsoleteBlockType getBlock(int legacyId) { - return getBlock(legacyId, (short) 0); - } - - public static ObsoleteBlockType getBlock(int legacyId, short data) { - for (ObsoleteBlockType block : values()) { - if (block.getLegacyId() == legacyId) { - if (block.getData() == data) { - return block; - } - } - } - return null; - } - - /** - * This is just an alias for getBlock() which checks for matches in - * many robust ways with numerous fall backs to ensure the best matching. - * @param key - * @return - */ - public static ObsoleteBlockType fromString( String key ) { - return getBlock( key ); - } - /** - *

    Must search first on block name since the block id has potential for duplicates which - * will corrupt the block list for the mine. If at all possible, only search by the block name. - *

    - * - * @param key Block name, id, or number. - * @return - */ - public static ObsoleteBlockType getBlock(String key) { - ObsoleteBlockType blockType = getBlockByName( key ); - if ( blockType == null ) { - blockType = getBlockById( key ); - } - if ( blockType == null ) { - blockType = getBlockByXMaterialName(key); - } - - return blockType; - } - - private static ObsoleteBlockType getBlockById(String id) { - for (ObsoleteBlockType block : values()) { - if (block.getId().equalsIgnoreCase(id) || block.name().equalsIgnoreCase(id) || - block.getId().equalsIgnoreCase( "minecraft:" + id )) { - return block; - } - } - boolean isInt = false; - try { - Integer.parseInt(id.replaceAll(":", "")); - isInt = true; - } catch (Exception e) { - isInt = false; - } - if (isInt) { - if (!id.contains(":")) { - return getBlockWithData(Integer.parseInt(id), (short) 0); - } - return getBlockWithData(Integer.parseInt(id.split(":")[0]), - Short.parseShort(id.split(":")[1])); - } -// Prison prison = Prison.get(); -// if ( prison != null && prison.getItemManager() != null ) { -// Set>> entrySet = prison.getItemManager().getItems().entrySet(); -// for (Map.Entry> entry : entrySet) { -// if (entry.getValue().contains(id.toLowerCase())) { -// return entry.getKey(); -// } -// } -// -// return getBlockByName(id); -// } - return null; - } - - private static ObsoleteBlockType getBlockByName(String name) { - for (ObsoleteBlockType block : values()) { - if (block.name().equalsIgnoreCase(name)) { - return block; - } - } - return null; - } - - private static ObsoleteBlockType getBlockByXMaterialName(String name) { - for (ObsoleteBlockType block : values()) { - if (block.getXMaterialAltNames().size() > 0 ) { - for ( String altName : block.getXMaterialAltNames() ) { - - if ( altName.equalsIgnoreCase(name)) { - return block; - } - } - } - - } - return null; - } - - public static ObsoleteBlockType getBlockWithData(int id, short data) { - for (ObsoleteBlockType block : values()) { - if (block.getLegacyId() == id && block.getData() == data) { - return block; - } - } - return null; - } - - public static boolean isDoor(ObsoleteBlockType block) { - return block == ACACIA_DOOR_BLOCK || block == BIRCH_DOOR_BLOCK - || block == DARK_OAK_DOOR_BLOCK || block == IRON_DOOR_BLOCK - || block == JUNGLE_DOOR_BLOCK || block == OAK_DOOR_BLOCK || block == SPRUCE_DOOR_BLOCK; - } - - public int getLegacyId() { - return legacyId; - } - - public String getId() { - return id; - } - - public short getData() { - return data; - } - - public boolean isBlock() { - return materialType == MaterialType.BLOCK; - } - - public boolean isItem() { - return materialType == MaterialType.ITEM; - } - - public MaterialType getMaterialType() { - return materialType; - } - - public MaterialVersion getMaterialVersion() { - return materialVersion; - } - - public List getAltNames() { - return altNames; - } - - @Override public String toString() { - return id + ":" + data; - } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/PrisonJarReporter.java b/prison-core/src/main/java/tech/mcprison/prison/util/PrisonJarReporter.java index b9cb8f58d..4086a1f76 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/PrisonJarReporter.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/PrisonJarReporter.java @@ -59,6 +59,15 @@ public enum JavaVersion { JavaSE_19("3f"), JavaSE_20("40"), JavaSE_21("41"), + JavaSE_22("42"), + JavaSE_23("43"), + JavaSE_24("44"), + JavaSE_25("45"), + + JavaSE_26("46"), // Confirm with wiki above when it's defined. + JavaSE_27("47"), // Confirm with wiki above when it's defined. + JavaSE_28("48"), // Confirm with wiki above when it's defined. + JavaSE_29("49"), // Confirm with wiki above when it's defined. JavaSE_UnknownVersion("UnknownJavaVersion") ; @@ -95,6 +104,37 @@ public PrisonJarReporter() { this.jarsByPluginName = new TreeMap<>(); } + public List getBukkitVersion() { + List versionMajMin = new ArrayList<>(); + + String version = getBukkitVersionRaw(); + + String versionStr = version.substring( + version.indexOf( "(MC:" ) + 4, version.lastIndexOf( ")" ) ); + String[] vMN = versionStr.split( "\\." ); + + for ( int x = 0; x < vMN.length; x++ ) { + String ver = vMN[x]; + + try { + versionMajMin.add( + Integer.parseInt( ver.trim() ) ); + } + catch ( NumberFormatException e ) { + // ignore... just break out: + break; + } + } + + return versionMajMin; + } + + public String getBukkitVersionRaw() { + + return Prison.get().getMinecraftVersion(); +// return Bukkit.getVersion(); + } + public class JarFileData { private String pluginName; @@ -217,16 +257,6 @@ public void scanForJars() { // These are not our plugins, so if there is a problem, then it really does not matter } -// catch ( ZipException e ) -// { -// e.printStackTrace(); -// } -// catch ( IOException e ) -// { -// e.printStackTrace(); -// } - - } } 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 1b00164f5..be5846f61 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 @@ -132,6 +132,11 @@ public ChatDisplay displayVersion(String options) { boolean showLaddersAndRanks = true; Prison.get().getPlatform().prisonVersionFeatures(display, isBasic, showLaddersAndRanks); + + // check directory structures: + checkDirectoryStructures( display ); + + return display; } @@ -141,6 +146,88 @@ public StringBuilder getSupportSubmitVersionData() { return text; } + + public void checkDirectoryStructures(ChatDisplay display) { + + + display.addText("."); + display.addText("&7Prison File System Check:"); + + display.addText( checkDirectory( "/" ) ); + display.addText( checkDirectory( "backpacks" ) ); + display.addText( checkDirectory( "backups" ) ); + display.addText( checkDirectory( "data_storage" ) ); + display.addText( checkDirectory( "data_storage/mines" ) ); + display.addText( checkDirectory( "data_storage/playerCache" ) ); + display.addText( checkDirectory( "data_storage/ranksDb" ) ); + display.addText( checkDirectory( "data_storage/ranksDb/ladders" ) ); + display.addText( checkDirectory( "data_storage/ranksDb/players" ) ); + display.addText( checkDirectory( "data_storage/ranksDb/ranks" ) ); + display.addText( checkDirectory( "module_conf" ) ); + + } + + private String checkDirectory( String dirPath ) { + + String pathMask = Prison.get().getDataFolder().getParentFile().getAbsolutePath(); + + File path = new File( Prison.get().getDataFolder(), dirPath ); + boolean pathCreated = path.mkdirs(); + + int countDirs = 0; + int countFiles = 0; + double fileSize = 0; + String fileSizeUnit = ""; + + File[] files = path.listFiles(); + for (File f : files) { + + if ( f.isDirectory() ) { + countDirs++; + } + else if ( f.isFile() ) { + countFiles++; + fileSize += f.length(); + } + } + + if ( fileSize > 0 ) { + fileSizeUnit = "bytes"; + + if ( fileSize >= 1024 ) { + fileSize /= 1024.0; + fileSizeUnit = "KB"; + + if ( fileSize >= 1024 ) { + fileSize /= 1024.0; + fileSizeUnit = "MB"; + + if ( fileSize >= 1024 ) { + fileSize /= 1024.0; + fileSizeUnit = "GB"; + + } + } + } + } + + + + DecimalFormat iFmt = Prison.getDecimalFormatStaticInt(); + DecimalFormat dFmt = Prison.getDecimalFormatStaticDouble(); + String msg = String.format( + " &bplugins%-40s &2dirs: %s%3s &2files: %s%3s &2totalFileSize: %s%7s &3%s %s", + path.getAbsolutePath().replace(pathMask, ""), + (countDirs == 0 ? "&3" : "&b"), iFmt.format( countDirs ), + (countFiles == 0 ? "&3" : "&b"), iFmt.format( countFiles ), + (fileSize == 0 ? "&3" : "&b"), dFmt.format( fileSize ), + fileSizeUnit, + ( pathCreated ? " &6DirCreated!" : "" ) + ); + + return msg; + } + public StringBuilder getColorTest() { StringBuilder sb = new StringBuilder(); @@ -254,13 +341,6 @@ public StringBuilder getSupportSubmitRanksData() { 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; } @@ -281,8 +361,6 @@ public StringBuilder getSupportSubmitRanksFileData() { } public StringBuilder getSupportSubmitMinesData() { -// List files = listFiles("data_storage/mines/mines/", ".json"); -// Collections.sort(files); StringBuilder text = new StringBuilder(); @@ -296,13 +374,6 @@ public StringBuilder getSupportSubmitMinesData() { // Display a list of all mines, then display the /mines info all for // each: text.append(Prison.get().getPlatform().getMinesListString()); -// printFooter(text); - -// // get all the file details for each mine: -// for (File file : files) { -// -// addFileToText(file, text); -// } return text; } @@ -332,48 +403,42 @@ public StringBuilder getSupportSubmitListenersData( String listenerType ) { listenerType = "all"; } - if ( "blockBreak".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { - - sb.append( "||Listeners blockBreak||" ); - sb.append( Prison.get().getPlatform().dumpEventListenersBlockBreakEvents() ); - } - - if ( "blockPlace".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { - - sb.append( "||Listeners blockPlace||" ); - sb.append( Prison.get().getPlatform().dumpEventListenersBlockPlaceEvents() ); - } - - if ( "chat".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { - - sb.append( "||Listeners chat||" ); - sb.append( Prison.get().getPlatform().dumpEventListenersPlayerChatEvents() ); - } - -// if ( "traceBlockBreak".equalsIgnoreCase( listenerType ) ) { -// -// Prison.get().getPlatform().traceEventListenersBlockBreakEvents( sender ); -// -// } - - if ( "playerInteract".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { - - sb.append( "||Listeners playerInteract||" ); - sb.append( Prison.get().getPlatform().dumpEventListenersPlayerInteractEvents() ); - } - - if ( "playerDropItem".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { - - sb.append( "||Listeners playerDropItem||" ); - sb.append( Prison.get().getPlatform().dumpEventListenersPlayerDropItemEvents() ); - } - - if ( "playerPickupItem".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { - - sb.append( "||Listeners playerPickupItem||" ); - sb.append( Prison.get().getPlatform().dumpEventListenersPlayerPickupItemEvents() ); - } - + if ( "blockBreak".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { + + sb.append( "||Listeners blockBreak||" ); + sb.append( Prison.get().getPlatform().dumpEventListenersBlockBreakEvents() ); + } + + if ( "blockPlace".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { + + sb.append( "||Listeners blockPlace||" ); + sb.append( Prison.get().getPlatform().dumpEventListenersBlockPlaceEvents() ); + } + + if ( "chat".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { + + sb.append( "||Listeners chat||" ); + sb.append( Prison.get().getPlatform().dumpEventListenersPlayerChatEvents() ); + } + + if ( "playerInteract".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { + + sb.append( "||Listeners playerInteract||" ); + sb.append( Prison.get().getPlatform().dumpEventListenersPlayerInteractEvents() ); + } + + if ( "playerDropItem".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { + + sb.append( "||Listeners playerDropItem||" ); + sb.append( Prison.get().getPlatform().dumpEventListenersPlayerDropItemEvents() ); + } + + if ( "playerPickupItem".equalsIgnoreCase( listenerType ) || "all".equalsIgnoreCase( listenerType ) ) { + + sb.append( "||Listeners playerPickupItem||" ); + sb.append( Prison.get().getPlatform().dumpEventListenersPlayerPickupItemEvents() ); + } + return sb; } @@ -387,9 +452,9 @@ public StringBuilder getCommandStatsDetailData() { List cmds = getCommandStats(); cmds.add( 1, "||CommandStats List||" ); - for (String cmd : cmds) { - - sb.append( cmd ).append( "\n" ); + for (String cmd : cmds) { + + sb.append( cmd ).append( "\n" ); } return sb; @@ -410,41 +475,41 @@ private List getCommandStats() { 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(); - } + 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. " ); + + 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; @@ -454,13 +519,13 @@ private List getCommandStats() { public StringBuilder getPrisonBackupLogsData() { StringBuilder sb = new StringBuilder(); - // Include Prison backup logs: + // 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" ); + List backupLogs = getPrisonBackupLogs(); + + for (String log : backupLogs) { + sb.append( Output.decodePercentEncoding(log) ).append( "\n" ); } return sb; @@ -468,9 +533,9 @@ public StringBuilder getPrisonBackupLogsData() { public List getPrisonBackupLogs() { - PrisonBackups prisonBackup = new PrisonBackups(); - List backupLogs = prisonBackup.backupReport02BackupLog(); - return backupLogs; + PrisonBackups prisonBackup = new PrisonBackups(); + List backupLogs = prisonBackup.backupReport02BackupLog(); + return backupLogs; } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java b/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPSSingleton.java similarity index 90% rename from prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java rename to prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPSSingleton.java index aab73a7a5..58d6eab47 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPS.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/PrisonTPSSingleton.java @@ -158,9 +158,11 @@ *

    * */ -public class PrisonTPS +public class PrisonTPSSingleton implements PrisonRunnable { + private static PrisonTPSSingleton instance; + /** * Note: Normally the task would have to run each tick, but by specifying the * SUBMIT_TICKS_INTERVAL it can skip a number of ticks to reduce the @@ -206,6 +208,23 @@ public class PrisonTPS public static final Object tpsLock = new Object(); + private PrisonTPSSingleton() { + super(); + } + + + public static PrisonTPSSingleton getInstance() { + if ( instance == null ) { + synchronized ( PrisonTPSSingleton.class ) { + if ( instance == null ) { + instance = new PrisonTPSSingleton(); + } + } + } + return instance; + } + + // When submitted, taskId identifies the job. A value of -1 indicates the job // failed to be submitted, or is not valid. private int taskId = -1; @@ -320,72 +339,63 @@ public void setHighResolution( boolean highResolution ) { * @return */ public double getAverageTPS() { - double avg = 0d; - - int cnt = 0; - - // Start collecting readings from the tail-end of the tpsHistory collection - // since that is the most recent reading: - synchronized ( tpsLock ) { - - for ( int i = tpsHistory.size(); i > 0; i-- ) { - double reading = tpsHistory.get( i - 1 ); - - // Ignore readings above TPS_THRESHOLD_TO_RECORD - if ( reading <= TPS_THRESHOLD_TO_RECORD ) { - avg += reading; - - // Once we get our target count, then break out of the for loop: - if ( cnt++ < TPS_AVERAGE_READINGS_TO_INCLUDE ) { - break; - } - } - } - } - - // Do not divide avg by count if zero or one: - if ( cnt > 1 ) { - avg /= cnt; - } - return avg; - - // The following was averaging all counts in the history, including very high values. - // This is no longer favorable. -// for (final Double f : tpsHistory) { -// if (f != null) { -// avg += f; -// } -// } -// return tpsHistory.size() == 0 ? 0 : avg / tpsHistory.size(); + double avg = 0d; + + int cnt = 0; + + // Start collecting readings from the tail-end of the tpsHistory collection + // since that is the most recent reading: + synchronized ( tpsLock ) { + + for ( int i = tpsHistory.size(); i > 0; i-- ) { + double reading = tpsHistory.get( i - 1 ); + + // Ignore readings above TPS_THRESHOLD_TO_RECORD + if ( reading <= TPS_THRESHOLD_TO_RECORD ) { + avg += reading; + + // Once we get our target count, then break out of the for loop: + if ( cnt++ < TPS_AVERAGE_READINGS_TO_INCLUDE ) { + break; + } + } + } + } + + // Do not divide avg by count if zero or one: + if ( cnt > 1 ) { + avg /= cnt; + } + return avg; } public String getAverageTPSFormatted() { - return tpsFmt.format( getAverageTPS() ); + return tpsFmt.format( getAverageTPS() ); } public String getTPSMinFormatted() { - return tpsFmt.format( getTpsMin() ); + return tpsFmt.format( getTpsMin() ); } public String getTPSMaxFormatted() { - return tpsFmt.format( getTpsMax() ); + return tpsFmt.format( getTpsMax() ); } public String getLastFewTPS() { - StringBuilder sb = new StringBuilder(); - - int cnt = 0; - - synchronized ( tpsLock ) { - - for ( int i = tpsHistory.size(); i > 0 && cnt++ < 15; i-- ) { - sb.append( tpsFmt.format( tpsHistory.get( i - 1 ) ) ).append( " " ); - } - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + int cnt = 0; + + synchronized ( tpsLock ) { + + for ( int i = tpsHistory.size(); i > 0 && cnt++ < 15; i-- ) { + sb.append( tpsFmt.format( tpsHistory.get( i - 1 ) ) ).append( " " ); + } + } + + return sb.toString(); } 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 c9af8c48f..8ca681dfb 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 @@ -113,13 +113,13 @@ public class Text private static DecimalFormat iFmt = Prison.getDecimalFormatStaticInt(); static { - if ( Prison.get() != null ) { - - } + if ( Prison.get() != null ) { + + } } protected Text() { - super(); + super(); } @@ -352,20 +352,24 @@ public static String implodeCommaAnd(final Collection objects) { * @return The translated string. */ public static String translateColorCodes(String text, char prefix) { - return translateColorCodes( text, prefix, COLOR_CHAR, COLOR_CHAR ); + return translateColorCodes( text, prefix, COLOR_CHAR, COLOR_CHAR ); } - public static String translateColorCodes(String text, char prefix, + private static String translateColorCodes(String text, char prefix, char targetColorCode, char targetHexColorCode) { if (prefix == COLOR_CHAR) { return text; // No need to translate, it's already been translated } + // If the hex color codes are translated here, then it was not marking + // 'dirty' as being true, when it actually was. + // So to fix, eliminate 'dirty' and always convert the character array to + // a String. char[] b = translateHexColorCodes( text, targetHexColorCode ).toCharArray(); int len = b.length; - boolean dirty = false; +// boolean dirty = false; boolean quote = false; boolean quoted = false; @@ -385,11 +389,12 @@ else if ( quote ) { else if (b[i] == prefix && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr#xX".indexOf(b[i + 1]) > -1) { b[i] = targetColorCode; // COLOR_CHAR; // 167; // Section symbol b[i + 1] = Character.toLowerCase(b[i + 1]); - dirty = true; +// dirty = true; } } - String results = dirty ? new String(b) : text; + String results = new String(b); +// String results = dirty ? new String(b) : text; if ( quoted ) { results = results.replace( "\\Q", "" ).replace( "\\E", "" ); } @@ -430,8 +435,17 @@ public static String translateAmpColorCodes(String text) { * @return */ public static String translateAmpColorCodesAltHexCode(String text) { - return translateColorCodes( text, '&', COLOR_CHAR, '&' ); + return translateColorCodes( text, '&', COLOR_CHAR, '&' ); } + + // NOTE: It's not needed to remove the '&' +// public static String translateAmpColorCodesAltHex2Code(String text) { +// if ( text != null && text.contains( "&#" ) ) { +// text = text.replace( "&#", "#" ); +// } +// return translateColorCodes( text, '&', COLOR_CHAR, '&' ); +// } + /** * Strips the given message of all color codes * @@ -460,41 +474,41 @@ public static String stripColor(String text) { * @param targetColorCode * @return */ - public static String translateHexColorCodes( String text, char targetColorCode ) { - StringBuilder sb = new StringBuilder(); - - if ( text != null && !text.trim().isEmpty() ) { - - int idxStart = text.indexOf( "\\Q" ); - int idxEnd = -1; - - if ( idxStart == -1 ) { - sb.append( translateHexColorCodesCore( text, targetColorCode ) ); - } - else { - while ( idxStart >= 0 ) { - sb.append( translateHexColorCodesCore( - text.substring( idxEnd + (idxEnd == -1 ? 1 : 0), idxStart ), targetColorCode) ); - - idxEnd = text.indexOf( "\\E", idxStart ); - - if ( idxEnd == -1 ) { - sb.append( text.substring( idxStart ) ); - idxStart = -1; - } - else { - sb.append( text.substring( idxStart, idxEnd ) ); - - idxStart = text.indexOf( "\\Q", idxEnd ); - } - } - if ( idxStart == -1 && idxEnd >= 0 && (idxEnd) < text.length() ) { - sb.append( text.substring( idxEnd ) ); - } - } - } - - return sb.toString(); + protected static String translateHexColorCodes( String text, char targetColorCode ) { + StringBuilder sb = new StringBuilder(); + + if ( text != null && !text.trim().isEmpty() ) { + + int idxStart = text.indexOf( "\\Q" ); + int idxEnd = -1; + + if ( idxStart == -1 ) { + sb.append( translateHexColorCodesCore( text, targetColorCode ) ); + } + else { + while ( idxStart >= 0 ) { + sb.append( translateHexColorCodesCore( + text.substring( idxEnd + (idxEnd == -1 ? 1 : 0), idxStart ), targetColorCode) ); + + idxEnd = text.indexOf( "\\E", idxStart ); + + if ( idxEnd == -1 ) { + sb.append( text.substring( idxStart ) ); + idxStart = -1; + } + else { + sb.append( text.substring( idxStart, idxEnd ) ); + + idxStart = text.indexOf( "\\Q", idxEnd ); + } + } + if ( idxStart == -1 && idxEnd >= 0 && (idxEnd) < text.length() ) { + sb.append( text.substring( idxEnd ) ); + } + } + } + + return sb.toString(); } /** @@ -506,39 +520,45 @@ public static String translateHexColorCodes( String text, char targetColorCode ) * @param targetColorCode the char value that is used to inject as a color code * @return */ - public static String translateHexColorCodesCore(String message, char targetColorCode) { - String results = ""; - - if ( message != null ) { - -// final Pattern hexPattern = Pattern.compile(startTag + "([A-Fa-f0-9]{6})" + endTag); - - Matcher matcher = HEX_PATTERN.matcher(message); - StringBuffer buffer = new StringBuffer(message.length() + 4 * 8); - while (matcher.find()) { - String group = matcher.group(1); - matcher.appendReplacement(buffer, targetColorCode + "x" - + targetColorCode + group.charAt(0) + targetColorCode + group.charAt(1) - + targetColorCode + group.charAt(2) + targetColorCode + group.charAt(3) - + targetColorCode + group.charAt(4) + targetColorCode + group.charAt(5) - ); - } - results = matcher.appendTail(buffer).toString(); - } - - return results; + private static String translateHexColorCodesCore(String message, char targetColorCode) { + String results = ""; + + if ( message != null ) { + + // NOTE: if '&#' is used, then it will convert the hex codes, but it will also + // leave the leading '&' there. So remove the '&' prefix. + if ( message != null && message.contains( "&#" ) ) { + message = message.replace( "&#", "#" ); + } + + // final Pattern hexPattern = Pattern.compile(startTag + "([A-Fa-f0-9]{6})" + endTag); + + Matcher matcher = HEX_PATTERN.matcher(message); + StringBuffer buffer = new StringBuffer(message.length() + 4 * 8); + while (matcher.find()) { + String group = matcher.group(1); + matcher.appendReplacement(buffer, targetColorCode + "x" + + targetColorCode + group.charAt(0) + targetColorCode + group.charAt(1) + + targetColorCode + group.charAt(2) + targetColorCode + group.charAt(3) + + targetColorCode + group.charAt(4) + targetColorCode + group.charAt(5) + ); + } + results = matcher.appendTail(buffer).toString(); + } + + return results; } - public static String convertToAmpColorCodes( String textEncoded ) { + private static String convertToAmpColorCodes( String textEncoded ) { - String results = textEncoded; - - if ( textEncoded != null && textEncoded.contains( COLOR_ ) ) { - results = textEncoded.replaceAll( COLOR_, "&" ); - } - - return results; + String results = textEncoded; + + if ( textEncoded != null && textEncoded.contains( COLOR_ ) ) { + results = textEncoded.replaceAll( COLOR_, "&" ); + } + + return results; } /** @@ -553,7 +573,7 @@ public static String convertToAmpColorCodes( String textEncoded ) { * @return */ public static String escapeAmpCodes( String textEncoded ) { - return convertToAmpColorCodes(textEncoded).replaceAll("&", "U+0026"); + return convertToAmpColorCodes(textEncoded).replaceAll("&", "U+0026"); } /** @@ -629,17 +649,17 @@ public static String tab(String text) { * @return The human-readable string. */ public static String getTimeUntilString(long millis) { - return getTimeUntilString( millis, unitMillis, unitPrefixSpacer, null ); + return getTimeUntilString( millis, unitMillis, unitPrefixSpacer, null ); } public static String getTimeUntilString(long millis, String spaces ) { - return getTimeUntilString( millis, unitMillis, spaces, null ); + return getTimeUntilString( millis, unitMillis, spaces, null ); } public static String getTimeUntilShortString(long millis, String spaces ) { - return getTimeUntilString( millis, unitMillisShort, spaces, null ); + 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 ); + DecimalFormat dFmt = new DecimalFormat( "00" ); + return getTimeUntilString( millis, unitMillisColons, spaces, dFmt ); } private static String getTimeUntilString(long millis, Map units, String unitSpacer, DecimalFormat dFmt ) { @@ -705,16 +725,16 @@ public static String pluralize(String baseNoun, int quantity) { public static String formatTimeDaysHhMmSs( long timeMs ) { - DecimalFormat iFmt = Prison.getDecimalFormatStaticInt(); - DecimalFormat tFmt = Prison.getDecimalFormatStatic("00"); + DecimalFormat iFmt = Prison.getDecimalFormatStaticInt(); + DecimalFormat tFmt = Prison.getDecimalFormatStatic("00"); // SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); // long _sec = 1000; // long _min = _sec * 60; // long _hour = _min * 60; // long _day = _hour * 24; - - long ms = timeMs; + + long ms = timeMs; long days = millisPerDay < ms ? ms / millisPerDay : 0; ms -= (days * millisPerDay); @@ -740,22 +760,18 @@ public static String formatTimeDaysHhMmSs( long timeMs ) { public static List formatTreeMapStats( TreeMap statMap, int columns ) { - return formatTreeMapStats( statMap, columns, false ); + return formatTreeMapStats( statMap, columns, false ); } public static List formatTreeMapStats( TreeMap statMap, int columns, boolean timeFormat ) { - List msgs = new ArrayList<>(); + List msgs = new ArrayList<>(); Set keys = statMap.keySet(); List values = new ArrayList<>(); -// List valueMaxLen = new ArrayList<>(); - -// StringBuilder sb = new StringBuilder(); -// int count = 0; for ( String earningKey : keys ) { @@ -784,84 +800,31 @@ else if ( valueObj instanceof Long ) { String msg = String.format( "&3%s&8: &b%s", earningKey, value ).trim(); -// String msgNoColor = Text.stripColor( msg ); -// int lenMNC = msgNoColor.length(); -// -// -// int col = values.size() % columns; values.add( msg ); -// if ( col >= valueMaxLen.size() || lenMNC > valueMaxLen.get( col ) ) { -// -// if ( col > valueMaxLen.size() - 1 ) { -// valueMaxLen.add( lenMNC ); -// } -// else { -// -// valueMaxLen.set( col, lenMNC ); -// } -// } } msgs = formatColumnsFromList( values, columns ); - -// for ( int j = 0; j < values.size(); j++ ) -// { -// String msg = values.get( j ); -// -// int col = j % columns; -// -// int maxColumnWidth = col > valueMaxLen.size() - 1 ? -// msg.length() : -// valueMaxLen.get( col ); -// -// sb.append( msg ); -// -// // Pad the right of all content with spaces to align columns, up to a -// // given maxLength: -// String msgNoColor = Text.stripColor( msg ); -// int lenMNC = msgNoColor.length(); -// for( int i = lenMNC; i < maxColumnWidth; i++ ) { -// sb.append( " " ); -// } -// -// // The spacer: -// sb.append( " " ); -// -// if ( ++count % columns == 0 ) { -// msgs.add( String.format( -// " " + sb.toString() ) ); -// sb.setLength( 0 ); -// -// } -// } -// -// if ( sb.length() > 0 ) { -// -// msgs.add( String.format( -// " " + sb.toString() ) ); -// } - - return msgs; + + return msgs; } public static List formatColumnsFromList( List textItems, int columns ) { - List msgs = new ArrayList<>(); - - List valueMaxLen = new ArrayList<>(); - - StringBuilder sb = new StringBuilder(); - int count = 0; - - // Find the maxLenght value for each column that will be generated: - for ( int i = 0; i < textItems.size(); i++ ) - { - String msg = textItems.get( i ); - - String msgNoColor = Text.stripColor( msg ); + List msgs = new ArrayList<>(); + + List valueMaxLen = new ArrayList<>(); + + StringBuilder sb = new StringBuilder(); + int count = 0; + + // Find the maxLenght value for each column that will be generated: + for ( int i = 0; i < textItems.size(); i++ ) { + String msg = textItems.get( i ); + + String msgNoColor = Text.stripColor( msg ); int lenMNC = msgNoColor.length(); @@ -878,7 +841,7 @@ public static List formatColumnsFromList( List textItems, } } } - + for ( int j = 0; j < textItems.size(); j++ ) { @@ -910,14 +873,14 @@ public static List formatColumnsFromList( List textItems, } } - + if ( sb.length() > 0 ) { msgs.add( String.format( " " + sb.toString() ) ); } - - return msgs; + + return msgs; } } diff --git a/prison-core/src/main/java/tech/mcprison/prison/util/Vector.java b/prison-core/src/main/java/tech/mcprison/prison/util/Vector.java index 46c93e2ee..b9695b6f1 100644 --- a/prison-core/src/main/java/tech/mcprison/prison/util/Vector.java +++ b/prison-core/src/main/java/tech/mcprison/prison/util/Vector.java @@ -20,6 +20,7 @@ import tech.mcprison.prison.internal.World; +import java.text.DecimalFormat; import java.util.LinkedHashMap; import java.util.Map; import java.util.Random; @@ -616,7 +617,8 @@ public int getBlockZ() { * to account for floating point errors. The epsilon can be retrieved * with epsilon. */ - @Override public boolean equals(Object obj) { + @Override + public boolean equals(Object obj) { if (!(obj instanceof Vector)) { return false; } @@ -632,7 +634,8 @@ public int getBlockZ() { * * @return hash code */ - @Override public int hashCode() { + @Override + public int hashCode() { int hash = 7; hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) @@ -649,7 +652,8 @@ public int getBlockZ() { * * @return vector */ - @Override public Vector clone() { + @Override + public Vector clone() { try { return (Vector) super.clone(); } catch (CloneNotSupportedException e) { @@ -660,8 +664,19 @@ public int getBlockZ() { /** * Returns this vector's components as x,y,z. */ - @Override public String toString() { - return x + "," + y + "," + z; + @Override + public String toString() { + + DecimalFormat dFmt = new DecimalFormat( "##0.0000" ); + + String msg = String.format( + "x: %8s y: %8s z: %8s", + dFmt.format( getX() ), + dFmt.format( getY() ), + dFmt.format( getZ() ) + ); + + return msg; } /** diff --git a/prison-core/src/main/java/tech/mcprison/prison/wip/internal/heads/MinecraftHeadData.java b/prison-core/src/main/java/tech/mcprison/prison/wip/internal/heads/MinecraftHeadData.java new file mode 100644 index 000000000..277131951 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/wip/internal/heads/MinecraftHeadData.java @@ -0,0 +1,76 @@ +package tech.mcprison.prison.wip.internal.heads; + +import java.util.ArrayList; +import java.util.List; + +import tech.mcprison.prison.wip.internal.heads.MinecraftHeadsCache.MinecraftHeadsCategory; + +public class MinecraftHeadData { + + private MinecraftHeadsCategory category; + private String name; + private String uuid; + private String value; + private String tags; + + private boolean used; + + private transient List tagList; + + public MinecraftHeadData() { + super(); + + this.used = false; + + this.tagList = new ArrayList<>(); + } + + public MinecraftHeadsCategory getCategory() { + return category; + } + public void setCategory(MinecraftHeadsCategory category) { + this.category = category; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public String getUuid() { + return uuid; + } + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + public String getTags() { + return tags; + } + public void setTags(String tags) { + this.tags = tags; + } + + public List getTagList() { + return tagList; + } + public void setTagList(List tagList) { + this.tagList = tagList; + } + + public boolean isUsed() { + return used; + } + public void setUsed(boolean used) { + this.used = used; + } +} diff --git a/prison-core/src/main/java/tech/mcprison/prison/wip/internal/heads/MinecraftHeadsCache.java b/prison-core/src/main/java/tech/mcprison/prison/wip/internal/heads/MinecraftHeadsCache.java new file mode 100644 index 000000000..c62cff466 --- /dev/null +++ b/prison-core/src/main/java/tech/mcprison/prison/wip/internal/heads/MinecraftHeadsCache.java @@ -0,0 +1,196 @@ +package tech.mcprison.prison.wip.internal.heads; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.TreeMap; +import java.util.TreeSet; + +public class MinecraftHeadsCache { + + private static MinecraftHeadsCache instance; + + private Date headDataDownloadDate; + + private transient TreeSet tags; + + private List headData; + + private transient TreeMap> headDataByCategory; + + private transient TreeMap headDataByUuid; + + private transient TreeMap> headDataByTags; + + public enum MinecraftHeadsCategory { + alphabet, + animals, + blocks, + decoration, + fooddrink("food-drinks"), + humans, + humanoid, + miscellaneous, + monsters, + plants; + + private final String value; + private MinecraftHeadsCategory() { + this.value = this.name(); + } + private MinecraftHeadsCategory( String value ) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + private MinecraftHeadsCache() { + super(); + + this.headDataDownloadDate = null; + + this.tags = new TreeSet<>(); + + this.headData = new ArrayList<>(); + + this.headDataByUuid = new TreeMap<>(); + + this.headDataByTags = new TreeMap<>(); + } + + public static MinecraftHeadsCache getInstance() { + if ( instance == null ) { + + synchronized ( MinecraftHeadsCache.class ) { + if ( instance == null ) { + instance = new MinecraftHeadsCache(); + } + } + } + + return instance; + } + + + /** + *

    After the headData is loaded from the file system, this function will build + * the associated indexes to allow the heads to be accessed in various ways. + *

    + * + */ + public void parseHeadData( boolean purgeUnused ) { + List purge = new ArrayList<>(); + + for (MinecraftHeadData head : this.headData ) { + + if ( purgeUnused && !head.isUsed() ) { + purge.add( head ); + } + + else { + + // Build the category index: + if ( !getHeadDataByCategory().containsKey( head.getCategory() ) ) { + getHeadDataByCategory().put( head.getCategory(), new ArrayList<>() ); + } + getHeadDataByCategory().get( head.getCategory() ).add( head ); + + // build uuid index: + if ( !getHeadDataByUuid().containsKey( head.getUuid() ) ) { + getHeadDataByUuid().put( head.getUuid(), head ); + } + + // Extract tags: + if ( head.getTags() != null ) { + List tagz = Arrays.asList( + head.getTags().toLowerCase().split(",") ); + // Extract "tags" in the name field that are within parenthesis: + getTagFromName( head.getName(), tagz ); + + for ( String tag : tagz ) { + + // Add to tag collection: + if ( !getTags().contains( tag ) ) { + getTags().add( tag ); + } + + if ( !getHeadDataByTags().containsKey( tag ) ) { + getHeadDataByTags().put( tag, new ArrayList<>() ); + } + getHeadDataByTags().get( tag ).add( head ); + + } + + } + } + + } + + + if ( purgeUnused && purge.size() > 0 ) { + getHeadData().removeAll( purge ); + } + } + + private void getTagFromName(String name, List tagz) { + + int b = name.indexOf('('); + int e = name.indexOf(')'); + + if ( b != -1 && e != -1 && b < e ) { + String tag = name.substring( b + 1, e ).toLowerCase(); + tagz.add( tag ); + } + } + + public Date getHeadDataDownloadDate() { + return headDataDownloadDate; + } + public void setHeadDataDownloadDate(Date headDataDownloadDate) { + this.headDataDownloadDate = headDataDownloadDate; + } + + public TreeSet getTags() { + return tags; + } + + public void setTags(TreeSet tags) { + this.tags = tags; + } + + public List getHeadData() { + return headData; + } + + public void setHeadData(List headData) { + this.headData = headData; + } + + public TreeMap> getHeadDataByCategory() { + return headDataByCategory; + } + + public void setHeadDataByCategory(TreeMap> headDataByCategory) { + this.headDataByCategory = headDataByCategory; + } + + public TreeMap getHeadDataByUuid() { + return headDataByUuid; + } + + public void setHeadDataByUuid(TreeMap headDataByUuid) { + this.headDataByUuid = headDataByUuid; + } + + public TreeMap> getHeadDataByTags() { + return headDataByTags; + } + + public void setHeadDataByTags(TreeMap> headDataByTags) { + this.headDataByTags = headDataByTags; + } +} 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 fa3866cf2..7f986035d 100644 --- a/prison-core/src/main/resources/lang/core/de_DE.properties +++ b/prison-core/src/main/resources/lang/core/de_DE.properties @@ -79,7 +79,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=10 +messages__version=11 messages__auto_refresh=true @@ -232,3 +232,7 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. + 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 469ec9e69..630cb8cdb 100644 --- a/prison-core/src/main/resources/lang/core/en_GB.properties +++ b/prison-core/src/main/resources/lang/core/en_GB.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=10 +messages__version=11 messages__auto_refresh=true @@ -232,3 +232,7 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. + 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 19f7bb39a..58c4e21a3 100644 --- a/prison-core/src/main/resources/lang/core/en_US.properties +++ b/prison-core/src/main/resources/lang/core/en_US.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=11 +messages__version=12 messages__auto_refresh=true @@ -232,4 +232,8 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. + 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 071440daf..41e3dfc3d 100644 --- a/prison-core/src/main/resources/lang/core/es_ES.properties +++ b/prison-core/src/main/resources/lang/core/es_ES.properties @@ -76,133 +76,133 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=10 +messages__version=12 messages__auto_refresh=true core_output__prefix_template=| %1 | &7 -core_output__prefix_template_prison=Prison -core_output__prefix_template_info=Info -core_output__prefix_template_warning=Warning +core_output__prefix_template_prison=Prisión +core_output__prefix_template_info=Información +core_output__prefix_template_warning=Advertencia core_output__prefix_template_error=Error -core_output__prefix_template_debug=Debug +core_output__prefix_template_debug=Depurar core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c 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 +core_output__error_startup_failure=Prisión: (Enviando a System.err debido a falla en el registro de salida): +core_output__error_incorrect_number_of_parameters=Falla en el registro (%1): Número incorrecto de parámetros: [%2] Mensaje en bruto original: [%3] Argumentos: %4 core_text__prefix=&3 -core_text__just_now=just now -core_text__ago=ago -core_text__from_now=from now -core_text__and=and +core_text__just_now=justo ahora +core_text__ago=hace +core_text__from_now=dentro de +core_text__and=y core_text__time_units_prefix_spacer= -core_text__time_units_singular=year,month,week,day,hour,minute,second -core_text__time_units_plural=years,months,weeks,days,hours,minutes,seconds -core_text__time_units_short=y,m,w,d,h,m,s +core_text__time_units_singular=año,mes,semana,día,hora,minuto,segundo +core_text__time_units_plural=años,meses,semanas,días,horas,minutos,segundos +core_text__time_units_short=a,m,s,d,h,m,s -core_tokens__name_required=Prison Tokens=A player's name is required when used from console. -core_tokens__cannot_view_others_balances=Prison Tokens: You do not have permission to view other player's balances. -core_tokens__view_balance=&3%1 has %2 tokens. -core_tokens__add_invalid_amount=Prison Tokens: Invalid amount: '%1'. Must be greater than zero. -core_tokens__added_amount=&3%1 now has &7%2 &3tokens after adding &7%3&3. -core_tokens__removed_amount=&3%1 now has &7%2 &3tokens after removing &7%3&3. -core_tokens__set_amount=&3%1 now has &7%2 &3tokens. +core_tokens__name_required=Tokens de la Prisión=Se requiere un nombre de jugador cuando se usa desde la consola. +core_tokens__cannot_view_others_balances=Tokens de la Prisión: No tienes permiso para ver los saldos de otros jugadores. +core_tokens__view_balance=&3%1 tiene %2 tokens. +core_tokens__add_invalid_amount=Tokens de la Prisión: Cantidad inválida: '%1'. Debe ser mayor que cero. +core_tokens__added_amount=&3%1 ahora tiene &7%2 &3tokens después de agregar &7%3&3. +core_tokens__removed_amount=&3%1 ahora tiene &7%2 &3tokens después de eliminar &7%3&3. +core_tokens__set_amount=&3%1 ahora tiene &7%2 &3tokens. -core_runCmd__name_required=A valid player name is required. -core_runCmd__command_required=A command is required. +core_runCmd__name_required=Se requiere un nombre de jugador válido. +core_runCmd__command_required=Se requiere un comando. + + +core_prison_utf8_test=Привет! Давай поÑмотрим, работает ли? Test 01 # The following are the original messages and they will eventually be replaced. includeError=[%1] tiene un valor inválido. excludeError=[%1] tiene un valor inválido. -cantAsConsole=No puedes realizar esto desde la consola. -missingArgument=The argument [%1] no está definido (no tiene valor predeterminado). +cantAsConsole=No puedes hacer esto como consola. +missingArgument=El argumento [%1] no está definido (no tiene un valor predeterminado). missingFlagArgument=La bandera -%1 no tiene los parámetros requeridos. -undefinedFlagArgument= [%1] para la bandera -%2 no está definido. -internalErrorOccurred=Un error interno ha ocurrido al ejecutar este comando. -noPermission=No tienes los permisos requeridos para ejecutar este comando. +undefinedFlagArgument=El argumento [%1] de la bandera -%2 no está definido. +internalErrorOccurred=Se produjo un error interno al intentar realizar este comando. +noPermission=Le faltan los permisos necesarios para realizar este comando. blockParseError=El parámetro [%1] no es un bloque válido. numberParseError=El parámetro [%1] no es un número. -numberTooLow=El parámetro [%1] debe ser igual o mayor a %2. -numberTooHigh=El parámetro [%1] debe ser igual o menor a %2. -numberRangeError=El parámetro [%1] debe ser igual o mayor a %2 y menor o igual a %3. -tooFewCharacters=El parámetro [%1] debe ser igual o mayor a %2 caracteres. -tooManyCharacters=El parámetro [%1] debe ser igual o menor a %2 caracteres. -playerNotOnline=El jugador %1 no se encuentra conectado. -worldNotFound=El mundo %1 no ha sido encontrado. - - - +numberTooLow=El parámetro [%1] debe ser igual o mayor que %2. +numberTooHigh=El parámetro [%1] debe ser igual o menor que %2. +numberRangeError=El parámetro [%1] debe ser igual o mayor que %2 y menor o igual que %3. +tooFewCharacters=El parámetro [%1] debe tener igual o mayor que %2 caracteres. +tooManyCharacters=El parámetro [%1] debe tener igual o menor que %2 caracteres. +playerNotOnline=El jugador %1 no está en línea. +worldNotFound=El mundo %1 no se encontró. -core_gui__click_to_decrease=&3Click to decrease. -core_gui__click_to_increase=&3Click to increase. +core_gui__click_to_decrease=&3Haz clic para disminuir. +core_gui__click_to_increase=&3Haz clic para aumentar. -core_gui__click_to_cancel=&3Click to cancel. -core_gui__click_to_close=&3Click to close. -core_gui__click_to_confirm=&3Click to confirm. -core_gui__click_to_delete=&3Click to delete. -core_gui__click_to_disable=&3Click to disable. -core_gui__click_to_edit=&3Click to edit. -core_gui__click_to_enable=&3Click to enable. -core_gui__click_to_open=&3Click to open. +core_gui__click_to_cancel=&3Haz clic para cancelar. +core_gui__click_to_close=&3Haz clic para cerrar. +core_gui__click_to_confirm=&3Haz clic para confirmar. +core_gui__click_to_delete=&3Haz clic para eliminar. +core_gui__click_to_disable=&3Haz clic para desactivar. +core_gui__click_to_edit=&3Haz clic para editar. +core_gui__click_to_enable=&3Haz clic para habilitar. +core_gui__click_to_open=&3Haz clic para abrir. -core_gui__left_click_to_confirm=&3Left-Click to confirm. -core_gui__left_click_to_reset=&3Left-Click to reset. -core_gui__left_click_to_open=&3Left-Click to open. -core_gui__left_click_to_edit=&3Left-Click to edit. +core_gui__left_click_to_confirm=&3Haz clic izquierdo para confirmar. +core_gui__left_click_to_reset=&3Haz clic izquierdo para restablecer. +core_gui__left_click_to_open=&3Haz clic izquierdo para abrir. +core_gui__left_click_to_edit=&3Haz clic izquierdo para editar. -core_gui__right_click_to_cancel=&3Right-Click to cancel. -core_gui__right_click_to_delete=&3Right-Click to delete. -core_gui__right_click_to_disable=&3Right-Click to disable. -core_gui__right_click_to_enable=&3Right-Click to enable. -core_gui__right_click_to_toggle=&3Right-Click to toggle. +core_gui__right_click_to_cancel=&3Haz clic derecho para cancelar. +core_gui__right_click_to_delete=&3Haz clic derecho para eliminar. +core_gui__right_click_to_disable=&3Haz clic derecho para desactivar. +core_gui__right_click_to_enable=&3Haz clic derecho para habilitar. +core_gui__right_click_to_toggle=&3Haz clic derecho para alternar. -core_gui__right_click_and_shift_to_delete=&3Right-Click and shift to delete. -core_gui__right_click_and_shift_to_disable=&3Right-Click and shift to disable. -core_gui__right_click_and_shift_to_toggle=&3Right-Click and shift to toggle. +core_gui__right_click_and_shift_to_delete=&3Haz clic derecho y shift para eliminar. +core_gui__right_click_and_shift_to_disable=&3Haz clic derecho y shift para desactivar. +core_gui__right_click_and_shift_to_toggle=&3Haz clic derecho y shift para alternar. -core_gui__page_next=&3Next page. -core_gui__page_prior=&3Prior page. +core_gui__page_next=&3Página siguiente. +core_gui__page_prior=&3Página anterior. # Note: The core_gui__page_tools_ messages all use the following placeholders # so you can structure them any way you need to. You not no have to use # any of them, but you can also use all of them. # {first_page} {prior_page} {current_page} {next_page} {last_page} -core_gui__page_tools_close=&3Close -core_gui__page_tools_go_back=&3Go Back -core_gui__page_tools_first_page=&3Prior page: {first_page} of {last_page} -core_gui__page_tools_prior_page=&3Prior page: {prior_page} of {last_page} -core_gui__page_tools_current_page=&3Current page: {current_page} of {last_page} -core_gui__page_tools_next_page=&3Next page: {next_page} of {last_page} -core_gui__page_tools_last_page=&3Last page: {last_page} of {last_page} +core_gui__page_tools_close=&3Cerrar +core_gui__page_tools_go_back=&3Volver +core_gui__page_tools_first_page=&3Página anterior: {first_page} de {last_page} +core_gui__page_tools_prior_page=&3Página anterior: {prior_page} de {last_page} +core_gui__page_tools_current_page=&3Página actual: {current_page} de {last_page} +core_gui__page_tools_next_page=&3Página siguiente: {next_page} de {last_page} +core_gui__page_tools_last_page=&3Última página: {last_page} de {last_page} -core_gui__money_earned=&3You earned &a$%1 -core_gui__price=&3Price: %1 -core_gui__confirm=&3Confirm: %1 %2 -core_gui__delay=&3Delay: %1 secs -core_gui__multiplier=&3Multiplier: x %1 -core_gui__value=&3Value: %1 -core_gui__permission=&3Permission: &7%1 -core_gui__prestige_name=&3Prestige name: %1 +core_gui__money_earned=&3Ganaste &a$%1 +core_gui__price=&3Precio: %1 +core_gui__confirm=&3Confirmar: %1 %2 +core_gui__delay=&3Retraso: %1 segs +core_gui__multiplier=&3Multiplicador: x %1 +core_gui__value=&3Valor: %1 +core_gui__permission=&3Permiso: &7%1 +core_gui__prestige_name=&3Nombre de prestigio: %1 @@ -215,9 +215,9 @@ core_gui__prestige_name=&3Prestige name: %1 # Important: Every [] must be paired with a value or it will produce a runtime error: # 'Incorrect number of parameters: [Format specifier %s] core_ranks_topn__player_line_1_header_format=[4] [-18] [-10] [11] [-8] [-12] -core_ranks_topn__player_line_1_header_values=Rank, Player, PreDefRanks, Balance, r-Score, Penalty +core_ranks_topn__player_line_1_header_values=Rango, Jugador, PreDefRanks, Balance, r-Score, Penalización core_ranks_topn__player_line_2_header_format=[4] [-10] [7] [-18] [9] -core_ranks_topn__player_line_2_header_values=Rank, Ranks, r-Score, Player, Balance +core_ranks_topn__player_line_2_header_values=Rango, Rangos, r-Score, Jugador, Balance # For detail_values you can use any of the following placeholders, but they must pair up # with the detail_format's []. @@ -232,3 +232,6 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. 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 10574cbf5..735000ce3 100644 --- a/prison-core/src/main/resources/lang/core/fi_FI.properties +++ b/prison-core/src/main/resources/lang/core/fi_FI.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=11 +messages__version=12 messages__auto_refresh=true @@ -232,3 +232,6 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. 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 a9d319fad..b45c2bd32 100644 --- a/prison-core/src/main/resources/lang/core/fr_FR.properties +++ b/prison-core/src/main/resources/lang/core/fr_FR.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=11 +messages__version=12 messages__auto_refresh=true @@ -232,3 +232,6 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. 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 7e4062aa0..85059ca8d 100644 --- a/prison-core/src/main/resources/lang/core/hu_HU.properties +++ b/prison-core/src/main/resources/lang/core/hu_HU.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=10 +messages__version=11 messages__auto_refresh=true @@ -232,3 +232,6 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. 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 1a2f28993..08f1fbe6e 100644 --- a/prison-core/src/main/resources/lang/core/it_IT.properties +++ b/prison-core/src/main/resources/lang/core/it_IT.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=10 +messages__version=11 messages__auto_refresh=true @@ -232,3 +232,6 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. 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 4ad3da75f..279e7f2d7 100644 --- a/prison-core/src/main/resources/lang/core/nl_BE.properties +++ b/prison-core/src/main/resources/lang/core/nl_BE.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=10 +messages__version=11 messages__auto_refresh=true @@ -232,4 +232,7 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. 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 88f1a3261..9421dca6a 100644 --- a/prison-core/src/main/resources/lang/core/nl_NL.properties +++ b/prison-core/src/main/resources/lang/core/nl_NL.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=10 +messages__version=11 messages__auto_refresh=true @@ -232,3 +232,6 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. 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 30f5072b9..3e2961b16 100644 --- a/prison-core/src/main/resources/lang/core/pt_PT.properties +++ b/prison-core/src/main/resources/lang/core/pt_PT.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=6 +messages__version=7 messages__auto_refresh=true @@ -232,3 +232,6 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. 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 aa7a2f680..ddf7ca06c 100644 --- a/prison-core/src/main/resources/lang/core/ro_RO.properties +++ b/prison-core/src/main/resources/lang/core/ro_RO.properties @@ -76,7 +76,7 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true @@ -232,4 +232,7 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. diff --git a/prison-core/src/main/resources/lang/core/zh-CN.properties b/prison-core/src/main/resources/lang/core/zh_CN.properties similarity index 60% rename from prison-core/src/main/resources/lang/core/zh-CN.properties rename to prison-core/src/main/resources/lang/core/zh_CN.properties index 6a036fd92..3e6715b95 100644 --- a/prison-core/src/main/resources/lang/core/zh-CN.properties +++ b/prison-core/src/main/resources/lang/core/zh_CN.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=9 +messages__version=12 messages__auto_refresh=true @@ -85,124 +85,124 @@ core_output__prefix_template_prison=监狱 core_output__prefix_template_info=ä¿¡æ¯ core_output__prefix_template_warning=警告 core_output__prefix_template_error=错误 -core_output__prefix_template_debug=Debug +core_output__prefix_template_debug=调试 core_output__color_code_info=&3 core_output__color_code_warning=&c core_output__color_code_error=&c 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 +core_output__error_startup_failure=监狱: (使用 System.err å‘é€, å›  Output.log 记录出现问题): +core_output__error_incorrect_number_of_parameters=日志记录失败 (%1): 字段数é‡ä¸æ­£ç¡®: [%2] 原信æ¯: [%3] 傿•°: %4 core_text__prefix=&3 core_text__just_now=现在 -core_text__ago=ä»¥å‰ -core_text__from_now=åŽ -core_text__and=å -core_text__time_units_prefix_spacer= ’Œ -core_text__time_units_singular=å¹´ã€æœˆã€å‘¨ã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ -core_text__time_units_plural=å¹´ã€æœˆã€å‘¨ã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ -core_text__time_units_short=å¹´ã€æœˆã€å‘¨ã€æ—¥ã€æ—¶ã€åˆ†ã€ç§’ +core_text__ago=å‰ +core_text__from_now=现在 +core_text__and=与 +core_text__time_units_prefix_spacer= +core_text__time_units_singular=å¹´,月,周,æ—¥,æ—¶,分,ç§’ +core_text__time_units_plural=å¹´,月,周,æ—¥,æ—¶,分,ç§’ +core_text__time_units_short=y,m,w,d,h,m,s -core_tokens__name_required=Prison Tokens=A player's name is required when used from console. -core_tokens__cannot_view_others_balances=Prison Tokens: You do not have permission to view other player's balances. -core_tokens__view_balance=&3%1 has %2 tokens. -core_tokens__add_invalid_amount=Prison Tokens: Invalid amount: '%1'. Must be greater than zero. -core_tokens__added_amount=&3%1 now has &7%2 &3tokens after adding &7%3&3. -core_tokens__removed_amount=&3%1 now has &7%2 &3tokens after removing &7%3&3. -core_tokens__set_amount=&3%1 now has &7%2 &3tokens. +core_tokens__name_required=Prison Tokens=åœ¨æŽ§åˆ¶å°æ‰§è¡Œè¯¥å‘½ä»¤æ—¶å¿…须输入玩家åç§°. +core_tokens__cannot_view_others_balances=监狱代å¸: 你没有æƒé™æŸ¥çœ‹å…¶ä»–玩家的余é¢. +core_tokens__view_balance=&3%1 拥有 %2 枚代å¸. +core_tokens__add_invalid_amount=监狱代å¸: æ•°é‡æ— æ•ˆ: '%1'. 需大于零. +core_tokens__added_amount=&3%1 获得了 &7%3&3 枚代å¸, 现在拥有 &7%2 &3枚代å¸. +core_tokens__removed_amount=&3%1 失去了 &7%3&3 枚代å¸, 现在拥有 &7%2 &3枚代å¸. +core_tokens__set_amount=&3%1 现在拥有 &7%2 &3枚代å¸. -core_runCmd__name_required=A valid player name is required. -core_runCmd__command_required=A command is required. +core_runCmd__name_required=请输入有效玩家åç§°. +core_runCmd__command_required=请输入有效命令. -core_prison_utf8_test=\u041F\u0440\u0438\u0432\u0435\u0442! \u0414\u0430\u0432\u0430\u0439 \u043F\u043E\u0441\u043C\u043E\u0442\u0440\u0438\u043C, \u0440\u0430\u0431\u043E\u0442\u0430\u0435\u0442 \u043B\u0438? Test 01 +core_prison_utf8_test=正在测试 UTF-8 ç¼–ç å…¼å®¹æ€§... 测试 01 # The following are the original messages and they will eventually be replaced. -includeError=[%1] 具有无效值 -excludeError=[%1] 具有无效值 -cantAsConsole=您ä¸èƒ½åœ¨æŽ§åˆ¶å°æ‰§è¡Œæ­¤æ“作 -missingArgument=æœªå®šä¹‰å‚æ•°[%1](它没有默认值) -missingFlagArgument=标志-%1æ²¡æœ‰æ‰€éœ€çš„å‚æ•° -undefinedFlagArgument=未定义标志-%2çš„å‚æ•°[%1] -internalErrorOccurred=å°è¯•执行此命令时å‘生内部错误 -noPermission=你缺少执行该命令的æƒé™ -blockParseError=傿•°[%1]䏿˜¯æœ‰æ•ˆçš„æ–¹å— -numberParseError=傿•°[%1]䏿˜¯æ•°å­— -numberTooLow=傿•°[%1]必须等于或大于%2 -numberTooHigh=傿•°[%1]必须等于或å°äºŽ%2 -numberRangeError=傿•°[%1]必须等于或大于%2且å°äºŽæˆ–等于%3 -tooFewCharacters=傿•°[%1]必须等于或大于%2 -tooManyCharacters=傿•°[%1]必须等于或å°äºŽ%2 -playerNotOnline=玩家%1ä¸åœ¨çº¿ -worldNotFound=找ä¸åˆ°ä¸–界%1 +includeError=[%1] 为无效值. +excludeError=[%1] 为无效值. +cantAsConsole=控制å°ä¸­ä¸èƒ½è¿™ä¹ˆåš. +missingArgument=傿•° [%1] 未定义 (无默认值). +missingFlagArgument=标志 -%1 缺少指定字段. +undefinedFlagArgument=标志 -%2 ç¼ºå°‘å‚æ•° [%1]. +internalErrorOccurred=执行命令时出现内部错误. +noPermission=你没有æƒé™æ‰§è¡Œè¿™ä¸ªå‘½ä»¤. +blockParseError=æ‰€ç»™å‚æ•° [%1] 䏿˜¯æœ‰æ•ˆæ–¹å—. +numberParseError=æ‰€ç»™å‚æ•° [%1] 䏿˜¯æœ‰æ•ˆæ•°å­—. +numberTooLow=æ‰€ç»™å‚æ•° [%1] å¿…é¡»ä¸å°äºŽ %2. +numberTooHigh=æ‰€ç»™å‚æ•° [%1] å¿…é¡»ä¸å¤§äºŽ %2. +numberRangeError=æ‰€ç»™å‚æ•° [%1] å¿…é¡»ä¸å°äºŽ %2 且ä¸å¤§äºŽ %3. +tooFewCharacters=æ‰€ç»™å‚æ•° [%1] å¿…é¡»ä¸å°äºŽ %2 个字符. +tooManyCharacters=æ‰€ç»™å‚æ•° [%1] å¿…é¡»ä¸å¤§äºŽ %2 个字符. +playerNotOnline=玩家 %1 ä¸åœ¨çº¿. +worldNotFound=世界 %1 ä¸å­˜åœ¨. -core_gui__click_to_decrease=&3点击å‡å°‘ -core_gui__click_to_increase=&3点击增加 +core_gui__click_to_decrease=&3点击å‡å°‘. +core_gui__click_to_increase=&3点击增加. -core_gui__click_to_cancel=&3å•击以喿¶ˆã€‚ -core_gui__click_to_close=&3å•击以关闭 -core_gui__click_to_confirm=&3点击确认 -core_gui__click_to_delete=&3å•击以删除 -core_gui__click_to_disable=&3å•击以ç¦ç”¨ -core_gui__click_to_edit=&3点击编辑 -core_gui__click_to_enable=&3å•击以å¯ç”¨ -core_gui__click_to_open=&3å•击打开 +core_gui__click_to_cancel=&3ç‚¹å‡»å–æ¶ˆ. +core_gui__click_to_close=&3点击关闭. +core_gui__click_to_confirm=&3点击确认. +core_gui__click_to_delete=&3点击删除. +core_gui__click_to_disable=&3点击ç¦ç”¨. +core_gui__click_to_edit=&3点击编辑. +core_gui__click_to_enable=&3点击å¯ç”¨. +core_gui__click_to_open=&3点击打开. -core_gui__left_click_to_confirm=&3左键å•击确认 -core_gui__left_click_to_reset=&3左键å•击以é‡ç½® -core_gui__left_click_to_open=&3左键å•击打开 -core_gui__left_click_to_edit=&3左键å•击进行编辑 +core_gui__left_click_to_confirm=&3左键点击确认. +core_gui__left_click_to_reset=&3左键点击é‡ç½®. +core_gui__left_click_to_open=&3左键点击打开. +core_gui__left_click_to_edit=&3左键点击编辑. -core_gui__right_click_to_cancel=&3å³é”®å•击以喿¶ˆ -core_gui__right_click_to_delete=&3å³é”®å•击以删除 -core_gui__right_click_to_disable=&3å³é”®å•击以ç¦ç”¨ -core_gui__right_click_to_enable=&3å³é”®å•击以å¯ç”¨ -core_gui__right_click_to_toggle=&3å³é”®å•å‡»ä»¥åˆ‡æ¢ +core_gui__right_click_to_cancel=&3å³é”®ç‚¹å‡»å–消. +core_gui__right_click_to_delete=&3å³é”®ç‚¹å‡»åˆ é™¤. +core_gui__right_click_to_disable=&3å³é”®ç‚¹å‡»ç¦ç”¨. +core_gui__right_click_to_enable=&3å³é”®ç‚¹å‡»å¯ç”¨. +core_gui__right_click_to_toggle=&3å³é”®ç‚¹å‡»åˆ‡æ¢. -core_gui__right_click_and_shift_to_delete=&3å³é”®å•击并按ä½shift键以删除 -core_gui__right_click_and_shift_to_disable=&3å³é”®å•击并按ä½shift键以ç¦ç”¨ -core_gui__right_click_and_shift_to_toggle=&3å³é”®å•击并按ä½shifté”®åˆ‡æ¢ +core_gui__right_click_and_shift_to_delete=&3Shift+å³é”®ç‚¹å‡»åˆ é™¤. +core_gui__right_click_and_shift_to_disable=&3Shift+å³é”®ç‚¹å‡»ç¦ç”¨. +core_gui__right_click_and_shift_to_toggle=&3Shift+å³é”®ç‚¹å‡»åˆ‡æ¢. -core_gui__page_next=&3下一页 -core_gui__page_prior=&3上一页 +core_gui__page_next=&3下一页. +core_gui__page_prior=&3上一页. # Note: The core_gui__page_tools_ messages all use the following placeholders # so you can structure them any way you need to. You not no have to use # any of them, but you can also use all of them. # {first_page} {prior_page} {current_page} {next_page} {last_page} -core_gui__page_tools_close=&3Close -core_gui__page_tools_go_back=&3Go Back -core_gui__page_tools_first_page=&3Prior page: {first_page} of {last_page} -core_gui__page_tools_prior_page=&3Prior page: {prior_page} of {last_page} -core_gui__page_tools_current_page=&3Current page: {current_page} of {last_page} -core_gui__page_tools_next_page=&3Next page: {next_page} of {last_page} -core_gui__page_tools_last_page=&3Last page: {last_page} of {last_page} +core_gui__page_tools_close=&3关闭 +core_gui__page_tools_go_back=&3返回 +core_gui__page_tools_first_page=&3已是首页: 第 {first_page} 页, å…± {last_page} 页 +core_gui__page_tools_prior_page=&3上一页: 第 {prior_page} 页, å…± {last_page} 页 +core_gui__page_tools_current_page=&3当å‰é¡µ: 第 {current_page} 页, å…± {last_page} 页 +core_gui__page_tools_next_page=&3下一页: 第 {next_page} 页, å…± {last_page} 页 +core_gui__page_tools_last_page=&3已是末页: 第 {last_page} 页, å…± {last_page} 页 -core_gui__money_earned=&3You earned &a$%1 -core_gui__price=&3价格:%1 -core_gui__confirm=&3确认:%1%2 -core_gui__delay=&3延迟:%1ç§’ -core_gui__multiplier=&3倿•°ï¼šx%1 -core_gui__value=&3值:%1 -core_gui__permission=&3æƒé™ï¼š&7%1 -core_gui__prestige_name=&3声望å称:%1 +core_gui__money_earned=&3你获得了 &a$%1 +core_gui__price=&3ä»·æ ¼: %1 +core_gui__confirm=&3确认: %1 %2 +core_gui__delay=&3延迟: %1 ç§’ +core_gui__multiplier=&3å€çއ: x %1 +core_gui__value=&3值: %1 +core_gui__permission=&3æƒé™: &7%1 +core_gui__prestige_name=&3特æƒå: %1 @@ -215,9 +215,9 @@ core_gui__prestige_name=&3声望å称:%1 # Important: Every [] must be paired with a value or it will produce a runtime error: # 'Incorrect number of parameters: [Format specifier %s] core_ranks_topn__player_line_1_header_format=[4] [-18] [-10] [11] [-8] [-12] -core_ranks_topn__player_line_1_header_values=Rank, Player, PreDefRanks, Balance, r-Score, Penalty +core_ranks_topn__player_line_1_header_values=等级, 玩家, 等级, ä½™é¢, 分数, 惩罚 core_ranks_topn__player_line_2_header_format=[4] [-10] [7] [-18] [9] -core_ranks_topn__player_line_2_header_values=Rank, Ranks, r-Score, Player, Balance +core_ranks_topn__player_line_2_header_values=等级, 等级, 分数, 玩家, ä½™é¢ # For detail_values you can use any of the following placeholders, but they must pair up # with the detail_format's []. @@ -232,4 +232,6 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} - +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. 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 d8daac534..5eaa9056a 100644 --- a/prison-core/src/main/resources/lang/core/zh_TW.properties +++ b/prison-core/src/main/resources/lang/core/zh_TW.properties @@ -76,7 +76,7 @@ # like to share, please contact a staff member on our Discord server. #Thanks for your contributions! # -messages__version=10 +messages__version=11 messages__auto_refresh=true @@ -232,4 +232,7 @@ core_ranks_topn__player_line_2_detail_format= [-3] [-10] [7] [-18] [9] core_ranks_topn__player_line_2_detail_values={rankPosition}, {prestigeDefaultRankTagNoColor}, {rankScore}, {playerName}, {balanceKmbt} +## Please note there is another similar message in the spigot module: +## spigot_minebombs__cooldown_delay +core_minebombs__cooldown_delay=You cannot use another Prison Mine Bomb for %1 seconds. 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 502cddbd9..fd9b8aa12 100644 --- a/prison-core/src/main/resources/lang/mines/de_DE.properties +++ b/prison-core/src/main/resources/lang/mines/de_DE.properties @@ -105,4 +105,4 @@ mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport reques mines_mtp__player_must_be_in_game=You can only teleport players that are online and in the game. mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. -mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? +mines_mtp__teleport_failed=&3Teleport failed. Are you sure you're a Player? 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 b21d897fe..4ddf1717b 100644 --- a/prison-core/src/main/resources/lang/mines/en_US.properties +++ b/prison-core/src/main/resources/lang/mines/en_US.properties @@ -60,7 +60,7 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true @@ -90,6 +90,7 @@ spawn_set=&7The mine spawnpoint has been set. spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7The &cspawnpoint &7must be in the same &cworld &7as the mine. not_a_block=&c%1 &7is not a block. +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7That block has already been added to the mine. mine_full=&cThe mine will be too full. &7Try lowering the percentage of this block and/or other blocks in the mine to make some room. block_added=&7Added block &3%1 &7to mine &3%2&7. @@ -106,4 +107,4 @@ mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport reques mines_mtp__player_must_be_in_game=You can only teleport players that are online and in the game. mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. -mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? +mines_mtp__teleport_failed=&3Teleport failed. Are you sure you're a Player? 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 e2baf94f9..2f7de6a62 100644 --- a/prison-core/src/main/resources/lang/mines/es_ES.properties +++ b/prison-core/src/main/resources/lang/mines/es_ES.properties @@ -60,13 +60,9 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true - - -# The following are the original messages and they will eventually be replaced. - reset_warning=&7Todas las minas %1 se reiniciarán en &3%2&7. reset_message=&7Todas las minas %1 han sido reiniciadas. skip_reset_message= @@ -90,6 +86,7 @@ spawn_set=&7El punto de aparición (spawnpoint) de la mina ha sido definid. spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7El &cpunto de aparición &7debe estar en el mismo &cmundo &7que la mina. not_a_block=&c%1 &7no es un bloque. +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7Ese bloque ya ha sido añadido a la mina. mine_full=&cLa mina estará demasiado llena. &7Intenta reduciendo el porcentaje de este bloque y/u otros bloques en la mina para hacer más espacio. block_added=&7Se ha añadido el bloque &3%1 &7a la mina &3%2&7. @@ -99,10 +96,10 @@ block_deleted=&7Se ha eliminado el bloque &3%1 &7de la mina &3%2&7. mine_redefined=&7Se ha &3redefinido &7la mina exitosamente. missing_world=&7El mundo en el que se ha creado la mina no se ha podido encontrar. -mines_mtp__unable_to_teleport=Sorry. You're unable to teleport there. -mines_mtp__unable_to_teleport_others=&3You cannot teleport other players to a mine. Ignoring parameter. -mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport request with a mine name. -mines_mtp__player_must_be_in_game=You can only teleport players that are online and in the game. -mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. -mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. -mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? +mines_mtp__unable_to_teleport=Lamentablemente, no puedes teletransportarte allí. +mines_mtp__unable_to_teleport_others=&3No puedes teletransportar a otros jugadores a una mina. Ignorando parámetro. +mines_mtp__no_target_mine_found=No se ha encontrado una mina objetivo. &3Vuelve a enviar la solicitud de teletransporte con un nombre de mina. +mines_mtp__player_must_be_in_game=Sólo puedes teletransportar a jugadores que estén en línea y en el juego. +mines_mtp__player_must_be_in_game=&3El jugador especificado no está en el juego, por lo que no se puede teletransportar. +mines_mtp__cannot_use_virtual_mines=&cOpción inválida. Esta mina es una mina virtual&7. Utiliza &a/mines set area &7para habilitar la mina. +mines_mtp__teleport_failed=&3Fallo en el teletransporte. ¿Estás seguro de que eres un jugador? \ No newline at end of file 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 a17a07eae..d29b4e55c 100644 --- a/prison-core/src/main/resources/lang/mines/fi_FI.properties +++ b/prison-core/src/main/resources/lang/mines/fi_FI.properties @@ -60,7 +60,7 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true @@ -90,6 +90,7 @@ spawn_set=&7Mainin spawni on asetettu. spawn_removed=&7Mainin spawni on onnistuneesti poistettu. spawnpoint_same_world=&cspawnpoint &7pitää olla samassa mailmassa kuin maini. not_a_block=&c%1 &7ei ole blockki. +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7Tämä blockki on jo lisätty mainiin.. mine_full=&cMaini on jo täynnä. block_added=&7Lisätty &3%1 &7mainiin &3%2&7. 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 fccacf7cb..4cc5ac32d 100644 --- a/prison-core/src/main/resources/lang/mines/fr_FR.properties +++ b/prison-core/src/main/resources/lang/mines/fr_FR.properties @@ -60,7 +60,7 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true @@ -89,7 +89,8 @@ mine_does_not_exist=&7Une mine du même nom existe déjà. spawn_set=&7Le point de spawn de la mine a été défini. spawn_removed=&7Le point de spawn de la mine a été supprimé. spawnpoint_same_world=&7Le &cpoint de spawn &7doit être dans le même &cmonde &7que la mine. -not_a_block=&c%1 &7n'est pas un bloc. +not_a_block=&c%1 &7n'est pas un bloc.. +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7Ce bloc a déjà été ajouté dans la mine. mine_full=&cCette mine sera trop remplie. &7Essaye de réduire le percentage de ce block ou d'un autre dans la mine pour faire de la place. block_added=&7Le bloc &3%1 &7a été ajoutée à la mine &3%2&7. 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 cd2424220..6ef77b837 100644 --- a/prison-core/src/main/resources/lang/mines/hu_HU.properties +++ b/prison-core/src/main/resources/lang/mines/hu_HU.properties @@ -60,7 +60,7 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true @@ -90,6 +90,7 @@ spawn_set=&7A bánya spawnpontja beállítva. spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7A &cspawnpont-nak&7 ugyanabban a &cvilágban&7 bányában kell lennie. not_a_block=&c%1 &7nem egy blokk. +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7Ez a blokk már felkerült a bányába. mine_full=&cA bánya túlságosan tele lesz. &7Jobban próbáld csökkenteni a blokk és/vagy más blokkok százalékos arányát a bányában. block_added=&7A blokk hozzáadva &3%1 &7a(z) &3%2&7 bányához. @@ -105,4 +106,4 @@ mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport reques mines_mtp__player_must_be_in_game=You can only teleport players that are online and in the game. mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. -mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? +mines_mtp__teleport_failed=&3Teleport failed. Are you sure you're a Player? 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 2c5b126ff..06213227e 100644 --- a/prison-core/src/main/resources/lang/mines/it_IT.properties +++ b/prison-core/src/main/resources/lang/mines/it_IT.properties @@ -60,7 +60,7 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true @@ -90,6 +90,7 @@ spawn_set=&7Il punto di spawn della miniera è stato settato. spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7Il &cPunto di spawn &7deve essere nello stesso &cmondo &7della miniera. not_a_block=&c%1 &7non è un blocco. +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7Quel blocco è già stato aggiunto alla miniera. mine_full=&cLa miniera con quel valore supera il limite. &7Prova ad abbassare la percentuale di questo blocco e / o altri blocchi nella miniera per fare spazio. block_added=&7Aggiunto il blocco &3%1 &7alla miniera &3%2&7. @@ -105,4 +106,4 @@ mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport reques mines_mtp__player_must_be_in_game=You can only teleport players that are online and in the game. mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. -mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? +mines_mtp__teleport_failed=&3Teleport failed. Are you sure you're a Player? 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 41c35aa61..a3464ed54 100644 --- a/prison-core/src/main/resources/lang/mines/nl_BE.properties +++ b/prison-core/src/main/resources/lang/mines/nl_BE.properties @@ -60,7 +60,7 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true @@ -88,6 +88,7 @@ spawn_set=&7De mijn zijn startpunt is gezet. spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7Het startpunt moet in dezelfde wereld als de mijn zijn . not_a_block=&c%1 &7is geen blok. +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7Deze blok is al in de mijn toegevoegd. mine_full=&cDe mijn zal te vol worden. &7Probeer het precentage te verlagen van deze blok en/of andere bloken in de mijn om plaats te maken. block_added=&7blok &3%1 &7bijgevoeg &7bij mijn &3%2&7. @@ -103,4 +104,4 @@ mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport reques mines_mtp__player_must_be_in_game=You can only teleport players that are online and in the game. mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. -mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? +mines_mtp__teleport_failed=&3Teleport failed. Are you sure you're a Player? 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 b93443167..b40f54a17 100644 --- a/prison-core/src/main/resources/lang/mines/nl_NL.properties +++ b/prison-core/src/main/resources/lang/mines/nl_NL.properties @@ -60,7 +60,7 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true @@ -88,6 +88,7 @@ spawn_set=&7De mijn zijn startpunt is gezet. spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7Het startpunt moet in dezelfde wereld als de mijn zijn . not_a_block=&c%1 &7is geen blok. +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7Deze blok is al in de mijn toegevoegd. mine_full=&cDe mijn zal te vol worden. &7Probeer het precentage te verlagen van deze blok en/of andere bloken in de mijn om plaats te maken. block_added=&7blok &3%1 &7bijgevoeg &7bij mijn &3%2&7. @@ -103,4 +104,4 @@ mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport reques mines_mtp__player_must_be_in_game=You can only teleport players that are online and in the game. mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. -mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? +mines_mtp__teleport_failed=&3Teleport failed. Are you sure you're a Player? 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 af7aa2c7b..0ef4465f9 100644 --- a/prison-core/src/main/resources/lang/mines/pt_PT.properties +++ b/prison-core/src/main/resources/lang/mines/pt_PT.properties @@ -60,7 +60,7 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true @@ -90,6 +90,7 @@ spawn_set=&7O spawnpoint da mina foi defenido. spawn_removed=&7O spawnpoint da mina foi eliminado. spawnpoint_same_world=&7O &cspawnpoint &7tem de ser no mesmo &cmundo &7que a mina. not_a_block=&c%1 &7não é um bloco. +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7Esse bloco já foi adicionado à mina. mine_full=&cA mina vai estar cheia demais. &7Tenta baixa a precentagem deste bloco e/ou outros blocos dentro da mina para fazer espaço. block_added=&7Bloco adicionado &3%1 &7á mina &3%2&7. 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 cfb6d17c9..0c2169975 100644 --- a/prison-core/src/main/resources/lang/mines/ro_RO.properties +++ b/prison-core/src/main/resources/lang/mines/ro_RO.properties @@ -60,7 +60,7 @@ # -messages__version=5 +messages__version=6 messages__auto_refresh=true @@ -90,6 +90,7 @@ spawn_set=&7Spawnpoint-ul minei a fost setat. spawn_removed=&7Spawnpoint-ul minei a fost È™ters. spawnpoint_same_world=&cSpawnpoint-ul &7trebuie să fie în aceeaÈ™i &clume &7cu mina. not_a_block=&c%1 &7nu este un block. +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7Acel block a fost adăugat deja în mină. mine_full=&cMina va fi prea plină. &7ÃŽncearcă să scazi È™ansele apariÈ›iei acestui block È™i/sau altor block-uri din mină pentru a avea mai mult spaÈ›iu. block_added=&7Block-ul &3%1 &7a fost adăugat în mina &3%2&7. @@ -106,4 +107,4 @@ mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport reques mines_mtp__player_must_be_in_game=You can only teleport players that are online and in the game. mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. -mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? +mines_mtp__teleport_failed=&3Teleport failed. Are you sure you're a Player? 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 d5e632a9b..3259e89a6 100644 --- a/prison-core/src/main/resources/lang/mines/zh-CN.properties +++ b/prison-core/src/main/resources/lang/mines/zh-CN.properties @@ -60,7 +60,7 @@ # -messages__version=4 +messages__version=6 messages__auto_refresh=true @@ -89,7 +89,8 @@ mine_does_not_exist=&7没有å«è¿™ä¸ªå字的矿区 spawn_set=&7矿区出生点已设置 spawn_removed=&7矿区出生点已移除 spawnpoint_same_world=&7&c出生点&7必须与矿区ä½äºŽåŒä¸€ä¸ª&c世界&7中 -not_a_block=&c%1 &7䏿˜¯ä¸€ä¸ªæ–¹å—,请检查拼写 +not_a_block=&c%1 &7䏿˜¯ä¸€ä¸ªæ–¹å—,请检查拼å +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7该方å—å·²æˆåŠŸæ·»åŠ åˆ°çŸ¿åŒºä¸­ mine_full=&c矿区满了 &7试ç€é™ä½Žè¯¥æ–¹å—或其他方å—的百分比,以腾出一些空间 block_added=&7将方å—&3%1 &7添加到矿区&3%2&7. 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 78a6e3e5d..045bf9d92 100644 --- a/prison-core/src/main/resources/lang/mines/zh_TW.properties +++ b/prison-core/src/main/resources/lang/mines/zh_TW.properties @@ -60,7 +60,7 @@ # -messages__version=6 +messages__version=7 messages__auto_refresh=true @@ -89,7 +89,8 @@ mine_does_not_exist=&7此礦場å稱並ä¸å­˜åœ¨ spawn_set=&7礦場出生點 å·²æˆåŠŸ 設定 spawn_removed=&7The mine spawnpoint has been removed. spawnpoint_same_world=&7這個 &c出生點 &7必須與其他 礦場 在åŒä¸€å€‹ &c世界 -not_a_block=&c%1 &7䏿˜¯ä¸€å€‹æ–¹å¡Š +not_a_block=&c%1 &7䏿˜¯ä¸€å€‹æ–¹å¡ +not_a_block_sellall=&c%1 &7is not a block that can be used in mines. Its only for sellall usage. block_already_added=&7此方塊已經被新增到礦場 mine_full=&c此礦場已經滿了。 &7è«‹é™ä½Žç¤¦å ´ä¸­è©²æ–¹å¡Šæˆ–其他方塊的 百分比 以騰出更多空間 block_added=&7將方塊 &3%1 &7加入到礦場 &3%2&7 @@ -106,4 +107,4 @@ mines_mtp__no_target_mine_found=No target mine found. &3Resubmit teleport reques mines_mtp__player_must_be_in_game=You can only teleport players that are online and in the game. mines_mtp__player_must_be_in_game=&3Specified player is not in the game so they cannot be teleported. mines_mtp__cannot_use_virtual_mines=&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine. -mines_mtp__teleport_failed=&3Telport failed. Are you sure you're a Player? +mines_mtp__teleport_failed=&3Teleport failed. Are you sure you're a Player? 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 9807416d3..2c1ec8c57 100644 --- a/prison-core/src/main/resources/lang/ranks/en_US.properties +++ b/prison-core/src/main/resources/lang/ranks/en_US.properties @@ -72,7 +72,7 @@ ## be able to enable them. -messages__version=29 +messages__version=30 messages__auto_refresh=true ranks_rankup__rankup_no_player_name=You have @@ -94,6 +94,7 @@ ranks_rankup__rankup_no_ranks=There are no ranks in this ladder. ranks_rankup__rankup_rank_does_not_exist=The rank %1 does not exist on this server. ranks_rankup__rankup_rank_is_not_in_ladder=The rank %1 does not exist in the ladder %2. ranks_rankup__rankup_currency_is_not_supported=The currency, %1, is not supported by any loaded economies. +ranks_rankup__rankup_economy_failed=Failed to adjust player's balance. Could be an issue with vault or a cache timing issue. Try again. ranks_rankup__rankup_ladder_removed=The ladder %1 was removed. ranks_rankup__rankup_failure_removing_ladder=Rankup failed since the player could not be removed from the ladder %1. (Players cannot be removed from the 'default' ladder). ranks_rankup__rankup_in_progress_failure=Rankup failed to complete normally. No status was set. diff --git a/prison-core/src/main/resources/lang/ranks/es_ES.properties b/prison-core/src/main/resources/lang/ranks/es_ES.properties new file mode 100644 index 000000000..077a4aaf7 --- /dev/null +++ b/prison-core/src/main/resources/lang/ranks/es_ES.properties @@ -0,0 +1,343 @@ + # NOTE: A messages__version is an arbitrary integer that will be manually incremented within Prison +# when there are changes to these messages. This value represents when message content is +# changed, fixed, or added to. This value may not be increased if the change is very small and +# insignificant, such as a space or a couple of letters. +# +# messages__auto_refresh=true indicates that this file will automatically be replaced if +# Prison detects a messages__version difference. The old file will be deleted (renamed) and +# a new copy will be placed in the directory to be used. If this value is set to false, then +# Prison will not refresh this file and there could be issues with the display of other messages. +# If auto refresh is set to false, we are not held responsible for possible issues that can +# arise from inaccurate messages. If set to false, then you are responsible for maintaining +# the messages on your own. +# +# If you make changes to this file, and you have messages__auto_refresh=false, then those +# changes will be replaced when this file is updated. Since the old file is renamed, and +# not deleted, you can manually merge your changes back in to the new update. The old +# renamed files will never be deleted by prison; you can remove them when you feel like it +# is safe to do so. +# +# 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 +# like to share, please contact a staff member on our Discord server. +#Thanks for your contributions! +# + +## +## Prison Supports Unicode (UTF-8) encoding in these properties files. BUt you must +## follow these instructions to ensure everything works properly. +## +## 1. You should only edit these files using a UTF-8 editor. On windows use NotePad, not WordPad. +## WordPad will save as plain text. To confirm the save was successful: save, close the editor, +## then reopen to confirm the encoding was preserved. +## +## 2. When running on Windows, you must enable utf-8 encoding in minecraft's console. Windows +## defaults to a characterpage 1252. To enable window's use of utf-8, you need to change the +## encoding prior to launching spigot/paper: +## chcp 65001 +## +## Full example of a windows script, which hooks for java debugging: +## rem Note: chcp 65001 enables utf-8 in windows, when normally windows uses characterpage 1252 +## chcp 65001 +## java -Dfile.encoding="UTF-8" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -Xms1g -Xmx4g -jar spigot-1.8.8.jar nogui --log-strip-color +## pause +## +## 3. When viewing the logs/latest.log files you must use an editor such as NotePad instead of WordPad. +## +## 4. Unicode is properly displayed in game, in console, in the logs, and with paste.helpch.at when using +## /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}'. +# + +## NOTE: Prison now supports the use of secondary placeholders on all "player" related messages. +## Just add these placeholders, in any position, combination, or quantity, to any +## message's text. +## {player} {rank_default} {rank_tag_default} {rank_next_default} {rank_next_tag_default} +## {rank_prestiges} {rank_tag_prestiges} {rank_next_prestiges} {rank_next_tag_prestiges} +## Player based messages are generally messages sent to player. Not all messages are able +## to support these secondary placeholders; if you find one that is not supported, please +## contact RoyalBlueRanger in a support thread on the Prison discord server and I may +## be able to enable them. + + +messages__version=29 +messages__auto_refresh=true + +ranks_rankup__rankup_no_player_name=Tienes +ranks_rankup__rankup_no_player_name_broadcast=Alguien +ranks_rankup__rankup_you_are=Tú eres +ranks_rankup__rankup_success=¡Felicidades! %1 subió de rango a '%2'. %3 +ranks_rankup__demote_success=Desafortunadamente, %1 ha sido degradado a rango '%2'. %3 +ranks_rankup__log_rank_change=%1 inició el cambio de rango: %2 +ranks_rankup__rankup_cant_afford=¡No tienes suficiente dinero para subir de rango! El siguiente rango cuesta %1%2. +ranks_rankup__rankup_lowest=%1 ya está en el rango más bajo! +ranks_rankup__rankup_highest=%1 ya está en el rango más alto! +ranks_rankup__rankup_failure=Fallo genérico al subir de rango. Revise los detalles de la subida de rango para identificar la razón. +ranks_rankup__rankup_failed_to_load_player=Error al cargar el jugador. +ranks_rankup__rankup_failed_to_load_ladder=Error al cargar la escalera. +ranks_rankup__rankup_failed_to_assign_rank=Error al asignar un rango. Revise los detalles de la subida de rango para identificar la razón. +ranks_rankup__rankup_failed_to_assign_rank_with_refund=Error al asignar un rango. Revise los detalles de la subida de rango para identificar la razón. Se han aplicado reembolsos. +ranks_rankup__rankup_failed_to_save_player_file=Error al recuperar o escribir datos. Sus archivos pueden estar dañados. Alerta a un administrador del servidor. +ranks_rankup__rankup_no_ranks=No hay rangos en esta escalera. +ranks_rankup__rankup_rank_does_not_exist=El rango %1 no existe en este servidor. +ranks_rankup__rankup_rank_is_not_in_ladder=El rango %1 no existe en la escalera %2. +ranks_rankup__rankup_currency_is_not_supported=La moneda, %1, no es compatible con ninguna economía cargada. +ranks_rankup__rankup_ladder_removed=La escalera %1 fue eliminada. +ranks_rankup__rankup_failure_removing_ladder=La subida de rango falló porque el jugador no pudo ser eliminado de la escalera %1. (Los jugadores no pueden ser eliminados de la escalera 'default'). +ranks_rankup__rankup_in_progress_failure=La subida de rango no pudo completarse normalmente. No se estableció ningún estado. + +ranks_rankup__rankup_failure_to_get_rankplayer=¡No existes! El servidor no tiene registros tuyos. Intenta unirte de nuevo, o contacta a un administrador del servidor para obtener ayuda. +ranks_rankup__rankup_failure_invalid_ladder=La escalera '%1' no existe. +ranks_rankup__rankup_failure_must_be_online_player=&3Debes ser un jugador en el juego para ejecutar este comando, y/o el jugador debe estar en línea. +ranks_rankup__no_permission=Necesitas el permiso '%1' para subir de rango en esta escalera. +ranks_rankup__cannot_run_from_console=&7No se puede ejecutar la subida de rango desde la consola. Consulta &3/rankup help&7. +ranks_rankup__invalid_player_name=&7Nombre de jugador no válido. '%1' +ranks_rankup__internal_failure=&7Modo de subida de rango no válido. Fallo interno. Por favor, informa. +ranks_rankup__error_no_default_ladder=&c[ERROR] ¡No hay una escalera predeterminada! ¡Por favor, informa esto a un administrador! +ranks_rankup__error_no_lower_rank=&c[ERROR] ¡No se puede obtener el rango más bajo! ¡Por favor, informa esto a un administrador! + +ranks_rankup__error_no_ladder=&c[ERROR] ¡La escalera %1 no existe! ¡Por favor, informa esto a un administrador! +ranks_rankup__error_no_lower_rank_on_ladder=&c[ERROR] ¡La escalera %1 no tiene rangos! ¡Por favor, informa esto a un administrador! + +ranks_rankup__error_player_not_on_default_ladder=&c[ERROR] El jugador no está en la escalera predeterminada. Jugador: %1 +ranks_rankup__not_at_last_rank=&c¡No estás en el último rango! +ranks_rankup__at_last_rank=&c¡Estás en el último rango! +ranks_rankup__not_able_to_prestige=&7[&3Lo siento&7] &3No pudiste &6Prestigiar! +ranks_rankup__not_able_to_reset_rank=&7No se puede restablecer tu rango en la escalera predeterminada. + +ranks_rankup__balance_set_to_zero=&7Tu saldo se ha establecido en cero. +ranks_rankup__prestige_successful=&7[&3Felicidades&7] &3Has &6Prestigiado&3 a %1&c! +ranks_rankup__prestige_failure=&7[&3Lo siento&7] &3No pudiste &6Prestigiar&3 a %1&c! +ranks_rankup__confirm_prestige_line_1=&3Confirmar Prestigio: %1 +ranks_rankup__confirm_prestige_line_2=&3 Costo: &7%1 +ranks_rankup__confirm_prestige_line_3=&3 Saldo: &7%1%2 +ranks_rankup__confirm_prestige_line_4=&3 El rango predeterminado se restablecerá. +ranks_rankup__confirm_prestige_line_5=&3 El saldo se restablecerá. +ranks_rankup__confirm_prestige_line_6=&3Confirmar con el comando: '&7/prestige %1confirm&3' +ranks_rankup__confirm_prestige_line_7=&3Confirmar haciendo clic en el bloque verde + +ranks_rankup__invalid_charge_value=&3Valor no válido para chargePlayer. Los valores válidos son: %1 %2 +ranks_rankup__invalid_refund_value=&3Valor no válido para refundPlayer. Los valores válidos son: %1 %2 + +ranks_rankutil__failure_internal=Fallo al realizar la comprobación de rankupPlayerInternal, revisa los registros del servidor para ver la traza de la pila: %1 +ranks_rankutil__failure_saving_player_data=Se produjo un error al guardar los archivos de jugador. + +ranks_firstJoinHandler__no_ranks_on_server=¡No hay rangos en el servidor! El nuevo jugador no tiene rango. +ranks_firstJoinHandler__could_not_save_player=No se pudieron guardar los archivos del jugador. +ranks_firstJoinHandler__success=¡Bienvenido! %1 acaba de unirse al servidor y se le asignó el rango predeterminado. + +ranks_prisonRanks__failure_no_economy_status=&cSin plugin de economía +ranks_prisonRanks__failure_no_economy=PrisonRanks.enable() - Falló - No hay un plugin de economía activo - %1 +ranks_prisonRanks__failure_loading_ranks_status=&cError al cargar los archivos de rango: %1 +ranks_prisonRanks__failure_loading_ranks=Error al cargar un archivo de rango. %1 +ranks_prisonRanks__failure_loading_ladders_status=&cError al cargar los archivos de escalera: %1 +ranks_prisonRanks__failure_loading_ladders=Error al cargar un archivo de escalera. %1 +ranks_prisonRanks__failure_loading_players_status=&cError al cargar los archivos de jugador: %1 +ranks_prisonRanks__failure_loading_players=Error al cargar un archivo de jugador. %1 +ranks_prisonRanks__failed_loading_players=&cError al cargar los jugadores: %1 +ranks_prisonRanks__failed_to_load_player_file=Error al cargar un archivo de jugador. %1 + +ranks_prisonRanks__status_loaded_ranks=Se cargaron %1 rangos en total. rangos predeterminados: %2 rangos de prestigio: %3 otros rangos: %4 +ranks_prisonRanks__status_loaded_ladders=Se cargaron %1 escaleras. +ranks_prisonRanks__status_loaded_players=Se cargaron %1 jugadores. + +ranks_prisonRanks__failure_with_ladder=&cError al %1 una nueva escalera de %2, no se pudo encontrar ninguna preexistente. +ranks_prisonRanks__failure_with_ladder_create=crear +ranks_prisonRanks__failure_with_ladder_save=guardar +ranks_prisonRanks__failure_with_ladder_default=predeterminada +ranks_prisonRanks__failure_with_ladder_prestiges=prestigios + +ranks_prisonRanks__added_new_player=&7Prisión: &cNuevo jugador añadido &7a la prisión: &3%1 &7fue encontrado en el servidor. +ranks_prisonRanks__added_and_fixed_players=Cargador de rango de prisión: Se añadieron %1 jugadores a la prisión. Se corrigieron %2 jugadores que no tenían un rango en la escalera predeterminada. + +ranks_rank__failure_loading_ranks=&aError: Cargando Rangos! &7Excepción al analizar documentos de rango. Id de rango= %1 nombre= %2 [%3] + +ranks_rankManager__failure_loading_rankManager=&aError: al cargar la escalera %1 (id de escalera: %2): &7No se pudo cargar el RankManager, por lo que no se puede acceder a ningún rango. +ranks_rankManager__failure_duplicate_rank=&aError: Fallo al cargar la escalera de Rank: El rango '%1' ya estaba vinculado a la escalera '%2', pero se intentó agregar a la escalera '%3'. Este rango no estará vinculado a la escalera '%4' + +ranks_rankManager__remove_rank_warning=Advertencia de eliminación de rango: No existe un rango de respaldo, por lo que los jugadores con el rango que se está eliminando no tendrán ningún rango en esa escalera. +ranks_rankManager__cannot_save_player_file=RemoveRank: No se pudo guardar el archivo del jugador. +ranks_rankManager__player_is_now=El jugador %1 es ahora %2 +ranks_rankManager__cannot_save_ladder_file=RemoveRank: No se pudo guardar la escalera %1. +ranks_rankManager__failure_no_economy=Fallo de economía: &7La moneda &a%1&7 fue registrada con el rango &a%2&7, pero no es compatible con ninguna integración de economía. +ranks_rankManager__ranks_by_ladders=&7Rangos por escaleras: + +ranks_ladderManager__cannot_save_ladder_file=&cLadderManager.saveLadder: No se pudo guardar la escalera. &7%1 &3Error= [&7%2&3]" + +ranks_playerManager__cannot_save_player_file=Se produjo un error al guardar los archivos de jugador: %1 +ranks_playerManager__cannot_add_new_player=PlayerManager.getPlayer(): Error al añadir el nuevo nombre de jugador: %1. %2 +ranks_playerManager__cannot_save_new_player_file=Error al crear un nuevo archivo de datos de jugador para el jugador %1 nombre de archivo de destino: %2 +ranks_playerManager__no_player_name_available= +ranks_playerManager__cannot_load_player_file=No se pudo cargar el jugador: %1 +ranks_playerManager__failed_to_load_economy_currency=Error al cargar la economía para obtener el saldo del jugador %1 con una moneda de %2. +ranks_playerManager__failed_to_load_economy=Error al cargar la economía para obtener el saldo del jugador %1. +ranks_playerManager__last_rank_message_for__prison_rankup_rank_tag_default= + +ranks_commandCommands__command_add_cannot_use_percent_symbols=&7No se pueden usar símbolos de porcentaje como caracteres de escape de marcadores de posición; debe usar { } en su lugar. +ranks_commandCommands__command_add_placeholders=&7Marcadores de posición personalizados para comandos de rango son: &3%1 +ranks_commandCommands__rank_does_not_exist=El rango '%1' no existe. +ranks_commandCommands__command_add_duplicate=El comando duplicado '%1' no se añadió al rango '%2'. +ranks_commandCommands__command_add_success=Se añadió el comando '%1' al rango '%2'. + +ranks_commandCommands__command_remove_sucess=Se eliminó el comando '%1' del rango '%2'. +ranks_commandCommands__command_remove_failed=El rango no contiene ese comando. No se realizó ningún cambio. + +ranks_commandCommands__command_list_contains_none=El rango '%1' no contiene comandos. +ranks_commandCommands__command_list_cmd_header=Comandos de RankUp para el rango %1 +ranks_commandCommands__command_list_click_cmd_to_remove=&8Haz clic en un comando para eliminarlo. +ranks_commandCommands__command_list_click_to_remove=Haz clic para eliminar. +ranks_commandCommands__command_list_add_button=&7[&a+&7] Añadir un nuevo comando +ranks_commandCommands__command_list_add_new_command_tool_tip=&7Añadir un nuevo comando. +ranks_commandCommands__command_row_number_must_be_greater_than_zero=&7Por favor, proporciona un número de fila válido mayor que cero. Fila era=[&b%1&7] +ranks_commandCommands__command_row_number_too_high=&7Por favor, proporciona un número de fila válido no mayor que &b%1&7. Fila era=[&b%2&7] + +ranks_commandCommands__ladder_command_add_placeholders=&7Marcadores de posición personalizados para comandos de escalera son: &3%1 +ranks_commandCommands__ladder_ladder_does_not_exist=La escalera '%1' no existe. +ranks_commandCommands__ladder_command_add_duplicate=El comando duplicado '%1' no se añadió a la escalera '%2'. +ranks_commandCommands__ladder_command_add_success=Se añadió el comando '%1' a la escalera '%2'. + +ranks_commandCommands__ladder_command_remove_sucess=Se eliminó el comando '%1' de la escalera '%2'. +ranks_commandCommands__ladder_command_remove_failed=La escalera no contiene ese comando. No se realizó ningún cambio. + +ranks_commandCommands__ladder_command_list_contains_none=La escalera '%1' no contiene comandos. +ranks_commandCommands__ladder_command_list_cmd_header=Comandos de RankUp para la escalera %1 + +ranks_LadderCommands__ladder_already_exists=Ya existe una escalera con el nombre '%1'. +ranks_LadderCommands__ladder_creation_error=Se produjo un error al crear tu escalera '%1'. &8Consulta la consola para obtener detalles. +ranks_LadderCommands__ladder_created=La escalera '%1' ha sido creada. +ranks_LadderCommands__ladder_could_not_save=No se pudo guardar la escalera. +ranks_LadderCommands__ladder_does_not_exist=La escalera '%1' no existe. +ranks_LadderCommands__rank_does_not_exist=El rango '%1' no existe. +ranks_LadderCommands__ladder_already_has_rank=La escalera '%1' ya contiene el rango '%2'. +ranks_LadderCommands__ladder_added_rank=Se añadió el rango '%1' a la escalera '%2' en la posición %3. +ranks_LadderCommands__ladder_deleted=La escalera '%1' ha sido eliminada. +ranks_LadderCommands__ladder_cannot_delete_default=No puedes eliminar la escalera predeterminada. Es necesaria. +ranks_LadderCommands__ladder_cannot_delete_prestiges=No puedes eliminar la escalera de prestigio. Es necesaria. +ranks_LadderCommands__ladder_cannot_delete_with_ranks=No se puede eliminar una escalera si todavía tiene rangos vinculados a ella. Elimina todos los rangos y vuelve a intentarlo. +ranks_LadderCommands__ladder_error=Se produjo un error al eliminar tu escalera. &8Consulta la consola para obtener detalles. +ranks_LadderCommands__ladder_error_adding=Se produjo un error al añadir un rango a tu escalera. &8Consulta la consola para obtener detalles. +ranks_LadderCommands__ladder_error_removing=Se produjo un error al eliminar un rango de tu escalera. &8Consulta la consola para obtener detalles. +ranks_LadderCommands__ladder_error_saving=Error al guardar la escalera. +ranks_LadderCommands__move_rank_notice=Intentando eliminar el rango especificado de su escalera original, luego se añadirá de nuevo a la escalera de destino en la ubicación especificada. El rango no se perderá. + +ranks_LadderCommands__ladder_has_ranks=&7Esta escalera contiene los siguientes rangos: +ranks_LadderCommands__ladder_default_rank=&b(Rango predeterminado) &7- +ranks_LadderCommands__ladder_see_ranks_list=&3Ver &f/ranks list &b[nombre de la escalera] &3para obtener más detalles sobre los rangos. +ranks_LadderCommands__ladder_has_no_perms=&3La escalera '&7%1&3' no contiene permisos ni grupos de permisos. +ranks_LadderCommands__ladder_set_rank_cost_multiplier=&3La escalera '&7%1&3' se guardó. El multiplicador de costo de rango es ahora [%2]; era [%3]. +ranks_LadderCommands__ladder_rank_cost_multiplier_no_change=&3La escalera '&7%1&3' no se actualizó. El multiplicador de costo de rango suministrado no cambió. [%2] +ranks_LadderCommands__ladder_rank_cost_multiplier_out_of_range=&3El multiplicador de costo de rango está fuera de rango. Debe estar entre -100% y 100%. [%1] +ranks_LadderCommands__ladder_apply_rank_cost_multiplier_no_change=&3La escalera '&7%1&3' no se actualizó. El multiplicador de costo de rango aplicado a esta escalera no cambió. [%2] +ranks_LadderCommands__ladder_apply_rank_cost_multiplier_saved=&3La escalera '&7%1&3' se guardó. La aplicación del multiplicador de costo de rango a esta escalera es ahora [%2]; era [%3]. + +ranks_rankCommands__rank_already_exists=&3El rango llamado &7%1 &3ya existe. Prueba con un nombre diferente. +ranks_rankCommands__rank_name_required=&3Se requiere un nombre de rango y no puede contener códigos de formato. +ranks_rankCommands__ladder_does_not_exist=&3Una escalera con el nombre de '&7%1&3' no existe. +ranks_rankCommands__ladder_has_no_ranks=&3La escalera '&7%1&3' no tiene ningún rango. +ranks_rankCommands__ladder_has_no_ranks_text=&3--- Esta escalera no tiene rangos --- +ranks_rankCommands__rank_does_not_exist=&3El rango '&7%1&3' no existe. +ranks_rankCommands__rank_cannot_be_created=&3No se pudo crear el rango. +ranks_rankCommands__rank_created_successfully=&3Tu nuevo rango, '&7%1&3', fue creado en la escalera '&7%2&3', usando el valor de etiqueta '&7%3&3' +ranks_rankCommands__error_saving_ladder=&3La escalera '&7%1&3' no se pudo guardar en el disco. Comprueba la consola para obtener detalles. +ranks_rankCommands__error_writting_ladder=&3La escalera '&7%1&3' no se pudo guardar en el disco. Comprueba la consola para obtener detalles. + +ranks_rankCommands__auto_config_preexisting_warning=&3Estás intentando ejecutar &7/ranks autoConfigure&3 con rangos o minas ya configurados. Cantidad de rangos = &7%1&3. Cantidad de minas = &7%2&3. Por favor, ejecuta este comando con la palabra clave &7help&3 para obtener más información y otras opciones de personalización: &7/ranks autoConfigure help&3. Es mejor ejecutar este comando desde la &7consola&3 debido al volumen de datos que genera. Añade la opción '&7force&3' para forzar la ejecución de este proceso. Si hay un conflicto con un rango o mina preexistente, este proceso hará todo lo posible para fusionar los nuevos rangos y minas con lo que ya existe. Hay el riesgo de que algo no se fusione correctamente. Al fusionar, todos los bloques serán reemplazados, pero en la consola se imprimirá la lista de bloques originales como referencia si quieres recrearlos. Por favor, haz una copia de seguridad de tu directorio &7plugins/Prison/&3 antes de ejecutar para estar seguro. +ranks_rankCommands__auto_config_force_warning=&a¡Advertencia! &3Ejecutar autoConfigure con &7force&3 habilitado. No se hace responsable si las minas o los rangos chocan. +ranks_rankCommands__auto_config_invalid_options=&3Se detectaron opciones no válidas. {br}Usa %1&3. {br}&3Las opciones restantes desconocidas fueron: [&7%2&3] +ranks_rankCommands__auto_config_skip_rank_warning=&a¡Advertencia! &3El rango &7%1 &3ya existe y se está omitiendo junto con la generación de la mina si está habilitada, junto con todas las demás funciones. + +ranks_rankCommands__auto_config_no_ranks_created=Rangos autoConfigure: No se crearon rangos. +ranks_rankCommands__auto_config_ranks_created=Rangos autoConfigure: Se crearon %1 rangos. +ranks_rankCommands__auto_config_no_rank_cmds_created=Rangos autoConfigure: No se crearon comandos de rango. +ranks_rankCommands__auto_config_ladder_rank_cost_multiplier_info=La escalera 'prestigios' se ha habilitado para aplicar un Multiplicador de Costo de Rango Base del %1 que se aplicará a 'todos' los costos de rango. Este multiplicador se incrementará con cada rango en la escalera. +ranks_rankCommands__auto_config_ladder_rank_cost_multiplier_command_example=El Multiplicador de Costo de Rango Base se puede ajustar o desactivar con el comando: '/ranks ladder rankCostMultiplier +ranks_rankCommands__auto_config_rank_cmds_created=Rangos autoConfigure: Se crearon %1 comandos de rango. + +ranks_rankCommands__auto_config_no_mines_created=Rangos autoConfigure: No se crearon minas. +ranks_rankCommands__auto_config_mines_created=Rangos autoConfigure: Se crearon %1 minas. + +ranks_rankCommands__auto_config_no_linkage=Rangos autoConfigure: No se vincularon minas y no se vincularon rangos. +ranks_rankCommands__auto_config_linkage_count=Rangos autoConfigure: Se vincularon %1 rangos y minas. + +ranks_rankCommands__rank_cannot_remove=No puedes eliminar este rango porque es el único rango en la escalera predeterminada. +ranks_rankCommands__rank_was_removed=El rango '%1' ha sido eliminado con éxito. +ranks_rankCommands__rank_delete_error=El rango '%1' no se pudo eliminar debido a un error. + +ranks_rankCommands__ranks_list_header=&3Rangos en la escalera &7%1 &3 +ranks_rankCommands__ranks_list_ladder_cost_multplier=&3 Multiplicador de Costo de Rango por Rango: &7%1 +ranks_rankCommands__ranks_list_ladder_apply_ranks_cost_multplier=&3 ¿Aplicar multiplicadores de costo de rango globales a este rango? &7%1 +ranks_rankCommands__ranks_list_ladder_edit_cost_multplier=Editar el Multiplicador de Costo de Rango de esta Escalera. + +ranks_rankCommands__ranks_list_click_to_edit=&7Haz clic en el nombre de un rango para ver más información. +ranks_rankCommands__ranks_list_command_count= &cCmds: &3%1 +ranks_rankCommands__ranks_list_currency= &3Moneda: &2%1 +ranks_rankCommands__ranks_list_click_to_view=&7Haz clic para ver la información. +ranks_rankCommands__ranks_list_click_to_view2=&7Haz clic para ver. +ranks_rankCommands__ranks_list_create_new_rank=&7Crear un nuevo rango. +ranks_rankCommands__ranks_list_you_may_try=&8También puedes probar + +ranks_rankCommands__ranks_info_header=Rango %1 +ranks_rankCommands__ranks_info_name=&3Nombre del Rango: &7%1 +ranks_rankCommands__ranks_info_tag=&3Etiqueta del Rango: &7%1 &3Sin formato: &7\Q%2\E +ranks_rankCommands__ranks_info_ladder=&3Escalera: &7%1 +ranks_rankCommands__ranks_info_not_linked_to_mines=&3Este rango no está vinculado a ninguna mina +ranks_rankCommands__ranks_info_linked_mines=&3Minas vinculadas a este rango: %1 +ranks_rankCommands__ranks_info_cost=&3Costo: &7$%1 +ranks_rankCommands__ranks_info_currency=&3Moneda: &7<&a%1&7> +ranks_rankCommands__ranks_info_players_with_rank=&7Jugadores con este rango: %1 +ranks_rankCommands__ranks_info_rank_id=&6ID de Rango: &7%1 +ranks_rankCommands__ranks_info_rank_delete_message=&7[&c-&7] Eliminar +ranks_rankCommands__ranks_info_rank_delete_tool_tip=&7Haz clic para eliminar este rango.\n&cEsta acción no se puede deshacer. + +ranks_rankCommands__rank_set_cost_success=Se ha establecido correctamente el costo del rango '%1' en %2 + +ranks_rankCommands__set_currency_not_specified=Se debe especificar un nombre de moneda, o debe ser 'ninguno'. '%1' no es válido. +ranks_rankCommands__set_currency_no_currency_to_clear=El rango '%1' no tiene una moneda, por lo que no se puede borrar. +ranks_rankCommands__set_currency_cleared=Se ha eliminado correctamente la moneda para el rango '%1'. Este rango ya no tiene una moneda personalizada. +ranks_rankCommands__set_currency_no_active_support=Ninguna economía activa admite la moneda llamada '%1'. +ranks_rankCommands__set_currency_successful=Se ha establecido correctamente la moneda para el rango '%1' en %2 + +ranks_rankCommands__set_tag_invalid=&cEl nombre de la etiqueta debe ser un valor válido. Para eliminar, use un valor de &aninguno&c. +ranks_rankCommands__set_tag_no_change=&cEl nuevo nombre de la etiqueta es el mismo que el anterior. No se ha realizado ningún cambio. +ranks_rankCommands__set_tag_cleared=&cEl nombre de la etiqueta se ha eliminado para el rango %1. +ranks_rankCommands__set_tag_success=&cEl nombre de la etiqueta se ha cambiado a %1 para el rango %2. + +ranks_rankCommands__player_must_be_online=&3Debes ser un jugador en el juego para ejecutar este comando, y/o el jugador debe estar en línea. +ranks_rankCommands__player_ladder_info=&7Escalera: &b%1 &7Rango Actual: &b%2 +ranks_rankCommands__player_ladder_highest_rank= ¡Es el rango más alto! +ranks_rankCommands__player_ladder_next_rank=&7 Próximo rango: &b%1&7 &c$&b%2 +ranks_rankCommands__player_ladder_next_rank_currency=&7 Moneda: &2%1 +ranks_rankCommands__player_balance_default=&7El saldo actual de &b%1 &7es &b%2 +ranks_rankCommands__player_balance_others=&7El saldo actual de &b%1 &7es &b%2 &2%3 +ranks_rankCommands__player_perms_offline=&7 Aviso: &3El jugador está desconectado, por lo que los permisos no están disponibles ni son precisos. +ranks_rankCommands__player_sellall_multiplier=&7 Multiplicador de Venta: &b%1 %2 +ranks_rankCommands__player_not_accurate=&5(&2No Preciso&5) +ranks_rankCommands__player_admin_only=&8[Solo Admin] +ranks_rankCommands__player_past_names=&7Nombres de Jugadores Anteriores y Fecha de Cambio: +ranks_rankCommands__player_perms=&7Permisos de Jugador: +ranks_rankCommands__player_op=&cOP +ranks_rankCommands__player_player=&3Jugador +ranks_rankCommands__player_online=&3En Línea +ranks_rankCommands__player_offline=&3Desconectado +ranks_rankCommands__player_prison_offline_player=&3PrisiónJugadorDesconectado +ranks_rankCommands__player_prison_player=&3PrisiónJugador +ranks_rankCommands__player_no_ranks_found=&3No se encontraron rangos para &c%1 + +ranks_rankCommands__players_invalid_ladder=La escalera '%1' no existe, o no era 'TODOS'. +ranks_rankCommands__players_invalid_action=La acción '%1' es inválida. [jugadores, todos, completo] + +ranks_rankCommands__topn_forced_reload_successful=La recarga forzada de topN fue exitosa. +ranks_rankCommands__topn_forced_reload_failure=La recarga forzada de topN falló. +ranks_rankCommands__topn_debug_saved_success=El modo de depuración topN: todos los datos topN guardados en Prison/data_storage/prisonTopN.json y recargados para estadísticas de rendimiento. \ No newline at end of file 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 d5284ec1b..1e5c2ab66 100644 --- a/prison-core/src/main/resources/lang/ranks/fr_FR.properties +++ b/prison-core/src/main/resources/lang/ranks/fr_FR.properties @@ -72,7 +72,7 @@ ## be able to enable them. -messages__version=28 +messages__version=29 messages__auto_refresh=true ranks_rankup__rankup_no_player_name=Tu as @@ -94,6 +94,7 @@ ranks_rankup__rankup_no_ranks=Il n'y a pas de rangs dans ce classement. ranks_rankup__rankup_rank_does_not_exist=Le rang %1 n'existe pas dans ce serveur. ranks_rankup__rankup_rank_is_not_in_ladder=Le rang %1 n'existe pas dans le classement %2. ranks_rankup__rankup_currency_is_not_supported=La monnaie, %1, n'est pas supporté par aucun plugin d'économie chargé. +ranks_rankup__rankup_economy_failed=Failed to adjust player's balance. Could be an issue with vault or a cache timing issue. Try again. ranks_rankup__rankup_ladder_removed=Le classement %1 a été supprimé. ranks_rankup__rankup_failure_removing_ladder=La montée en rang a échoué comme le joueur n'a pas pu être supprimé du classement. (Les joueurs ne peuvent pas être supprimés du classement 'default'). ranks_rankup__rankup_in_progress_failure=La montée en rang n'a pas réussi à se terminer correctement. Aucun statut n'a été défini. 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 13c0a863c..d24bc1e39 100644 --- a/prison-core/src/main/resources/lang/ranks/pt_PT.properties +++ b/prison-core/src/main/resources/lang/ranks/pt_PT.properties @@ -72,7 +72,7 @@ ## be able to enable them. -messages__version=6 +messages__version=7 messages__auto_refresh=true ranks_rankup__rankup_no_player_name=Tu têns @@ -94,6 +94,7 @@ ranks_rankup__rankup_no_ranks=Não existe ranks nesta ladder. ranks_rankup__rankup_rank_does_not_exist=O rank %1 não existe neste server. ranks_rankup__rankup_rank_is_not_in_ladder=O rank %1 não existe naladder %2. ranks_rankup__rankup_currency_is_not_supported=A economia não é suportada, %1. +ranks_rankup__rankup_economy_failed=Failed to adjust player's balance. Could be an issue with vault or a cache timing issue. Try again. ranks_rankup__rankup_ladder_removed=A ladder %1 foi removida. ranks_rankup__rankup_failure_removing_ladder=Rankup falhou porque nao foi possivel remover o player da ladder %1. (Players cannot be removed from the 'default' ladder). ranks_rankup__rankup_in_progress_failure=Rankup falhou ser complet corretamente. 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 9a53f49c5..73d9bca5c 100644 --- a/prison-core/src/main/resources/lang/ranks/zh-CN.properties +++ b/prison-core/src/main/resources/lang/ranks/zh-CN.properties @@ -72,7 +72,7 @@ ## be able to enable them. -messages__version=25 +messages__version=26 messages__auto_refresh=true ranks_rankup__rankup_no_player_name=ä½ å·²ç» @@ -92,6 +92,7 @@ ranks_rankup__rankup_failed_to_assign_rank_with_refund=分é…阶级失败. é‡ ranks_rankup__rankup_failed_to_save_player_file=无法检索或写入数æ®ï¼Œæ‚¨çš„æ–‡ä»¶å¯èƒ½å·²æŸå,通知æœåŠ¡å™¨ç®¡ç†å‘˜ ranks_rankup__rankup_no_ranks=这个矿区上没有阶级 ranks_rankup__rankup_rank_does_not_exist=阶级%1ä¸å­˜åœ¨ +ranks_rankup__rankup_economy_failed=Failed to adjust player's balance. Could be an issue with vault or a cache timing issue. Try again. ranks_rankup__rankup_rank_is_not_in_ladder=阶级%2中ä¸å­˜åœ¨é˜¶çº§%1 ranks_rankup__rankup_currency_is_not_supported=ä»»ä½•å·²åŠ è½½çš„ç»æµŽå‰ç½®éƒ½ä¸æ”¯æŒè´§å¸%1 ranks_rankup__rankup_ladder_removed=已删除阶级%1 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 45cce31bc..97fc64c7f 100644 --- a/prison-core/src/main/resources/lang/ranks/zh_TW.properties +++ b/prison-core/src/main/resources/lang/ranks/zh_TW.properties @@ -72,7 +72,7 @@ ## be able to enable them. -messages__version=9 +messages__version=10 messages__auto_refresh=true ranks_rankup__rankup_no_player_name=您已經 @@ -94,6 +94,7 @@ ranks_rankup__rankup_no_ranks=這個階內沒有階級 ranks_rankup__rankup_rank_does_not_exist=階級 %1 ä¸å­˜åœ¨ ranks_rankup__rankup_rank_is_not_in_ladder=此階級 %1 ä¸å­˜åœ¨æ–¼éšŽ %2 之中 ranks_rankup__rankup_currency_is_not_supported=這個貨幣, %1, 無法使用於此 +ranks_rankup__rankup_economy_failed=Failed to adjust player's balance. Could be an issue with vault or a cache timing issue. Try again. ranks_rankup__rankup_ladder_removed=階 %1 已經刪除 ranks_rankup__rankup_failure_removing_ladder=Rankup failed since the player could not be removed from the ladder %1. (Players cannot be removed from the 'default' ladder). ranks_rankup__rankup_in_progress_failure=無法正常的å‡ç´š. 此階級ä¸å­˜åœ¨ diff --git a/prison-core/src/main/resources/lang/sellall/es_ES.properties b/prison-core/src/main/resources/lang/sellall/es_ES.properties new file mode 100644 index 000000000..3b42bef6c --- /dev/null +++ b/prison-core/src/main/resources/lang/sellall/es_ES.properties @@ -0,0 +1,74 @@ +# NOTE: A messages__version is an arbitrary integer that will be manually incremented within Prison +# when there are changes to these messages. This value represents when message content is +# changed, fixed, or added to. This value may not be increased if the change is very small and +# insignificant, such as a space or a couple of letters. +# +# messages__auto_refresh=true indicates that this file will automatically be replaced if +# Prison detects a messages__version difference. The old file will be deleted (renamed) and +# a new copy will be placed in the directory to be used. If this value is set to false, then +# Prison will not refresh this file and there could be issues with the display of other messages. +# If auto refresh is set to false, we are not held responsible for possible issues that can +# arise from inaccurate messages. If set to false, then you are responsible for maintaining +# the messages on your own. +# +# If you make changes to this file, and you have messages__auto_refresh=false, then those +# changes will be replaced when this file is updated. Since the old file is renamed, and +# not deleted, you can manually merge your changes back in to the new update. The old +# renamed files will never be deleted by prison; you can remove them when you feel like it +# is safe to do so. +# +# 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 +# like to share, please contact a staff member on our Discord server. +#Thanks for your contributions! +# + +## +## Prison Supports Unicode (UTF-8) encoding in these properties files. BUt you must +## follow these instructions to ensure everything works properly. +## +## 1. You should only edit these files using a UTF-8 editor. On windows use NotePad, not WordPad. +## WordPad will save as plain text. To confirm the save was successful: save, close the editor, +## then reopen to confirm the encoding was preserved. +## +## 2. When running on Windows, you must enable utf-8 encoding in minecraft's console. Windows +## defaults to a characterpage 1252. To enable window's use of utf-8, you need to change the +## encoding prior to launching spigot/paper: +## chcp 65001 +## +## Full example of a windows script, which hooks for java debugging: +## rem Note: chcp 65001 enables utf-8 in windows, when normally windows uses characterpage 1252 +## chcp 65001 +## java -Dfile.encoding="UTF-8" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -Xms1g -Xmx4g -jar spigot-1.8.8.jar nogui --log-strip-color +## pause +## +## 3. When viewing the logs/latest.log files you must use an editor such as NotePad instead of WordPad. +## +## 4. Unicode is properly displayed in game, in console, in the logs, and with paste.helpch.at when using +## /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 + +sellall_function__message=&dEjemplo &7Mensaje + +sellall_spigot_utils__money_earned=&3Has ganado &a$%1 +sellall_spigot_utils__only_sellall_signs_are_enabled=&3Solo puedes vender a través de letreros. El comando está desactivado. +sellall_spigot_utils__rate_limit_exceeded=&3Despacio. Se ha excedido el límite de uso. +sellall_spigot_utils__shop_is_empty=&3Lo siento, esta tienda de sellall está vacía. +sellall_spigot_utils__you_have_nothing_to_sell=&3Lo siento, no tienes nada que vender. + +sellall_spigot_utils__sellall_is_disabled=&3Lo siento, sellall está deshabilitado. +sellall_spigot_utils__sellall_gui_is_disabled=&3Lo siento, el menú de sellall está deshabilitado. \ No newline at end of file diff --git a/prison-core/src/main/resources/lang/spigot/es_ES.properties b/prison-core/src/main/resources/lang/spigot/es_ES.properties new file mode 100644 index 000000000..341787a89 --- /dev/null +++ b/prison-core/src/main/resources/lang/spigot/es_ES.properties @@ -0,0 +1,324 @@ +# NOTE: A messages__version is an arbitrary integer that will be manually incremented within Prison +# when there are changes to these messages. This value represents when message content is +# changed, fixed, or added to. This value may not be increased if the change is very small and +# insignificant, such as a space or a couple of letters. +# +# messages__auto_refresh=true indicates that this file will automatically be replaced if +# Prison detects a messages__version difference. The old file will be deleted (renamed) and +# a new copy will be placed in the directory to be used. If this value is set to false, then +# Prison will not refresh this file and there could be issues with the display of other messages. +# If auto refresh is set to false, we are not held responsible for possible issues that can +# arise from inaccurate messages. If set to false, then you are responsible for maintaining +# the messages on your own. +# +# If you make changes to this file, and you have messages__auto_refresh=false, then those +# changes will be replaced when this file is updated. Since the old file is renamed, and +# not deleted, you can manually merge your changes back in to the new update. The old +# renamed files will never be deleted by prison; you can remove them when you feel like it +# is safe to do so. +# +# 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 +# like to share, please contact a staff member on our Discord server. +#Thanks for your contributions! +# + +## +## Prison Supports Unicode (UTF-8) encoding in these properties files. BUt you must +## follow these instructions to ensure everything works properly. +## +## 1. You should only edit these files using a UTF-8 editor. On windows use NotePad, not WordPad. +## WordPad will save as plain text. To confirm the save was successful: save, close the editor, +## then reopen to confirm the encoding was preserved. +## +## 2. When running on Windows, you must enable utf-8 encoding in minecraft's console. Windows +## defaults to a characterpage 1252. To enable window's use of utf-8, you need to change the +## encoding prior to launching spigot/paper: +## chcp 65001 +## +## Full example of a windows script, which hooks for java debugging: +## rem Note: chcp 65001 enables utf-8 in windows, when normally windows uses characterpage 1252 +## chcp 65001 +## java -Dfile.encoding="UTF-8" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -Xms1g -Xmx4g -jar spigot-1.8.8.jar nogui --log-strip-color +## pause +## +## 3. When viewing the logs/latest.log files you must use an editor such as NotePad instead of WordPad. +## +## 4. Unicode is properly displayed in game, in console, in the logs, and with paste.helpch.at when using +## /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 + +## Haga clic para hacer algo +spigot_gui_lore_click_to_add=Haz clic para agregar. +spigot_gui_lore_click_to_add_backpack=Haz clic para agregar una mochila. +#spigot_gui_lore_click_to_cancel=Haz clic para cancelar. +#spigot_gui_lore_click_to_close=Haz clic para cerrar. +#spigot_gui_lore_click_to_confirm=Haz clic para confirmar. +#spigot_gui_lore_click_to_decrease=Haz clic para disminuir. +#spigot_gui_lore_click_to_delete=Haz clic para eliminar. +#spigot_gui_lore_click_to_disable=Haz clic para deshabilitar. +#spigot_gui_lore_click_to_edit=Haz clic para editar. +#spigot_gui_lore_click_to_enable=Haz clic para habilitar. +#spigot_gui_lore_click_to_increase=Haz clic para aumentar. +spigot_gui_lore_click_to_manage_rank=Haz clic para administrar el rango. +#spigot_gui_lore_click_to_open=Haz clic para abrir. +spigot_gui_lore_click_to_rankup=Haz clic para subir de rango. +spigot_gui_lore_click_to_rename=Haz clic para renombrar. +spigot_gui_lore_click_to_select=Haz clic para seleccionar. +spigot_gui_lore_click_to_start_block_setup=Haz clic para agregar un bloque. +spigot_gui_lore_click_to_teleport=Haz clic para teleportar. +spigot_gui_lore_click_to_use=Haz clic para usar. + +## Haga clic izquierdo para hacer algo. +#spigot_gui_lore_click_left_to_confirm=Haz clic izquierdo para confirmar. +#spigot_gui_lore_click_left_to_reset=Haz clic izquierdo para reiniciar. +#spigot_gui_lore_click_left_to_open=Haz clic izquierdo para abrir. +#spigot_gui_lore_click_left_to_edit=Haz clic izquierdo para editar. + +## Haga clic derecho para hacer algo. +#spigot_gui_lore_click_right_to_cancel=Haz clic derecho para cancelar. +#spigot_gui_lore_click_right_to_delete=Haz clic derecho para eliminar. +#spigot_gui_lore_click_right_to_disable=Haz clic derecho para deshabilitar. +#spigot_gui_lore_click_right_to_enable=Haz clic derecho para habilitar. +#spigot_gui_lore_click_right_to_toggle=Haz clic derecho para cambiar. + +## Cambio de turno y haga clic derecho para hacer algo +#spigot_gui_lore_click_right_and_shift_to_delete=Cambio de turno y haz clic derecho para eliminar. +#spigot_gui_lore_click_right_and_shift_to_disable=Cambio de turno y haz clic derecho para deshabilitar. +#spigot_gui_lore_click_right_and_shift_to_toggle=Cambio de turno y haz clic derecho para cambiar. + +## Títulos o nombres de datos. +spigot_gui_lore_backpack_id=ID de la mochila: +spigot_gui_lore_blocks=Bloques: +spigot_gui_lore_blocktype=Tipo de bloque: +spigot_gui_lore_chance=Probabilidad: +spigot_gui_lore_command=Comando: +spigot_gui_lore_currency=Moneda: +#spigot_gui_lore_delay=Retraso: +spigot_gui_lore_id=ID: +spigot_gui_lore_info=Información: +spigot_gui_lore_minename=Nombre de la mina: +#spigot_gui_lore_multiplier=Multiplicador: +spigot_gui_lore_name=Nombre: +spigot_gui_lore_owner=Propietario: +spigot_gui_lore_percentage=Porcentaje: +#spigot_gui_lore_permission=Permiso: +spigot_gui_lore_players_at_rank=Jugadores en rango: +#spigot_gui_lore_prestige_name=Nombre de prestigio: +#spigot_gui_lore_price=Precio: +spigot_gui_lore_radius=Radio: +spigot_gui_lore_rank_tag=Etiqueta de rango: +spigot_gui_lore_reset_time=Tiempos de reinicio: +spigot_gui_lore_size=Tamaño: +spigot_gui_lore_show_item=Mostrar artículo: +spigot_gui_lore_spawnpoint=Punto de aparición: +spigot_gui_lore_volume=Volumen: +#spigot_gui_lore_value=Valor: +spigot_gui_lore_world=Mundo: + +## Acciones simples o estado. +spigot_gui_lore_disabled=Desactivado. +spigot_gui_lore_enabled=Activado. +spigot_gui_lore_locked=¡Bloqueado! +#spigot_gui_lore_next_page=Página siguiente. +#spigot_gui_lore_prior_page=Página anterior. +spigot_gui_lore_rankup=Subir de rango. +spigot_gui_lore_selected=Seleccionado. +spigot_gui_lore_unlocked=Desbloqueado! + +## Descripciones. +spigot_gui_lore_add_backpack_instruction_1=Agrega al menos un elemento +spigot_gui_lore_add_backpack_instruction_2=Si no lo haces, la mochila +spigot_gui_lore_add_backpack_instruction_3=no se guardará. +spigot_gui_lore_prestige_warning_1=El prestigio restablecerá: +spigot_gui_lore_prestige_warning_2=- Rango. +spigot_gui_lore_prestige_warning_3=- Saldo. +spigot_gui_lore_ranks_setup_1=¡No hay rangos! +spigot_gui_lore_ranks_setup_2=Si deseas continuar la configuración. +spigot_gui_lore_ranks_setup_3=Todos los rangos y minas de A a Z se realizarán +spigot_gui_lore_ranks_setup_4=¡Con valores &apredeterminados&3! +spigot_gui_lore_ranks_setup_5=También puedes usar: +spigot_gui_lore_ranks_setup_6=/ranks autoConfigure full ! +spigot_gui_lore_ranks_setup_7=Reemplace X con el precio inicial y +spigot_gui_lore_ranks_setup_8=el multiplicador, precio predeterminado = 50000, multiplicador = 1.5. +spigot_gui_lore_sellall_delay_use_1=Breve retraso antes de usar nuevamente +spigot_gui_lore_sellall_delay_use_2=el comando &3/sellall sell &8. +spigot_gui_lore_set_mine_delay_instruction_1=Establece un retraso de mina +spigot_gui_lore_set_mine_delay_instruction_2=antes de restablecer cuando +spigot_gui_lore_set_mine_delay_instruction_3=llegue a cero bloques. +spigot_gui_lore_show_item_description_1=Este es el artículo +spigot_gui_lore_show_item_description_2=mostrado en la GUI del jugador +spigot_gui_lore_show_item_description_3=o /mines GUI. +spigot_gui_lore_skip_reset_instruction_1=Salta el reinicio si +spigot_gui_lore_skip_reset_instruction_2=no se han extraído suficientes bloques +spigot_gui_lore_skip_reset_instruction_3=. + +## Nombres de botones o descripciones de una sola línea. +spigot_gui_lore_autofeatures_button_description=Gestionar funciones automáticas. +spigot_gui_lore_backpacks_button_description=Gestionar mochilas. +spigot_gui_lore_disable_notifications=Deshabilitar notificaciones. +spigot_gui_lore_enable_radius_mode=Activar el modo de radio. +spigot_gui_lore_enable_within_mode=Activar el modo dentro. +spigot_gui_lore_mines_button_description=Gestionar minas. +spigot_gui_lore_no_multipliers=[!] ¡No hay multiplicadores! +spigot_gui_lore_ranks_button_description=Administrador de GUI de rangos. +spigot_gui_lore_rankup_if_enough_money=Si tienes suficiente dinero. +spigot_gui_lore_sellall_button_description=Gestionar SellAll. +spigot_gui_lore_sellall_edit_info=Editar moneda de SellAll. +spigot_gui_lore_tp_to_mine=Haz clic para teleportar a la mina. + +## Mensajes +spigot_message_missing_permission=¡Lo siento, no tienes permiso para usar eso! +spigot_message_chat_event_time_end=¡Se acabó el tiempo, evento cancelado! +spigot_message_event_cancelled=Evento cancelado. +spigot_message_command_wrong_format=Lo siento, el formato del comando es incorrecto. +spigot_message_console_error=Lo siento, debes ser un jugador para usar eso. + +## Mensajes de escalera +spigot_message_ladder_default_empty=Lo siento, la escalera predeterminada está vacía. + +## Mensajes de minas +spigot_message_mines_disabled=Lo siento, las minas están desactivadas. +spigot_message_mines_name_chat_1=Por favor, escribe el &6mineName &7que te gustaría usar y &6submit&7. +spigot_message_mines_name_chat_2=Escribe &cclose &7para cancelar o espera &c30 segundos&7. +spigot_message_mines_name_chat_cancelled=Renombrar mina &ccerrado&7, ¡nada cambió! +spigot_message_mines_item_show_edit_success=Elemento de muestra de mina editado con éxito. +spigot_message_mines_or_gui_disabled=Lo siento, las minas o las GUI están deshabilitadas. + +## Mensajes de mochila +spigot_message_backpack_cant_own=Lo siento, no puedes tener mochilas. +spigot_message_backpack_delete_error=Lo siento, no se puede eliminar la mochila. +spigot_message_backpack_delete_success=Mochila eliminada con éxito. +spigot_message_backpack_format_error=Lo siento, el formato del comando no es correcto, tal vez falten algunos argumentos. +spigot_message_backpack_limit_decrement_fail=El límite de la mochila no puede ser negativo. +spigot_message_backpack_limit_edit_success=Límite de mochila editado con éxito. +spigot_message_backpack_limit_not_number=Lo siento, el límite de la mochila no es un número. +spigot_message_backpack_limit_reached=Lo siento, no puedes tener más mochilas. +spigot_message_backpack_missing_playername=Lo siento, por favor agrega un nombre de jugador válido. +spigot_message_backpack_resize_success=Si la mochila existe, se redimensionó con éxito. +spigot_message_backpack_size_must_be_multiple_of_9=¡El tamaño de la mochila debe ser un múltiplo de 9 y no exceder 64! + + +## Mensajes de prestigio +spigot_message_prestiges_disabled=Lo siento, los prestigios están desactivados. +spigot_message_prestiges_empty=Lo siento, no hay prestigios. +spigot_message_prestiges_or_gui_disabled=Lo siento, los prestigios o las GUI están deshabilitados. +spigot_message_prestiges_confirm=Confirmar&7: Escribe la palabra &aconfirm&7 para confirmar. +spigot_message_prestiges_cancel=Cancelar&7: Escribe la palabra &ccancel&7 para cancelar, &ctienes 30 segundos. +spigot_message_prestiges_cancelled=Prestigio cancelado. +spigot_message_prestiges_cancelled_wrong_keyword=Prestigio &ccancelado&7, no escribiste la palabra: &aconfirm&7. + +## Mensajes de rangos +spigot_message_ranks_disabled=Lo siento, los rangos están desactivados. +spigot_message_ranks_or_gui_disabled=Lo siento, los rangos o las GUI están deshabilitados. +spigot_message_ranks_tag_chat_rename_1=Por favor, introduce la &6tag &7que te gustaría usar y &6submit&7. +spigot_message_ranks_tag_chat_rename_2=Introduce &cclose &7para cancelar o espera &c30 segundos&7. +spigot_message_ranks_tag_chat_cancelled=Rename tag &ccerrado&7, ¡nada cambió! + +## Mensajes de SellAll +spigot_message_sellall_auto_already_enabled=Sellall AutoSell ya esta habilitado. +spigot_message_sellall_auto_already_disabled=SellAll AutoSell ya esta deshabilitado. +spigot_message_sellall_auto_disabled=AutoSell se ha deshabilitado. +spigot_message_sellall_auto_disabled_cant_use=Lo siento, debes habilitar AutoSell para usar esto. +spigot_message_sellall_auto_enabled=AutoSell se ha habilitado. +spigot_message_sellall_auto_perusertoggleable_enabled=Sellall AutoSell perUserToggleable está habilitado. +spigot_message_sellall_auto_perusertoggleable_disabled=Sellall AutoSell perUserToggleable está deshabilitado. +spigot_message_sellall_auto_perusertoggleable_already_enabled=Sellall AutoSell perUserToggleable ya esta habilitado. +spigot_message_sellall_auto_perusertoggleable_already_disabled=Sellall AutoSell perUserToggleable ya esta deshabilitado. +spigot_message_sellall_boolean_input_invalid=El valor booleano no es válido (los valores válidos son Verdadero o Falso). +spigot_message_sellall_cant_find_item_config=Lo siento, no puedo encontrar tu artículo en la configuración. +spigot_message_sellall_currency_chat_1=&3¡Inicio de la configuración de una nueva moneda para SellAll! +spigot_message_sellall_currency_chat_2=Escribe &ccancel &7para cancelar. +spigot_message_sellall_currency_chat_3=Escribe &3default &7para establecer la moneda predeterminada. +spigot_message_sellall_currency_chat_4=Escribe el &anombre de la moneda &7para establecer la nueva moneda. +spigot_message_sellall_currency_edit_success=Moneda de SellAll editada con éxito. +spigot_message_sellall_currency_not_found=Lo siento, moneda no encontrada. +spigot_message_sellall_hand_disabled=SellAll Hand desactivado con éxito. +spigot_message_sellall_hand_enabled=SellAll Hand habilitado con éxito. +spigot_message_sellall_hand_is_disabled=SellAll Hand está desactivado. +spigot_message_sellall_item_add_success=Artículo agregado con éxito. +spigot_message_sellall_item_already_added=Ya has agregado este artículo, por favor usa el comando de edición en su lugar. +spigot_message_sellall_item_delete_success=Artículo eliminado con éxito. +spigot_message_sellall_item_edit_success=SellAll Item editado con éxito. +spigot_message_sellall_item_id_not_found=Lo siento, nombre de artículo/ID no válido. +spigot_message_sellall_item_missing_name=Agrega el argumento de nombre de artículo/ID por favor. +spigot_message_sellall_item_missing_price=Agrega el argumento de valor de artículo por favor. +spigot_message_sellall_item_not_found=Artículo de SellAll no encontrado en la configuración. +spigot_message_sellall_default_values_success=Valores predeterminados de SellAll establecidos con éxito. +spigot_message_sellall_delay_already_enabled=SellAll Delay ya esta habilitado. +spigot_message_sellall_delay_already_disabled=SellAll Delay ya esta deshabilitado. +spigot_message_sellall_delay_disabled=SellAll Delay deshabilitado con éxito. +spigot_message_sellall_delay_disabled_cant_use=Lo siento, por favor habilita SellAll Delay para usar esto. +spigot_message_sellall_delay_edit_success=Sellall Delay editado con éxito. +spigot_message_sellall_delay_enabled=SellAll Delay habilitado con éxito. +spigot_message_sellall_delay_not_number=El número de SellAll Delay no es válido. +#spigot_message_sellall_delay_wait=Sellall delay is enabled, please slow down. +spigot_message_sellall_gui_disabled=La GUI de SellAll está desactivada. +#spigot_message_sellall_money_earned=You earned &a$ +spigot_message_sellall_multiplier_add_success=SellAll Multiplier añadido con éxito. +spigot_message_sellall_multiplier_are_disabled=Lo siento, los multiplicadores de SellAll están desactivados. +spigot_message_sellall_multiplier_cant_find=Lo siento, no se puede encontrar el multiplicador de SellAll. +spigot_message_sellall_multiplier_delete_success=SellAll Multiplier eliminado con éxito. +spigot_message_sellall_multiplier_disabled=Multiplicadores de SellAll desactivados con éxito. +spigot_message_sellall_multiplier_edit_success=SellAll Multiplier editado con éxito. +#spigot_message_sellall_sell_empty=Sorry, there aren't items in the SellAll shop. +#spigot_message_sellall_sell_nothing_sellable=Sorry but you've nothing to sell. +#spigot_message_sellall_sell_sign_only=You can use SellAll Sell only with Signs. +spigot_message_sellall_sell_sign_notify=Has vendido con éxito a través de un cartel. +spigot_message_sellall_trigger_already_disabled=SellAll Trigger ya esta deshabilitado. +spigot_message_sellall_trigger_already_enabled=SellAll Trigger ya esta habilitado. +spigot_message_sellall_trigger_disabled=SellAll Trigger deshabilitado con éxito. +spigot_message_sellall_trigger_enabled=SellAll Trigger habilitado con éxito. +spigot_message_sellall_trigger_is_disabled=Lo siento, SellAll Trigger está desactivado. +spigot_message_sellall_trigger_item_add_success=Disparador de artículo SellAll añadido con éxito. +spigot_message_sellall_trigger_item_cant_find=Disparador de artículo SellAll no encontrado en la configuración. +spigot_message_sellall_trigger_item_delete_success=Disparador de artículo SellAll eliminado con éxito. +spigot_message_sellall_trigger_item_missing=Agrega el nombre/ID del artículo al comando. + +## Mensajes de GUI +spigot_message_gui_backpack_disabled=No se puede abrir la GUI, las mochilas están desactivadas. +spigot_message_gui_backpack_empty=Lo siento, no hay mochilas que mostrar. +spigot_message_gui_backpack_too_many=Lo siento, hay demasiadas mochilas y la GUI no puede mostrarlas. +spigot_message_gui_close_success=GUI cerrada con éxito. +spigot_message_gui_error=No se puede abrir la GUI, deshabilitada o con error. +spigot_message_gui_error_empty=No se puede abrir la GUI, está vacía. +spigot_message_gui_ladder_empty=Lo siento, no hay escaleras que mostrar. [%1] +spigot_message_gui_ladder_too_many=Lo siento, hay demasiadas escaleras y la GUI no puede mostrarlas. +spigot_message_gui_mines_empty=Lo siento, no hay minas que mostrar. +spigot_message_gui_mines_too_many=Lo siento, hay demasiadas minas para que la GUI las muestre. +spigot_message_gui_prestiges_empty=Lo siento, no hay prestigios que mostrar. +spigot_message_gui_prestiges_too_many=Lo siento, hay demasiados prestigios y la GUI no puede mostrarlos. +spigot_message_gui_ranks_empty=Lo siento, no hay rangos en esta escalera para mostrar. +spigot_message_gui_ranks_rankup_commands_empty=Lo siento, no hay comandos de subida de rango para mostrar. +spigot_message_gui_ranks_rankup_commands_too_many=Lo siento, hay demasiados comandos de subida de rango y la GUI no puede mostrarlos. +spigot_message_gui_ranks_too_many=Lo siento, hay demasiados rangos y la GUI no puede mostrarlos. +spigot_message_gui_reload_success=¡GUI recargada con éxito! +#spigot_message_gui_sellall_disabled=Sorry, SellAll is disabled. +spigot_message_gui_sellall_empty=Lo siento, no hay nada que mostrar. +spigot_message_gui_too_high=Lo siento, pero el valor es demasiado alto (por encima del máximo posible). +spigot_message_gui_too_low_value=Lo siento, pero el valor es demasiado bajo (por debajo del mínimo posible). + + +spigot_blockbreak_mines__mine_is_being_reset__please_wait=La mina %1 se está restableciendo... por favor espera. + +spigot_blockbreak_core__validate_event__your_tool_is_worn_out=&cTu herramienta está desgastada y no se puede usar. + +spigot_auto_manager__inventory_is_full=&c¡ADVERTENCIA! ¡Tu inventario está lleno! +spigot_auto_manager__is_full_dropping_item__ignore__not_useds=&c¡ADVERTENCIA! ¡Tu inventario está lleno y estás dejando caer objetos! +spigot_auto_manager__inventory_is_full_losing_items=&c¡ADVERTENCIA! ¡Tu inventario está lleno y estás perdiendo objetos! + +spigot_minebombs__cooldown_delay=No puedes usar otra Bomba de Mina de Prisión durante %1 segundos. \ No newline at end of file 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 74eb4933e..3a86b57ca 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestPlatform.java @@ -30,6 +30,7 @@ import tech.mcprison.prison.PrisonCommand.RegisteredPluginsData; import tech.mcprison.prison.backpacks.PlayerBackpack; +import tech.mcprison.prison.bombs.MineBombEffectsData; import tech.mcprison.prison.commands.PluginCommand; import tech.mcprison.prison.file.FileStorage; import tech.mcprison.prison.file.YamlFileIO; @@ -79,6 +80,21 @@ public void getWorldLoadErrors( ChatDisplay display ) { } + @Override + public Player getPlatformPlayer(RankPlayer rankPlayer) { + return null; + } + + @Override + public RankPlayer getRankPlayer(UUID uuid, String name) { + return null; + } + + @Override + public boolean saveRankPlayer(RankPlayer rPlayer) { + return false; + } + @Override public Optional getPlayer(String name) { return null; @@ -93,10 +109,11 @@ public Optional getPlayer(UUID uuid) { public List getOnlinePlayers() { return new ArrayList<>(); } + @Override public List getOfflinePlayers() { - List players = new ArrayList<>(); - return players; + List players = new ArrayList<>(); + return players; } @Override @@ -171,15 +188,15 @@ public void log(String message, Object... format) { @Override public void logCore( String message ) { - if (suppressOutput) { - return; - } - System.out.println(ChatColor.stripColor(message)); + if (suppressOutput) { + return; + } + System.out.println(ChatColor.stripColor(message)); } @Override public void logPlain( String message ) { - System.out.println(message); + System.out.println(message); } @Override @@ -229,24 +246,24 @@ public void identifyRegisteredPlugins() { public Map getPlaceholderDetailCounts() { - Map placeholderDetails = new TreeMap<>(); - - return placeholderDetails; + Map placeholderDetails = new TreeMap<>(); + + return placeholderDetails; } public int getPlaceholderCount() { - return 0; + return 0; } public int getPlaceholderRegistrationCount() { - return 0; + return 0; } @Override public Placeholders getPlaceholders() { - return null; + return null; } @@ -311,6 +328,11 @@ public List getConfigHashKeys(String hashPrefix) { return new ArrayList(); } + @Override + public boolean isConfigSection(String section) { + return false; + } + @Override public boolean isWorldExcluded( String worldName ) { @@ -575,19 +597,21 @@ public Map loadYaml(File file) { @Override public String dumpEventListenersBlockPlaceEvents() { - // TODO Auto-generated method stub return null; } @Override public String dumpEventListenersPlayerDropItemEvents() { - // TODO Auto-generated method stub return null; } @Override public String dumpEventListenersPlayerPickupItemEvents() { - // TODO Auto-generated method stub return null; } + + public MineBombEffectsData validateMineBombEffect(MineBombEffectsData mineBombEffectsData) { + return mineBombEffectsData; + } + } diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java b/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java index 6cf0b48c4..385587d00 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestPlayer.java @@ -72,50 +72,62 @@ public List getInput() { */ public String getPlayerFileName() { - return JsonFileIO.getPlayerFileName( this ); + return JsonFileIO.filePlayer( this ).getName(); +// return JsonFileIO.filenamePlayer( this ); } - @Override public void updateInventory() { + @Override + public void updateInventory() { } - @Override public void dispatchCommand(String command) { + @Override + public void dispatchCommand(String command) { } - @Override public boolean hasPermission(String perm) { + @Override + public boolean hasPermission(String perm) { return true; } - @Override public void sendMessage(String message) { + @Override + public void sendMessage(String message) { System.out.println(message); input.add(message); } - @Override public void sendMessage(String[] messages) { + @Override + public void sendMessage(String[] messages) { input.addAll(Arrays.asList(messages)); } - @Override public void sendRaw(String json) { + @Override + public void sendRaw(String json) { input.add(json); } - @Override public UUID getUUID() { + @Override + public UUID getUUID() { return null; } - @Override public String getDisplayName() { + @Override + public String getDisplayName() { return null; } - @Override public void setDisplayName(String newDisplayName) { + @Override + public void setDisplayName(String newDisplayName) { } - @Override public void give(ItemStack itemStack) { + @Override + public void give(ItemStack itemStack) { } - @Override public Location getLocation() { + @Override + public Location getLocation() { return null; } @@ -127,42 +139,49 @@ public Block getLineOfSightBlock() { @Override public List getLineOfSightBlocks() { - List results = new ArrayList<>(); - return results; + List results = new ArrayList<>(); + return results; } - @Override public void teleport(Location location) { - + @Override + public boolean teleport(Location location) { + return false; } - @Override public boolean isOnline() { + @Override + public boolean isOnline() { return true; } - @Override public void setScoreboard(Scoreboard scoreboard) { + @Override + public void setScoreboard(Scoreboard scoreboard) { } - @Override public Gamemode getGamemode() { + @Override + public Gamemode getGamemode() { return null; } - @Override public void setGamemode(Gamemode gamemode) { + @Override + public void setGamemode(Gamemode gamemode) { } - @Override public Optional getLocale() { + @Override + public Optional getLocale() { return Optional.of("en_US"); } - @Override public boolean isOp() { + @Override + public boolean isOp() { return true; } @Override public boolean isPlayer() { - return false; + return false; } @Override public Inventory getInventory() { @@ -181,22 +200,29 @@ public void recalculatePermissions() { @Override public List getPermissions() { - List results = new ArrayList<>(); - - return results; + List results = new ArrayList<>(); + + return results; } + @Override public List getPermissions( String prefix ) { - List results = new ArrayList<>(); - for ( String perm : getPermissions() ) { - if ( perm.startsWith( prefix ) ) { - results.add( perm ); - } - } - - return results; + return getPermissions( prefix, getPermissions() ); + } + + @Override + public List getPermissions( String prefix, List perms ) { + List results = new ArrayList<>(); + + for ( String perm : perms ) { + if ( perm.startsWith( prefix ) ) { + results.add( perm ); + } + } + + return results; } @Override @@ -209,9 +235,19 @@ public List getPermissionsIntegrations( boolean detailed ) { @Override public double getSellAllMultiplier() { - return 1.0; + return 1.0; } + @Override + public double getSellAllMultiplierDebug() { + return 1.0; + } + + @Override + public List getSellAllMultiplierListings() { + return new ArrayList<>(); + } + @Override public void setTitle( String title, String subtitle, int fadeIn, int stay, int fadeOut ) { } @@ -253,10 +289,6 @@ public void incrementMinecraftStatsDropCount( Player player, String blockName, i } - @Override - public List getSellAllMultiplierListings() { - return new ArrayList<>(); - } @Override @@ -274,4 +306,26 @@ public RankPlayer getRankPlayer() { return null; } + + + /** + * This miscText is not used for any specific purpose other than to hold a String + * value. It can be used to return a message from a function, but it should always + * be cleared when done using it. + * + * @return + */ + @Override + public String getMiscText() { + return null; + } + + @Override + public void setMiscText( String text ) { + } + + @Override + public long getLastSeenDate() { + return 0; + } } diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestScheduler.java b/prison-core/src/test/java/tech/mcprison/prison/TestScheduler.java index b3182ee53..4058aaa8a 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestScheduler.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestScheduler.java @@ -7,19 +7,23 @@ * @author Faizaan A. Datoo */ public class TestScheduler implements Scheduler { - @Override public int runTaskLater(Runnable run, long delay) { + @Override + public int runTaskLater(Runnable run, long delay) { return 0; } - @Override public int runTaskLaterAsync(Runnable run, long delay) { + @Override + public int runTaskLaterAsync(Runnable run, long delay) { return 0; } - @Override public int runTaskTimer(Runnable run, long delay, long interval) { + @Override + public int runTaskTimer(Runnable run, long delay, long interval) { return 0; } - @Override public int runTaskTimerAsync(Runnable run, long delay, long interval) { + @Override + public int runTaskTimerAsync(Runnable run, long delay, long interval) { return 0; } @@ -33,16 +37,18 @@ public void performCommand(Player player, String command) { } - @Override public void cancelTask(int taskId) { + @Override + public void cancelTask(int taskId) { } - @Override public void cancelAll() { + @Override + public void cancelAll() { } @Override public boolean isPrimaryThread() { - return false; + return false; } } diff --git a/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java b/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java index 873d31269..4b42963f5 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java +++ b/prison-core/src/test/java/tech/mcprison/prison/TestWorld.java @@ -18,8 +18,13 @@ package tech.mcprison.prison; +import java.util.ArrayList; import java.util.List; +import tech.mcprison.prison.bombs.MineBombs.AnimationArmorStandItemLocation; +import tech.mcprison.prison.internal.ArmorStand; +import tech.mcprison.prison.internal.Entity; +import tech.mcprison.prison.internal.EntityType; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.PrisonStatsElapsedTimeNanos; import tech.mcprison.prison.internal.World; @@ -76,5 +81,30 @@ public void setBlocksSynchronously( List tBlocks, } + @Override + public List getEntities() { + return new ArrayList<>(); + } + + @Override + public Entity spawnEntity( Location location, EntityType entityType ) { + return null; + } + + @Override + public ArmorStand spawnArmorStand( Location location ) { + return null; + } + + @Override + public int getMaxHeight() { + return 125; + } + + @Override + public ArmorStand spawnArmorStand( Location location, String itemType, + AnimationArmorStandItemLocation asLocation ) { + return null; + } } diff --git a/prison-core/src/test/java/tech/mcprison/prison/bombs/GeometricShapesTest.java b/prison-core/src/test/java/tech/mcprison/prison/bombs/GeometricShapesTest.java new file mode 100644 index 000000000..870bc0550 --- /dev/null +++ b/prison-core/src/test/java/tech/mcprison/prison/bombs/GeometricShapesTest.java @@ -0,0 +1,67 @@ +package tech.mcprison.prison.bombs; + +import java.text.DecimalFormat; + +import tech.mcprison.prison.internal.World; +import tech.mcprison.prison.internal.WorldTest; +import tech.mcprison.prison.util.Location; +import tech.mcprison.prison.util.Vector; + +public class GeometricShapesTest extends GeometricShapes { + +// @Test + public void test() { + + DecimalFormat dFmt = new DecimalFormat( "##0" ); + double radius = 1d; + + for ( double deg = 0; deg <= 360; deg += 5 ) { + + Vector v = getPointsOnCircleXZ( deg, radius ); + + System.out.println( + String.format( + "points on a circle: degree: %s r: %s %s", + dFmt.format( deg ), + dFmt.format( radius ), + v.toString() + ) + ); + } + } + +// @Test + public void testWithLocations() { + + DecimalFormat dFmt = new DecimalFormat( "##0" ); + + double x = 120; + double y = 60; + double z = -50; + + World w = new WorldTest(); + + Location loc = new Location( w, x, y, z ); + + double radius = 1d; + + for ( double deg = 0; deg <= 360; deg += 5 ) { + + Vector v = getPointsOnCircleXZ( deg, radius ); + + Location circleLoc = loc.add( v ); + + System.out.println( + String.format( + "points on a circle: degree: %3s r: %2s %s %s", + dFmt.format( deg ), + dFmt.format( radius ), + v.toString(), + circleLoc.toString() + ) + ); + } + + } + +} diff --git a/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java b/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java index e958991ff..a400e9f1d 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/bombs/MineBombEffectsDataTest.java @@ -1,13 +1,20 @@ package tech.mcprison.prison.bombs; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.TreeSet; import org.junit.Test; +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.TestPlatform; +import tech.mcprison.prison.internal.platform.Platform; + public class MineBombEffectsDataTest extends MineBombEffectsData { @@ -17,12 +24,17 @@ public final void testCompare() { MineBombEffectsData mbef01 = new MineBombEffectsData("ABC", EffectState.explode, 0 ); + mbef01.setEffectType( EffectType.sounds ); MineBombEffectsData mbef02 = new MineBombEffectsData("XYZ", EffectState.placed, 3 ); + mbef02.setEffectType( EffectType.sounds ); MineBombEffectsData mbef03 = new MineBombEffectsData("BDF", EffectState.finished, 14 ); + mbef03.setEffectType( EffectType.sounds ); MineBombEffectsData mbef04 = new MineBombEffectsData("DEF", EffectState.finished, 0 ); + mbef04.setEffectType( EffectType.sounds ); MineBombEffectsData mbef05 = new MineBombEffectsData("ABC", EffectState.placed, 0 ); + mbef05.setEffectType( EffectType.sounds ); assertEquals( 1, compare( mbef01, mbef02 ) ); @@ -53,5 +65,66 @@ public final void testCompare() assertEquals( mbef03, testList.get( 4 ) ); } + + @Test + public final void testJson() + { + + Platform platform = new TestPlatform( new File("tempDir"), true ); + Prison.get().setPlatform( platform ); + + + MineBombs mBombs = new MineBombs(); + + // First build the default bombs: + MineBombDefaultConfigSettings defConfigs = new MineBombDefaultConfigSettings(); + defConfigs.setupDefaultMineBombData(mBombs); + + String json = mBombs.toJson(); + + MineBombs mBombsTwo = MineBombs.fromJson(json); + + assertNotNull( mBombs ); + assertNotNull( mBombsTwo ); + + assertEquals( 0, mBombs.compareTo(mBombsTwo )); + +// assertEquals( mBombs, mBombsTwo ); + } + + + @Test + public final void testClone() + { + + Platform platform = new TestPlatform( new File("tempDir"), true ); + Prison.get().setPlatform( platform ); + + + MineBombs mBombs = new MineBombs(); + + // First build the default bombs: + MineBombDefaultConfigSettings defConfigs = new MineBombDefaultConfigSettings(); + defConfigs.setupDefaultMineBombData(mBombs); + + MineBombs mBombsTwo = new MineBombs(); + + Set keys = mBombs.getConfigData().getBombs().keySet(); + for (String key : keys) { + MineBombData mBomb = mBombs.getConfigData().getBombs().get(key); + + mBombsTwo.getConfigData().getBombs().put( + key, mBomb.clone() ); + + } + + assertNotNull( mBombs ); + assertNotNull( mBombsTwo ); + + assertEquals( 0, mBombs.compareTo(mBombsTwo )); + +// assertEquals( mBombs, mBombsTwo ); + } + } diff --git a/prison-core/src/test/java/tech/mcprison/prison/chat/ChatTest.java b/prison-core/src/test/java/tech/mcprison/prison/chat/ChatTest.java index 34befeafe..343ef08dd 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/chat/ChatTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/chat/ChatTest.java @@ -34,7 +34,9 @@ public class ChatTest { .color(ChatColor.BLACK); String expected = - "{\"text\":\"\",\"extra\":[{\"text\":\"Test\",\"color\":\"aqua\",\"clickEvent\":{\"action\":\"open_url\",\"value\":\"http://google.com\"}},{\"text\":\"ing\",\"color\":\"black\"}]}"; + "{\"text\":\"\",\"extra\":[{\"text\":\"Test\",\"color\":\"aqua\"," + + "\"clickEvent\":{\"action\":\"open_url\",\"value\":\"http://google.com\"}}," + + "{\"text\":\"ing\",\"color\":\"black\"}]}"; String actual = message.toJSONString(); assertEquals(expected, actual); diff --git a/prison-core/src/test/java/tech/mcprison/prison/internal/EulerAngleTest.java b/prison-core/src/test/java/tech/mcprison/prison/internal/EulerAngleTest.java new file mode 100644 index 000000000..9bcd5a2cf --- /dev/null +++ b/prison-core/src/test/java/tech/mcprison/prison/internal/EulerAngleTest.java @@ -0,0 +1,24 @@ +package tech.mcprison.prison.internal; + +import org.junit.Test; + +public class EulerAngleTest { + + @Test + public void test() { + + // Have no idea what the starting values should be, which 0,0,0 should work, + // but they don't. + // Also not sure what angle is expected, such as degrees or radians. + EulerAngle ea = new EulerAngle( 1, 1, 1 ); + + for ( double angle = -10; angle <= 10; angle += 0.5 ) { + ea.rotateAroundAxisX( angle ); + +// System.out.println( ea.toString() + " angle: " + angle ); + } + +// fail("Not yet implemented"); + } + +} diff --git a/prison-core/src/test/java/tech/mcprison/prison/internal/WorldTest.java b/prison-core/src/test/java/tech/mcprison/prison/internal/WorldTest.java new file mode 100644 index 000000000..7834279bf --- /dev/null +++ b/prison-core/src/test/java/tech/mcprison/prison/internal/WorldTest.java @@ -0,0 +1,74 @@ +package tech.mcprison.prison.internal; + +import java.util.ArrayList; +import java.util.List; + +import tech.mcprison.prison.bombs.MineBombs.AnimationArmorStandItemLocation; +import tech.mcprison.prison.internal.block.Block; +import tech.mcprison.prison.internal.block.MineResetType; +import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.util.Location; + +public class WorldTest implements World { + + + @Override + public String getName() { + return "Test world - does not exist"; + } + + @Override + public List getPlayers() { + return new ArrayList<>(); + } + + @Override + public List getEntities() { + return new ArrayList<>(); + } + + @Override + public Block getBlockAt(Location location) { + return PrisonBlock.AIR; + } + + @Override + public Block getBlockAt(Location location, boolean containsCustomBlocks) { + return PrisonBlock.AIR; + } + + @Override + public void setBlock(PrisonBlock block, int x, int y, int z) { + } + + @Override + public void setBlockAsync(PrisonBlock prisonBlock, Location location) { + } + + @Override + public void setBlocksSynchronously(List tBlocks, MineResetType resetType, + PrisonStatsElapsedTimeNanos nanos) { + } + + @Override + public Entity spawnEntity(Location loc, EntityType entityType) { + return null; + } + + @Override + public ArmorStand spawnArmorStand(Location location) { + return null; + } + + @Override + public ArmorStand spawnArmorStand(Location location, String itemType, AnimationArmorStandItemLocation asLocation ) { + return null; + } + + @Override + public int getMaxHeight() { + return 255; + } + +} diff --git a/prison-core/src/test/java/tech/mcprison/prison/placeholders/PlaceHolderKeyTest.java b/prison-core/src/test/java/tech/mcprison/prison/placeholders/PlaceHolderKeyTest.java index 87ec837a7..7446fc807 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/placeholders/PlaceHolderKeyTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/placeholders/PlaceHolderKeyTest.java @@ -2,6 +2,9 @@ import org.junit.Test; +/** + * @deprecated + */ public class PlaceHolderKeyTest //extends PlaceHolderKey { @@ -15,85 +18,8 @@ public PlaceHolderKeyTest() { @Test public void test() { - /** - [14:04:20] [Async Chat Thread - #0/INFO]: &8| &3Prison &8| &7 &cFailure to generate log message due to incorrect number of parameters: [Format specifier '%1$s'] :: Original raw message [### ChatHandler - before [\Q%s\E] after [\Q%s\E]] Arguments: [<{prison_rank_tag}{prison_rank}{prison_r}{prison_rank_default}{PRISON_RANK}{PRISON_RANK_TAG}[{prison_rc} {prison_rcp}]:%1$s>%2$s] [<{prison_rank_tag}{prison_rank}{prison_r}{prison_rank_default}{PRISON_RANK}{PRISON_RANK_TAG}[{prison_rc} {prison_rcp}]:%1$s>%2$s] - [14:04:20] [Async Chat Thread - #0/INFO]: <{prison_rank_tag}{prison_rank}{prison_r}{prison_rank_default}{PRISON_RANK}{PRISON_RANK_TAG}[{prison_rc} {prison_rcp}]:RoyalBlueRanger>hey - - */ - -// List placeHolderKeys = new ArrayList<>(); -// -// PlaceHolderKey key1 = new PlaceHolderKey( PrisonPlaceHolders.prison_rank.name(), PrisonPlaceHolders.prison_rank, true ); -// PlaceHolderKey key2 = new PlaceHolderKey( PrisonPlaceHolders.prison_rank_tag.name(), PrisonPlaceHolders.prison_rank_tag, true ); -// -// placeHolderKeys.add( key1 ); -// placeHolderKeys.add( key2 ); -// -// String testText1 = "<{prison_rank_tag}{prison_rank}>"; -// String testText2 = "<{prison_rank_tag}{prison_r}>"; -// String testText3 = "<{prison_rank_default}{prison_rank_tag}>"; -// -// String testText4 = "<{prison_rank_tag}{prison_rank::some:annotation:goes:here}>"; -// -// String testText5 = "<{prison_rank_tag}{Prison_Rank}>"; -// String testText6 = "<{prison_rank_tag}{PRISON_RANK}>"; - -// String testText7 = "<{prison_rank_tag}{prison_rank}{prison_r}{prison_rank_default}" + -// "{PRISON_RANK}{PRISON_RANK_TAG}[{prison_rc} {prison_rcp}"; - - -// PlaceholderResults results1 = key1.getIdentifier( testText1 ); -// PlaceholderResults results2 = key1.getIdentifier( testText2 ); -// PlaceholderResults results3 = key1.getIdentifier( testText3 ); -// -// assertTrue( results1.hasResults() ); -// assertEquals( "prison_rank", results1.getIdentifier() ); -// -// assertFalse( results2.hasResults() ); -// assertNull( results2.getIdentifier() ); -// -// assertFalse( results3.hasResults() ); -// assertNull( results3.getIdentifier() ); -// -// -// -// PlaceholderResults results4 = key2.getIdentifier( testText3 ); -// -// assertTrue( results4.hasResults() ); -// assertEquals( "prison_rank_tag", results4.getIdentifier() ); -// -// -// -// PlaceholderResults results5 = key1.getIdentifier( testText4 ); -// -// assertTrue( results5.hasResults() ); -// assertEquals( "prison_rank::some:annotation:goes:here", results5.getIdentifier() ); -// -// -// PlaceholderResults results6 = key1.getIdentifier( testText5 ); -// PlaceholderResults results7 = key1.getIdentifier( testText6 ); -// -// assertTrue( results6.hasResults() ); -// assertEquals( "Prison_Rank", results6.getIdentifier() ); -// -// assertTrue( results7.hasResults() ); -// assertEquals( "PRISON_RANK", results7.getIdentifier() ); -// -// -// -// String testText10 = "<{prison_rANk_tag}{prison_rank_default}{PRISON_RANK}[{prison_rc} {prison_rcp}]"; -// -// PlaceholderResults results10a = key1.getIdentifier( testText10 ); -// PlaceholderResults results10b = key2.getIdentifier( testText10 ); -// -// -// assertTrue( results10a.hasResults() ); -// assertEquals( "PRISON_RANK", results10a.getIdentifier() ); -// -// -// assertTrue( results10b.hasResults() ); -// assertEquals( "prison_rANk_tag", results10b.getIdentifier() ); + // NOTE: Commented out source has been purged. See github's history. Could be deleted soon. } diff --git a/prison-core/src/test/java/tech/mcprison/prison/selection/SelectionTest.java b/prison-core/src/test/java/tech/mcprison/prison/selection/SelectionTest.java index 188c13c4a..58738ae71 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/selection/SelectionTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/selection/SelectionTest.java @@ -59,7 +59,8 @@ public class SelectionTest { World ourWorld = new TestWorld("TestWorld"); TestPlayer ourPlayer = new TestPlayer(); - ItemStack coloredToolItemStack = SelectionManager.SELECTION_TOOL; + ItemStack coloredToolItemStack = ItemStack.SELECTION_WAND; + coloredToolItemStack .setDisplayName(Text.translateAmpColorCodes(coloredToolItemStack.getDisplayName())); @@ -88,10 +89,8 @@ public void testSelectionToolCheck() throws Exception { Prison.get().getEventBus().post( new PrisonPlayerInteractEvent(ourPlayer, new ItemStack("test", 1, acaciaSapling ), PrisonPlayerInteractEvent.Action.LEFT_CLICK_BLOCK, new Location(ourWorld, 10, 20, 30))); -// Prison.get().getEventBus().post( -// new PrisonPlayerInteractEvent(ourPlayer, new ItemStack("test", 1, BlockType.ACACIA_SAPLING), -// PrisonPlayerInteractEvent.Action.LEFT_CLICK_BLOCK, new Location(ourWorld, 10, 20, 30))); + assertEquals(initialAmount, ourPlayer.getInput() .size()); // nothing should have happened because we have the wrong item in our hand diff --git a/prison-spigot/src/test/java/tech/mcprison/prison/spigot/spiget/BluesSemanticVersionDataTest.java b/prison-core/src/test/java/tech/mcprison/prison/util/BluesSemanticVersionDataTest.java similarity index 91% rename from prison-spigot/src/test/java/tech/mcprison/prison/spigot/spiget/BluesSemanticVersionDataTest.java rename to prison-core/src/test/java/tech/mcprison/prison/util/BluesSemanticVersionDataTest.java index 863e44d1b..bf26ed0d4 100644 --- a/prison-spigot/src/test/java/tech/mcprison/prison/spigot/spiget/BluesSemanticVersionDataTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/util/BluesSemanticVersionDataTest.java @@ -1,4 +1,4 @@ -package tech.mcprison.prison.spigot.spiget; +package tech.mcprison.prison.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -160,12 +160,12 @@ public void test() // Test the compareTo function: - assertTrue( new BluesSpigetSemVerComparator().compareTo( "1.8.0", "1.9.0" ) < 0 ); - assertTrue( new BluesSpigetSemVerComparator().compareTo( "1.8.8", "1.9.0" ) < 0 ); - assertFalse( new BluesSpigetSemVerComparator().compareTo( "1.9.0", "1.9.0" ) < 0 ); - assertFalse( new BluesSpigetSemVerComparator().compareTo( "1.15.2", "1.9.0" ) < 0 ); - assertTrue( new BluesSpigetSemVerComparator().compareTo( "1.9.0", "1.9.0" ) == 0 ); - assertTrue( new BluesSpigetSemVerComparator().compareTo( "1.15.2", "1.9.0" ) > 0 ); + assertTrue( new BluesSemanticVersionComparator().compareTo( "1.8.0", "1.9.0" ) < 0 ); + assertTrue( new BluesSemanticVersionComparator().compareTo( "1.8.8", "1.9.0" ) < 0 ); + assertFalse( new BluesSemanticVersionComparator().compareTo( "1.9.0", "1.9.0" ) < 0 ); + assertFalse( new BluesSemanticVersionComparator().compareTo( "1.15.2", "1.9.0" ) < 0 ); + assertTrue( new BluesSemanticVersionComparator().compareTo( "1.9.0", "1.9.0" ) == 0 ); + assertTrue( new BluesSemanticVersionComparator().compareTo( "1.15.2", "1.9.0" ) > 0 ); // The following "should" assert to a value of true. diff --git a/prison-spigot/src/test/java/tech/mcprison/prison/spigot/spiget/BluesSpigetSemVerComparatorTest.java b/prison-core/src/test/java/tech/mcprison/prison/util/BluesSpigetSemVerComparatorTest.java similarity index 54% rename from prison-spigot/src/test/java/tech/mcprison/prison/spigot/spiget/BluesSpigetSemVerComparatorTest.java rename to prison-core/src/test/java/tech/mcprison/prison/util/BluesSpigetSemVerComparatorTest.java index c0c02627d..87c2d612d 100644 --- a/prison-spigot/src/test/java/tech/mcprison/prison/spigot/spiget/BluesSpigetSemVerComparatorTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/util/BluesSpigetSemVerComparatorTest.java @@ -1,4 +1,4 @@ -package tech.mcprison.prison.spigot.spiget; +package tech.mcprison.prison.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -13,23 +13,23 @@ public class BluesSpigetSemVerComparatorTest @Test public void test() { - BluesSpigetSemVerComparator bssvc = new BluesSpigetSemVerComparator(); + BluesSemanticVersionComparator bsvc = new BluesSemanticVersionComparator(); // Test a few comparisons that should work easily: // Two valid semVers, but at same version should return a false: - assertFalse( bssvc.performComparisons( "1.0.1", "1.0.1" ) ); + assertFalse( bsvc.performComparisons( "1.0.1", "1.0.1" ) ); - assertFalse( bssvc.performComparisons( "1.0.2", "1.0.1" ) ); + assertFalse( bsvc.performComparisons( "1.0.2", "1.0.1" ) ); // Newer version available, should return true: - assertTrue( bssvc.performComparisons( "1.0.1", "1.0.2" ) ); + assertTrue( bsvc.performComparisons( "1.0.1", "1.0.2" ) ); // Newer version available, should return true: - assertTrue( bssvc.performComparisons( "1.4.1", "1.5.0" ) ); + assertTrue( bsvc.performComparisons( "1.4.1", "1.5.0" ) ); // Newer version available, should return true: - assertTrue( bssvc.performComparisons( "1.4.61", "1.5.0" ) ); + assertTrue( bsvc.performComparisons( "1.4.61", "1.5.0" ) ); @@ -38,27 +38,27 @@ public void test() // First test a SINGLE digit number: no decimals: // Neither are valid semVersion so should return false: - assertFalse( bssvc.performComparisons( "1", "1" ) ); + assertFalse( bsvc.performComparisons( "1", "1" ) ); // Neither are valid semVersion so should return false: - assertFalse( bssvc.performComparisons( "0", "1" ) ); + assertFalse( bsvc.performComparisons( "0", "1" ) ); // Test for a larger gap: - assertFalse( bssvc.performComparisons( "1", "7" ) ); + assertFalse( bsvc.performComparisons( "1", "7" ) ); // Test for one of them being a double digit: - assertFalse( bssvc.performComparisons( "1", "17" ) ); + assertFalse( bsvc.performComparisons( "1", "17" ) ); // Test for one of them being a double digit, but older version's digit a non-one: - assertFalse( bssvc.performComparisons( "8", "17" ) ); + assertFalse( bsvc.performComparisons( "8", "17" ) ); // These should all be false since they are all equal: - assertFalse( bssvc.performComparisons( "1.0", "1.0" ) ); - assertFalse( bssvc.performComparisons( "1.0.1", "1.0.1" ) ); + assertFalse( bsvc.performComparisons( "1.0", "1.0" ) ); + assertFalse( bsvc.performComparisons( "1.0.1", "1.0.1" ) ); // The following is an invalid semVer so it should return a false: - assertFalse( bssvc.performComparisons( "2.37.902.181.0.2.4", "2.37.902.181.0.2.4" ) ); - assertFalse( bssvc.performComparisons( "2.37.902.181.0.2.4", "2.37.902.181.0.2.5" ) ); + assertFalse( bsvc.performComparisons( "2.37.902.181.0.2.4", "2.37.902.181.0.2.4" ) ); + assertFalse( bsvc.performComparisons( "2.37.902.181.0.2.4", "2.37.902.181.0.2.5" ) ); // This should be false, where current is newer than "new". @@ -66,62 +66,62 @@ public void test() // what has been published: // equals... so should be false: - assertFalse( bssvc.performComparisons( "2.37.902-alpha.181-beta.0+build2.5", + assertFalse( bsvc.performComparisons( "2.37.902-alpha.181-beta.0+build2.5", "2.37.902-alpha.181-beta.0+build2.5" ) ); // buildmeta should be ignored so does not matter. Should be false: - assertFalse( bssvc.performComparisons( "2.37.902-alpha.181-beta.0+build2.5", + assertFalse( bsvc.performComparisons( "2.37.902-alpha.181-beta.0+build2.5", "2.37.902-alpha.181-beta.0+build2.7.34" ) ); // should be true: - assertTrue( bssvc.performComparisons( "2.37.902-alpha.181-beta.0+build2.5", + assertTrue( bsvc.performComparisons( "2.37.902-alpha.181-beta.0+build2.5", "2.37.902-alpha.181-beta.1+build2.7.34" ) ); // Newer version has invalid semVer, but its corrected to be valid: return true: - assertTrue( bssvc.performComparisons( "1.2.3", "1.3" ) ); + assertTrue( bsvc.performComparisons( "1.2.3", "1.3" ) ); // Current version has invalid semVer, but newer has valid. Always true: - assertTrue( bssvc.performComparisons( "1.2", "1.2.1" ) ); + assertTrue( bsvc.performComparisons( "1.2", "1.2.1" ) ); // 1.501 is valid so this test will fail since 1.2.1 is less: - assertFalse( bssvc.performComparisons( "1.501", "1.2.1" ) ); - assertTrue( bssvc.performComparisons( "9999901", "1.2.1" ) ); + assertFalse( bsvc.performComparisons( "1.501", "1.2.1" ) ); + assertTrue( bsvc.performComparisons( "9999901", "1.2.1" ) ); // Test situations with prerelease tagging: // First test that these are equal and returns a value of false: - assertFalse( bssvc.performComparisons( "1.2.3-alpha.1", + assertFalse( bsvc.performComparisons( "1.2.3-alpha.1", "1.2.3-alpha.1" ) ); // Newer has alpha.2 and should return true: - assertTrue( bssvc.performComparisons( "1.2.3-alpha.1", + assertTrue( bsvc.performComparisons( "1.2.3-alpha.1", "1.2.3-alpha.2" ) ); // current has alpha.2 and should return false: - assertFalse( bssvc.performComparisons( "1.2.3-alpha.2", + assertFalse( bsvc.performComparisons( "1.2.3-alpha.2", "1.2.3-alpha.1" ) ); // Current has alpha.1 and newer has full release, should return true: - assertTrue( bssvc.performComparisons( "1.2.3-alpha.1", + assertTrue( bsvc.performComparisons( "1.2.3-alpha.1", "1.2.3" ) ); // Newer has alpha.1 and should return false since full release is ranked // higher than prerelease: - assertFalse( bssvc.performComparisons( "1.2.3", + assertFalse( bsvc.performComparisons( "1.2.3", "1.2.3-alpha.1" ) ); - assertTrue( bssvc.performComparisons( "1.16.5", "1.17" ) ); - assertTrue( bssvc.performComparisons( "1.16.5", "1.17.0" ) ); + assertTrue( bsvc.performComparisons( "1.16.5", "1.17" ) ); + assertTrue( bsvc.performComparisons( "1.16.5", "1.17.0" ) ); } @Test public void test02() { - BluesSpigetSemVerComparator bssvc = new BluesSpigetSemVerComparator(); + BluesSemanticVersionComparator bsvc = new BluesSemanticVersionComparator(); String paperTest = "Minecraft version: git-Paper-21 (MC: 1.15)"; - assertEquals( "1.15", bssvc.getBukkitVersion( paperTest ) ); + assertEquals( "1.15", bsvc.getBukkitVersion( paperTest ) ); } } diff --git a/prison-core/src/test/java/tech/mcprison/prison/util/BoundsTest.java b/prison-core/src/test/java/tech/mcprison/prison/util/BoundsTest.java index 7593fd0db..28620cbf7 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/util/BoundsTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/util/BoundsTest.java @@ -30,20 +30,86 @@ */ public class BoundsTest { - @Test public void equals() throws Exception { + @Test + public void equals() throws Exception { Bounds bounds = new Bounds(new Location(null, 0.0, 0.0, 0.0), new Location(null, 10.0, 10.0, 10.0)); Bounds otherBounds = new Bounds(new Location(null, 0.0, 0.0, 0.0), new Location(null, 10.0, 10.0, 10.0)); + // Since world is null, this cannot be true: + // Bounds should never exist without a world, otherwise it is virtual. + assertFalse(bounds.equals(otherBounds)); + + // NOTE: How would this ever be true??? +// assertTrue(bounds.equals(otherBounds)); + + TestWorld world1 = new TestWorld("test1"); + TestWorld world2 = new TestWorld("test2"); + + bounds.setWorld( world1 ); + otherBounds.setWorld( world2 ); + + assertFalse(bounds.equals(otherBounds)); + + otherBounds.setWorld( world1 ); + + assertTrue(bounds.equals(otherBounds)); + + otherBounds.getMax().setX( 10.1 ); + assertTrue(bounds.equals(otherBounds)); } - @Test public void fail() throws Exception { - assertTrue( true ); + @Test + public void equalsInSameBlock() throws Exception { + + TestWorld world1 = new TestWorld("test1"); + + Bounds bounds = + new Bounds(new Location(world1, 0.0, 0.0, 0.0), new Location(world1, 10.0, 10.0, 10.0)); + Bounds otherBounds = + new Bounds(new Location(world1, 0.0, 0.0, 0.0), new Location(world1, 10.0, 10.0, 10.0)); + + + // Check to ensure these are identical before changing anything: + assertTrue(bounds.equals(otherBounds)); + + + // Confirm that it will fail if outside of existing block: + otherBounds.getMax().setX( 9.0 ); + assertFalse(bounds.equals(otherBounds)); + + + // Now try a somewhere in the original block, using fractions: + otherBounds.getMax().setX( 10.001 ); + assertTrue(bounds.equals(otherBounds)); + + // And a few other variations: + otherBounds.getMax().setX( 10.5 ); + assertTrue(bounds.equals(otherBounds)); + + otherBounds.getMax().setX( 10.999999 ); + assertTrue(bounds.equals(otherBounds)); + + otherBounds.getMax().setX( 10.000001 ); + otherBounds.getMax().setY( 10.999999 ); + otherBounds.getMax().setY( 10.5 ); + assertTrue(bounds.equals(otherBounds)); + + + assertTrue(bounds.equals(otherBounds)); + + } + +// @Test +// public void fail() throws Exception { +// assertTrue( true ); +// } - @Test public void within() throws Exception { + @Test + public void within() throws Exception { TestWorld world1 = new TestWorld("test1"); // TestWorld world2 = new TestWorld("test2"); Location loc1 = new Location(world1, 0.0, 4.0, 0.0); diff --git a/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java b/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java index 9c038a37d..76c5dfe5e 100644 --- a/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java +++ b/prison-core/src/test/java/tech/mcprison/prison/util/TextTest.java @@ -134,6 +134,29 @@ public void testHexColors() { // Test with two complete quote: assertEquals("This ^7is ^x^a^3^b^4^c^5 ^ra test #123456 test test2 #778899 test", replaceColorCodeWithx( translateColorCodes("This &7is #a3b4c5 &Ra test \\Q#123456 test\\E test2 \\Q#778899 test\\E", '&'), '^' )); + + } + + @Test + public void testHexColorBug() { + + // Note: These is a problem with hex color codes being used in lore (or elsewhere probably) + // where they are not being translated unless there is another color, such as &7 + // Proceeding it. So try to reproduce the situation... + + // The problem was that the hex conversion was working perfectly well. But + // since the "dirty" variable was not getting modified, since the hex colors were + // applied before that point in processing, it would always revert back to the original + // unchanged String value because it thought there was nothing that changed. + + // To fix the problem, I eliminated the dirty variable and am always converting the byte + // array back to a String value. So no need to check if dirty anymore, since it always converts. + assertEquals("This is ^x^a^3^b^4^c^5 a test", replaceColorCodeWithx( + translateAmpColorCodes("This is #a3b4c5 a test" ), '^' )); + + assertEquals("This is ^x^a^3^b^4^c^5a test", replaceColorCodeWithx( + translateAmpColorCodes("This is &#a3b4c5a test" ), '^' )); + } diff --git a/prison-core/src/test/java/tech/mcprison/prison/wip/discord/PrisonSupportFileLinkageTest.java b/prison-core/src/test/java/tech/mcprison/prison/wip/discord/PrisonSupportFileLinkageTest.java new file mode 100644 index 000000000..d243a879b --- /dev/null +++ b/prison-core/src/test/java/tech/mcprison/prison/wip/discord/PrisonSupportFileLinkageTest.java @@ -0,0 +1,53 @@ +package tech.mcprison.prison.wip.discord; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import tech.mcprison.prison.discord.PrisonSupportFileLinkage; +import tech.mcprison.prison.discord.PrisonSupportFileLinkage.PrimaryLinkages; + +public class PrisonSupportFileLinkageTest extends PrisonSupportFileLinkage { + + @Test + public void test() { + + PrisonSupportFileLinkage psfl = new PrisonSupportFileLinkage(); + + String test1 = "||Ladder default||"; + String test2 = "Some regular text"; + String test3 = "||Ladder cats||"; + String test4 = "||Invalid Primary||"; + + + // This should be ignored since it's not a linkage: + psfl.addLinkage(test2); + + assertEquals( 0, psfl.getPrimaries().size() ); + + + + // This should be rejected because the primary is not a valid one: + psfl.addLinkage(test4); + + assertEquals( 0, psfl.getPrimaries().size() ); + + + + // This should result in the first one being added: + psfl.addLinkage(test1); + + assertEquals( 1, psfl.getPrimaries().size() ); + assertEquals( 1, psfl.getPrimaries().get( PrimaryLinkages.Ladder ).size() ); + + + // + psfl.addLinkage(test3); + + assertEquals( 1, psfl.getPrimaries().size() ); + assertEquals( 2, psfl.getPrimaries().get( PrimaryLinkages.Ladder ).size() ); + + + } + +} diff --git a/prison-core/src/test/java/tech/mcprison/prison/wip/tasks/PrisonCommandTaskDataTest.java b/prison-core/src/test/java/tech/mcprison/prison/wip/tasks/PrisonCommandTaskDataTest.java new file mode 100644 index 000000000..81b78157b --- /dev/null +++ b/prison-core/src/test/java/tech/mcprison/prison/wip/tasks/PrisonCommandTaskDataTest.java @@ -0,0 +1,70 @@ +package tech.mcprison.prison.wip.tasks; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import tech.mcprison.prison.tasks.PrisonCommandTaskData; + +public class PrisonCommandTaskDataTest + extends PrisonCommandTaskData { + + public PrisonCommandTaskDataTest() { + super( "junit-test", "junit tests" ); + } + @Test + public void test() { + + { + String orig = "{range: 1 1}"; + String result = taskInsertRange( orig ); + + assertEquals( "1", result); + System.out.println( "Test 1: orig: " + orig + " result: " + result); + } + { + String orig = "{range: 1 3}"; + String result = taskInsertRange( orig ); + + boolean success = "1".equals(result) || + "2".equals(result) || + "3".equals(result); + assertTrue( success ); + System.out.println( "Test 2: orig: " + orig + " result: " + result); + } + { + String orig = "{range: 6 7}"; + String result = taskInsertRange( orig ); + + boolean success = "6".equals(result) || + "7".equals(result); + assertTrue( success ); + System.out.println( "Test 3: orig: " + orig + " result: " + result); + } + { + String orig = "{range: 0 2}"; + String result = taskInsertRange( orig ); + + boolean success = "0".equals(result) || + "1".equals(result) | + "2".equals(result); + assertTrue( success ); + System.out.println( "Test 4: orig: " + orig + " result: " + result); + } + { + String orig = "{range: -1 2}"; + String result = taskInsertRange( orig ); + + boolean success = "0".equals(result) || + "-1".equals(result) | + "1".equals(result) | + "2".equals(result); + assertTrue( success ); + System.out.println( "Test 5: orig: " + orig + " result: " + result); + } + + +// fail("Not yet implemented"); + } + +} diff --git a/prison-mines/build.gradle b/prison-mines/build.gradle index 5f24da4ac..8009fab02 100644 --- a/prison-mines/build.gradle +++ b/prison-mines/build.gradle @@ -1,10 +1,19 @@ group 'tech.mcprison' -//apply plugin: 'java' compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = "UTF-8" + + +// Lists all versions of java that are available to the toolchain +// $ ./gradlew -q javaToolchains + +// Specify the java version's location as found in the javaToolchains. +// $ ./gradlew build -Dorg.gradle.java.home="C:\Program Files\Java\jdk1.8.0_291" + + + dependencies { implementation project(':prison-core') testImplementation group: 'junit', name: 'junit', version: '4.12' diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesChatHandler.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesChatHandler.java index 21c561ba7..deb1ee1a0 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesChatHandler.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesChatHandler.java @@ -15,34 +15,16 @@ public MinesChatHandler() { @Subscribe public void onPlayerChat(PlayerChatEvent e) { -// String message = e.getMessage(); - String newFormat = e.getFormat(); - - Player player = e.getPlayer(); - - // Now translates - - String translated = Prison.get().getPlatform().getPlaceholders() - .placeholderTranslateText( player.getUUID(), player.getName(), newFormat ); - - -// String translated = Prison.get().getPlatform().getPlaceholders() -// .placeholderTranslateText( newFormat ); - - e.setFormat( translated ); - -// MineManager mm = PrisonMines.getInstance().getMineManager(); -// -// List placeholderKeys = mm.getTranslatedPlaceHolderKeys(); -// -// for ( PlaceHolderKey placeHolderKey : placeholderKeys ) { -// String key = "{" + placeHolderKey.getKey() + "}"; -// if ( newFormat.contains( key )) { -// newFormat = newFormat.replace(key, Text.translateAmpColorCodes( -// mm.getTranslateMinesPlaceHolder( placeHolderKey ) )); -// } -// } -// -// e.setFormat(newFormat); + String newFormat = e.getFormat(); + + Player player = e.getPlayer(); + + // Now translates + + String translated = Prison.get().getPlatform().getPlaceholders() + .placeholderTranslateText( player.getUUID(), player.getName(), newFormat ); + + e.setFormat( translated ); + } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesConversionAgent.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesConversionAgent.java index 3fdc4f550..f90120934 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesConversionAgent.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesConversionAgent.java @@ -14,112 +14,27 @@ public class MinesConversionAgent @Override public ConversionResult convert() { - Output.get().logWarn( "&7This version of prison is unable to convert older versions " + - "to this release. Please upgrade first to Prision v3.1.1, then " + - "Prison v3.2.1, then Prison v3.2.11. Once prison is upgraded to " + - "version v3.2.11 then it should be able to convert automatically to " + - "Prison v3.3.0. When upgrading to all of these versions, all that is needed " + - "is to just install the newer Prison jar file, and then start the server. " + - "The configs will be converted for you. Then 'stop' the server and " + - "continue to the next version. You may be able to skip v3.2.1, but it " + - "may be safest to run that version for the incremental adjustments. " + - "It also would not be a bad idea to may a copy of the prison plugin " + - "directory betwen version upgrades: plugins/Prison/. " ); - - Output.get().logWarn( "&7NOTE: This version of prison cannot process the older block types that " + - "were used in the older versions of prison." ); - -// File oldFolder = new File(PrisonAPI.getPluginDirectory().getParent(), "Prison.old"); -// File minesFolder = new File(oldFolder, "mines"); -// -// File alreadyConverted = new File(minesFolder, ".converted"); -// if (alreadyConverted.exists()) { -// return ConversionResult.failure(getName(), -// "Already converted. Delete the '/plugins/Prison.old/mines' folder."); -// } -// -// String[] jsonFiles = minesFolder.list((dir, name) -> name.endsWith(".json")); -// -// try { -// -// // ----------- -// // JSON -// // ----------- -// -// if (jsonFiles != null) { -// for (String jsonFile : jsonFiles) { -// File jsonFileObj = new File(minesFolder, jsonFile); -// String json = new String(Files.readAllBytes(jsonFileObj.toPath())); -// JsonObject obj = (JsonObject) JsonParser.parseString(json); -// -// String name = obj.getAsJsonPrimitive("name").getAsString(); -// String world = obj.getAsJsonPrimitive("world").getAsString(); -// double minX = obj.getAsJsonPrimitive("minX").getAsInt(); -// double minY = obj.getAsJsonPrimitive("minY").getAsInt(); -// double minZ = obj.getAsJsonPrimitive("minZ").getAsInt(); -// double maxX = obj.getAsJsonPrimitive("maxX").getAsInt(); -// double maxY = obj.getAsJsonPrimitive("maxY").getAsInt(); -// double maxZ = obj.getAsJsonPrimitive("maxZ").getAsInt(); -// -// Optional prisonWorld = -// Prison.get().getPlatform().getWorld(world); -// if (!prisonWorld.isPresent()) { -// Output.get().logWarn(String.format( -// "Can't convert mine %s because its world %s doesn't exist anymore.", -// name, world)); -// break; // Skip it, its world didn't exist. -// } -// -// Bounds bounds = new Bounds(new Location(prisonWorld.get(), minX, minY, minZ), -// new Location(prisonWorld.get(), maxX, maxY, maxZ)); -// -// HashMap blocks = new HashMap<>(); -// for (Map.Entry blockEntry : obj.getAsJsonObject("blocks") -// .entrySet()) { -// String[] blockParts = blockEntry.getKey().split(":"); -// BlockType type = BlockType.getBlock(Integer.parseInt(blockParts[0]), -// Short.parseShort(blockParts[1])); -// -// // Prison 2 stores chances in values < 1, whereas Prison 3 does it < 100 -// int chance = (int) ((blockEntry.getValue().getAsDouble()) * 100); -// -// blocks.put(type, chance); -// } -// -// Mine ourMine = new Mine(); -// ourMine.setName(name); -// ourMine.setBounds(bounds); -// ourMine.setBlocks(blocks); -// -// if (PrisonMines.getInstance().getMines().contains(ourMine)) { -// break; -// } -// -// PrisonMines.getInstance().getMines().add(ourMine); -// } -// -// PrisonMines.getInstance().getMineManager().saveMines(); -// alreadyConverted.createNewFile(); -// return new ConversionResult(getName(), ConversionResult.Status.Success, -// "Converted " + jsonFiles.length + " mines."); -// } else { -// alreadyConverted.createNewFile(); -// return new ConversionResult(getName(), ConversionResult.Status.Success, -// "Converted 0 mines."); -// } -// } catch (IOException e) { -// PrisonMines.getInstance().getErrorManager().throwError( -// new Error("Encountered an error while converting mines.") -// .appendStackTrace("while loading mines", e)); -// return new ConversionResult(getName(), ConversionResult.Status.Failure, -// "IOException, check console for details"); -// } - - return ConversionResult.failure(getName(), - "This version of prison cannot perform conversion upgrades. It skips too " + - "many versions. See WARNING in console, and install the suggested older " + - "versions of Prison to ensure all of the old data is updated correctly, " + - "with no losses."); + Output.get().logWarn( "&7This version of prison is unable to convert older versions " + + "to this release. Please upgrade first to Prision v3.1.1, then " + + "Prison v3.2.1, then Prison v3.2.11. Once prison is upgraded to " + + "version v3.2.11 then it should be able to convert automatically to " + + "Prison v3.3.0. When upgrading to all of these versions, all that is needed " + + "is to just install the newer Prison jar file, and then start the server. " + + "The configs will be converted for you. Then 'stop' the server and " + + "continue to the next version. You may be able to skip v3.2.1, but it " + + "may be safest to run that version for the incremental adjustments. " + + "It also would not be a bad idea to may a copy of the prison plugin " + + "directory betwen version upgrades: plugins/Prison/. " ); + + Output.get().logWarn( "&7NOTE: This version of prison cannot process the older block types that " + + "were used in the older versions of prison." ); + + + return ConversionResult.failure(getName(), + "This version of prison cannot perform conversion upgrades. It skips too " + + "many versions. See WARNING in console, and install the suggested older " + + "versions of Prison to ensure all of the old data is updated correctly, " + + "with no losses."); } @Override diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesListener.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesListener.java index 4058eab05..dd9d10fe7 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesListener.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/MinesListener.java @@ -28,10 +28,10 @@ public void onSelectionComplete(SelectionCompletedEvent e) { @Subscribe public void onWorldLoadListener( PrisonWorldLoadEvent e ) { - - String worldName = e.getWorldName(); - PrisonMines.getInstance().getMineManager().assignAvailableWorld( worldName ); - + + String worldName = e.getWorldName(); + PrisonMines.getInstance().getMineManager().assignAvailableWorld( worldName ); + } @@ -45,132 +45,38 @@ public void onWorldLoadListener( PrisonWorldLoadEvent e ) { @Subscribe public void onPlayerSuffocationListener( PlayerSuffocationEvent e ) { - Player player = e.getPlayer(); - Mine mine = PrisonMines.getInstance().findMineLocation( player ); - - if ( mine != null ) { - - // If players can't be suffocated in mines, then cancel the suffocation event: - if ( !Prison.get().getPlatform().getConfigBooleanFalse( "prison-mines.enable-suffocation-in-mines" ) ) { - - e.setCanceled( true ); - } - + Player player = e.getPlayer(); + Mine mine = PrisonMines.getInstance().findMineLocation( player ); + + if ( mine != null ) { + + // If players can't be suffocated in mines, then cancel the suffocation event: + if ( !Prison.get().getPlatform().getConfigBooleanFalse( "prison-mines.enable-suffocation-in-mines" ) ) { + + e.setCanceled( true ); + } - if ( Prison.get().getPlatform().getConfigBooleanTrue( "prison-mines.tp-to-spawn-on-mine-resets" ) ) { + + if ( Prison.get().getPlatform().getConfigBooleanTrue( "prison-mines.tp-to-spawn-on-mine-resets" ) ) { + + // Submit the teleport task to run in 3 ticks. This will allow the suffocation + // event to be canceled. If the player moves then they don't need to be teleported + // so it will be canceled. + MineTeleportWarmUpTask mineTeleportWarmUp = new MineTeleportWarmUpTask( + player, mine, "spawn", 0.5 ); + mineTeleportWarmUp.setMessageSuccess( + "&7You have been teleported out of the mine to prevent suffocating." ); + mineTeleportWarmUp.setMessageFailed( null ); + + PrisonTaskSubmitter.runTaskLater( mineTeleportWarmUp, 3 ); + } - // Submit the teleport task to run in 3 ticks. This will allow the suffocation - // event to be canceled. If the player moves then they don't need to be teleported - // so it will be canceled. - MineTeleportWarmUpTask mineTeleportWarmUp = new MineTeleportWarmUpTask( - player, mine, "spawn", 0.5 ); - mineTeleportWarmUp.setMessageSuccess( - "&7You have been teleported out of the mine to prevent suffocating." ); - mineTeleportWarmUp.setMessageFailed( null ); + } + else { + player.sendMessage( "&7You cannot be teleported to safety. Good luck." ); - PrisonTaskSubmitter.runTaskLater( mineTeleportWarmUp, 3 ); -// mine.teleportPlayerOut( player ); } - -// -// -// // To "move" the player out of the mine, they are elevated by one block above the surface -// // so need to remove the glass block if one is spawned under them. If there is no glass -// // block, then it will do nothing. -// mine.submitTeleportGlassBlockRemoval(); - -// player.sendMessage( "&7You have been teleported out of the mine to prevent suffocating." ); - } - else { - player.sendMessage( "&7You cannot be teleported to safety. Good luck." ); - - } } - -// /** -// * Powertool helper -// */ -// @Subscribe -// public void onBlockBreak(BlockBreakEvent e) { -// if (PrisonMines.getInstance().getPlayerManager().hasAutosmelt(e.getPlayer())) { -// smelt(e.getBlockLocation().getBlockAt() -// .getDrops(((PlayerInventory) e.getPlayer().getInventory()).getItemInRightHand())); -// } -// if (PrisonMines.getInstance().getPlayerManager().hasAutopickup(e.getPlayer())) { -// e.getPlayer().getInventory() -// .addItem(e.getBlockLocation().getBlockAt().getDrops().toArray(new ItemStack[]{})); -// e.getBlockLocation().getBlockAt().setType(BlockType.AIR); -// e.setCanceled(true); -// } -// if (PrisonMines.getInstance().getPlayerManager().hasAutoblock(e.getPlayer())) { -// block(e.getPlayer()); -// } -// } - -// private void smelt(List drops) { -// drops.replaceAll(x -> { -// if (x.getMaterial() == BlockType.GOLD_ORE) { -// return new ItemStack(x.getAmount(), BlockType.GOLD_INGOT); -// } else if (x.getMaterial() == BlockType.IRON_ORE) { -// return new ItemStack(x.getAmount(), BlockType.IRON_INGOT); -// } else { -// return x; -// } -// }); -// } - -// private void block(Player player) { -// List itemList = Arrays.asList(player.getInventory().getItems()); -// List giveBack = new ArrayList<>(); -// itemList.replaceAll(x -> { -// if (x != null) { -// if (x.getMaterial() == BlockType.DIAMOND) { -// if (x.getAmount() % 9 > 0) { -// giveBack.add(new ItemStack(x.getAmount() % 9, x.getMaterial())); -// } -// return new ItemStack(x.getAmount() / 9, BlockType.DIAMOND_BLOCK); -// } else if (x.getMaterial() == BlockType.EMERALD) { -// if (x.getAmount() % 9 > 0) { -// giveBack.add(new ItemStack(x.getAmount() % 9, x.getMaterial())); -// } -// return new ItemStack(x.getAmount() / 9, BlockType.EMERALD_BLOCK); -// } else if (x.getMaterial() == BlockType.IRON_INGOT) { -// if (x.getAmount() % 9 > 0) { -// giveBack.add(new ItemStack(x.getAmount() % 9, x.getMaterial())); -// } -// return new ItemStack(x.getAmount() / 9, BlockType.IRON_BLOCK); -// } else if (x.getMaterial() == BlockType.GLOWSTONE_DUST) { -// if (x.getAmount() % 4 > 0) { -// giveBack.add(new ItemStack(x.getAmount() % 9, x.getMaterial())); -// } -// return new ItemStack(x.getAmount() / 4, BlockType.GLOWSTONE); -// } else if (x.getMaterial() == BlockType.GOLD_INGOT) { -// if (x.getAmount() % 9 > 0) { -// giveBack.add(new ItemStack(x.getAmount() % 9, x.getMaterial())); -// } -// return new ItemStack(x.getAmount() / 9, BlockType.GOLD_BLOCK); -// } else if (x.getMaterial() == BlockType.COAL) { -// if (x.getAmount() % 9 > 0) { -// giveBack.add(new ItemStack(x.getAmount() % 9, x.getMaterial())); -// } -// return new ItemStack(x.getAmount() / 9, BlockType.BLOCK_OF_COAL); -// } else if (x.getMaterial() == BlockType.REDSTONE) { -// if (x.getAmount() % 9 > 0) { -// giveBack.add(new ItemStack(x.getAmount() % 9, x.getMaterial())); -// } -// return new ItemStack(x.getAmount() / 9, BlockType.REDSTONE_BLOCK); -// } else if (x.getMaterial() == BlockType.LAPIS_LAZULI) { -// return new ItemStack(x.getAmount() / 9, BlockType.LAPIS_LAZULI_BLOCK); -// } else { -// return x; -// } -// } else { -// return x; -// } -// }); -// player.getInventory().setItems(itemList); -// player.getInventory().addItem((ItemStack[]) giveBack.toArray()); -// } } 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 d4d0739f6..4574439a2 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 @@ -52,11 +52,9 @@ public class PrisonMines extends Module { 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; -// private List worlds; private LocaleManager localeManager; private Database db; private ErrorManager errorManager; @@ -64,7 +62,6 @@ public class PrisonMines extends Module { private JsonFileIO jsonFileIO; private MineManager mineManager; -// private PlayerManager player; private MinesCommands minesCommands; @@ -78,7 +75,7 @@ public class PrisonMines extends Module { *

    * */ - private final TreeMap playerCache; + private final TreeMap playerCache; @@ -89,17 +86,17 @@ public PrisonMines(String version) { } public static PrisonMines getInstance() { - if ( i == null ) { - PrisonMines temp = new PrisonMines("(not loaded yet)"); - temp.setEnabled(false); - return temp; - } + if ( i == null ) { + PrisonMines temp = new PrisonMines("(not loaded yet)"); + temp.setEnabled(false); + return temp; + } return i; } @Override public String getBaseCommands() { - return "/mines"; + return "/mines"; } @Override @@ -113,25 +110,13 @@ public void enable() { initConfig(); this.localeManager = new LocaleManager(this, "lang/mines"); -// initWorlds(); - this.mineManager = new MineManager(); -// getMineManager().loadFromDbCollection(this); - - // Player manager for mines is not used. -// this.player = new PlayerManager(); -// initMines(); PrisonAPI.getEventBus().register(new MinesListener()); setMinesCommands( new MinesCommands() ); Prison.get().getCommandHandler().registerCommands( getMinesCommands() ); - //Prison.get().getCommandHandler().registerCommands(new PowertoolCommands()); - - - // This is obsolete and was part of converting from pre-v3.0: - // ConversionManager.getInstance().registerConversionAgent(new MinesConversionAgent()); } @@ -142,8 +127,8 @@ public void enable() { */ @Override public void deferredStartup() { - // Load the mines at this time. - getMineManager().loadFromDbCollection(this); + // Load the mines at this time. + getMineManager().loadFromDbCollection(this); } @@ -160,8 +145,8 @@ public void deferredStartup() { @Override public void disable() { - // Shutdown the mines by saving any unsaved block stats: - getMineManager().saveMinesIfUnsavedBlockCounts(); + // Shutdown the mines by saving any unsaved block stats: + getMineManager().saveMinesIfUnsavedBlockCounts(); } @@ -190,14 +175,12 @@ private void initConfig() { File configFile = new File(getModuleDataFolder(), "config.json"); if (!configFile.exists()) { - getJsonFileIO().saveJsonFile( configFile, config ); - } else { - config = (MinesConfig) getJsonFileIO().readJsonFile( configFile, config ); + getJsonFileIO().saveJsonFile( configFile, config ); + } else { + config = (MinesConfig) getJsonFileIO().readJsonFile( configFile, config ); } } - - /** @@ -229,17 +212,17 @@ public Mine findMineLocationIncludeTopBottomOfMine( Location locationToCheck ) { return mine; } - public TreeMap getPlayerCache() { + public TreeMap getPlayerCache() { return playerCache; } public Mine findMineLocation( Player player ) { Mine results = null; - Long playerUUIDLSB = Long.valueOf( player.getUUID().getLeastSignificantBits() ); + String uuid = player.getUUID().toString(); // Get the cached mine, if it exists: - Mine mine = getPlayerCache().get( playerUUIDLSB ); + Mine mine = getPlayerCache().get( uuid ); if ( mine != null && mine.isInMineIncludeTopBottomOfMine( player.getLocation() )) { results = mine; @@ -251,10 +234,10 @@ else if ( player.getLocation() != null ) { // Store the mine in the player cache if not null: if ( results != null ) { - getPlayerCache().put( playerUUIDLSB, results ); + getPlayerCache().put( uuid, results ); } else { - getPlayerCache().remove( playerUUIDLSB ); + getPlayerCache().remove( uuid ); } } @@ -274,12 +257,6 @@ public Mine findMineLocation( Location blockLocation ) { return results; } -// private void initMines() { -//// mines = MineManager.fromDb(); -//// player = new PlayerManager(); -//// Prison.get().getPlatform().getScheduler().runTaskTimer(mines.getTimerTask(), 20, 20); -// } - /** *

    Submit all mines to reset. This should only be called once since @@ -314,14 +291,32 @@ public void cancelResetAllMines() { getMineManager().cancelResetAllMines();; } - + /** + * For modules that have elements, this will return the count. If a module has no + * elements, then it will return a -1. Otherwise a zero would indicate that a module + * should have elements, but it currently has none. + * + * Example would be ranks and mines. For these, if it returns a zero, then they have + * no ranks or mines defined. If it return a -1 then the module is not active. + * + * @return + */ + public int getElementCount() { + int results = isEnabled() ? 0 : -1; + + if ( isEnabled() ) { + results = getMines().size(); + } + + return results; + } + public JsonFileIO getJsonFileIO() { return jsonFileIO; } - public MinesConfig getConfig() { return config; } @@ -350,14 +345,6 @@ public LocaleManager getMinesMessages() { return localeManager; } -// public List getWorlds() { -// return worlds; -// } - -// public PlayerManager getPlayerManager() { -// return player; -// } - public MinesCommands getMinesCommands() { return minesCommands; } @@ -365,5 +352,4 @@ public void setMinesCommands( MinesCommands minesCommands ) { this.minesCommands = minesCommands; } - } 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 304a5a21e..e70313179 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 @@ -43,13 +43,6 @@ public void addBlockCommand(CommandSender sender, Mine m = pMines.getMine(mineName); - // should be able manage blocks even if disabled or virtual: -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - - block = block == null ? null : block.trim().toLowerCase(); PrisonBlock prisonBlock = null; @@ -57,39 +50,32 @@ public void addBlockCommand(CommandSender sender, PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); if ( block != null ) { - prisonBlock = prisonBlockTypes.getBlockTypesByName( block ); + prisonBlock = prisonBlockTypes.getBlockTypesByName( block ); } -// if ( block != null && prisonBlockTypes.getBlockTypesByName().containsKey( block ) ) { -// prisonBlock = prisonBlockTypes.getBlockTypesByName( block ); -// prisonBlock = prisonBlockTypes.getBlockTypesByName().get( block ); -// } if ( prisonBlock == null ) { - pMines.getMinesMessages().getLocalizable("not_a_block"). - withReplacements(block).sendTo(sender); - return; + pMines.getMinesMessages().getLocalizable("not_a_block"). + withReplacements(block).sendTo(sender); + return; } - if ( !prisonBlock.isBlock() ) { - pMines.getMinesMessages().getLocalizable("not_a_block"). - withReplacements(block).sendTo(sender); - return; + if ( prisonBlock.isSellallOnly() ) { + pMines.getMinesMessages().getLocalizable("not_a_block_sellall"). + withReplacements(block).sendTo(sender); + return; } + if ( !prisonBlock.isBlock() ) { + pMines.getMinesMessages().getLocalizable("not_a_block"). + withReplacements(block).sendTo(sender); + return; + } -// if (m.isInMine(prisonBlock)) { -// pMines.getMinesMessages().getLocalizable("block_already_added"). -// sendTo(sender); -// return; -// } -// updateMinePrisonBlock( sender, m, prisonBlock, chance, pMines ); - getBlocksList(m, null, true ).send(sender); - //pMines.getMineManager().clearCache(); } private void updateMinePrisonBlock( CommandSender sender, Mine m, PrisonBlock prisonBlock, @@ -102,9 +88,9 @@ private void updateMinePrisonBlock( CommandSender sender, Mine m, PrisonBlock pr sender.sendMessage( "The percent chance must have a value greater than zero." ); } else { - - // Check if one of the blocks is effected by gravity, and if so, set that indicator. - m.checkGravityAffectedBlocks(); + + // Check if one of the blocks is effected by gravity, and if so, set that indicator. + m.checkGravityAffectedBlocks(); // Delete the block since it exists and the chance was set to zero: @@ -266,11 +252,14 @@ private void addBlockStats( Mine mine, PrisonBlockStatusData block, PlaceholdersUtil.formattedKmbtSISize( 1.0d * block.getBlockCountTotal(), dFmt, "" ) ) ) .tooltip( "&3T&7otal blocks of this type that have been mined." ); row.addFancy( msg3 ); + + + if ( block.isPreventDrops() ) { + FancyMessage msg4 = new FancyMessage( " &dNoDrops!" ) + .tooltip( "&9This block will not drop anything. &3BlockEvents can be used to reward player."); + row.addFancy( msg4 ); + } -// FancyMessage msg4 = new FancyMessage( String.format( (totals ? "&b%-9s" : " &3S: &7%-9s"), -// PlaceholdersUtil.formattedKmbtSISize( 1.0d * block.getBlockCountTotal(), dFmt, "" ) ) ) -// .tooltip( "&7Blocks of this type that have been mined since the server was &3S&7tarted." ); -// row.addFancy( msg4 ); builder.add( row ); @@ -328,12 +317,6 @@ public void setBlockCommand(CommandSender sender, PrisonMines pMines = PrisonMines.getInstance(); Mine m = pMines.getMine(mineName); - // you should be able to configure virtual and disabled mines -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - block = block == null ? null : block.trim().toLowerCase(); @@ -342,86 +325,65 @@ public void setBlockCommand(CommandSender sender, PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); if ( block != null ) { - prisonBlock = prisonBlockTypes.getBlockTypesByName( block ); + prisonBlock = prisonBlockTypes.getBlockTypesByName( block ); } if ( block == null || prisonBlock == null ) { - sender.sendMessage( - String.format( "Invalid blockk name: [%s]", block ) ); - return; + 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)) { - addBlockCommand( sender, mineName, block, chance ); -// pMines.getMinesMessages().getLocalizable("block_not_removed") -// .sendTo(sender); - return; + addBlockCommand( sender, mineName, block, chance ); + return; } updateMinePrisonBlock( sender, m, prisonBlock, chance, pMines ); - getBlocksList(m, null, true ).send(sender); - //pMines.getMineManager().clearCache(); - } -// private BlockPercentTotal calculatePercentage( double chance, BlockType blockType, Mine m ) { -// BlockPercentTotal results = new BlockPercentTotal(); -// results.addChance( chance ); -// -// for ( BlockOld block : m.getBlocks() ) { -// if ( block.getType() == blockType ) { -// // do not replace the block's chance since this may fail -// results.setOldBlock( block ); -// } -// else { -// results.addChance( block.getChance() ); -// } -// } -// -// return results; -// } private BlockPercentTotal calculatePercentage( double chance, PrisonBlock prisonBlock, Mine m ) { - BlockPercentTotal results = new BlockPercentTotal(); - results.addChance( chance ); - - for ( PrisonBlock block : m.getPrisonBlocks() ) { - - // Only check the block's name: - if ( block.equals( prisonBlock ) ) { - // do not replace the block's chance since this may fail - results.setPrisonBlock( block ); - } - else { - results.addChance( block.getChance() ); - } - } - - if ( results.getPrisonBlock() == null ) { - prisonBlock.setChance( chance ); - results.setPrisonBlock( prisonBlock ); - } - return results; + BlockPercentTotal results = new BlockPercentTotal(); + results.addChance( chance ); + + for ( PrisonBlock block : m.getPrisonBlocks() ) { + + // Only check the block's name: + if ( block.equals( prisonBlock ) ) { + // do not replace the block's chance since this may fail + results.setPrisonBlock( block ); + } + else { + results.addChance( block.getChance() ); + } + } + + if ( results.getPrisonBlock() == null ) { + prisonBlock.setChance( chance ); + results.setPrisonBlock( prisonBlock ); + } + return results; } protected class BlockPercentTotal { - private double totalChance = 0d; -// private BlockOld oldBlock = null; - private PrisonBlock prisonBlock = null; - - public BlockPercentTotal() { - } - - public void addChance( double chance ) { - this.totalChance += chance; - } + private double totalChance = 0d; + + private PrisonBlock prisonBlock = null; + + public BlockPercentTotal() { + } + + public void addChance( double chance ) { + this.totalChance += chance; + } public double getTotalChance() { return totalChance; } @@ -429,14 +391,6 @@ public void setTotalChance( double totalChance ) { this.totalChance = totalChance; } - // Obsolete... the old block model: -// public BlockOld getOldBlock() { -// return oldBlock; -// } -// public void setOldBlock( BlockOld oldBlock ) { -// this.oldBlock = oldBlock; -// } - public PrisonBlock getPrisonBlock() { return prisonBlock; } @@ -461,7 +415,6 @@ public void delBlockCommand(CommandSender sender, Mine m = pMines.getMine(mineName); - block = block == null ? null : block.trim().toLowerCase(); PrisonBlock prisonBlock = null; @@ -469,29 +422,24 @@ public void delBlockCommand(CommandSender sender, PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); if ( block != null ) { - prisonBlock = prisonBlockTypes.getBlockTypesByName( block ); + prisonBlock = prisonBlockTypes.getBlockTypesByName( block ); } - // Cannot delete a block if it does not exist: -// if (!m.isInMine(prisonBlock)) { -// return; -// } // make sure the deleteBlock is deleting the actual block stored in the mine: PrisonBlock preexistingPrisonBlock = m.getPrisonBlock( prisonBlock ); if ( preexistingPrisonBlock != null ) { - - deleteBlock( sender, pMines, m, preexistingPrisonBlock ); + + deleteBlock( sender, pMines, m, preexistingPrisonBlock ); } else { - - pMines.getMinesMessages().getLocalizable("block_not_removed") - .sendTo(sender); - return; + + pMines.getMinesMessages().getLocalizable("block_not_removed") + .sendTo(sender); + return; } - getBlocksList(m, null, true).send(sender); } @@ -506,8 +454,8 @@ public void delBlockCommand(CommandSender sender, private void deleteBlock( CommandSender sender, PrisonMines pMines, Mine m, PrisonBlock prisonBlock ) { if ( m.removePrisonBlock( prisonBlock ) ) { - // Check if one of the blocks is effected by gravity, and if so, set that indicator. - m.checkGravityAffectedBlocks(); + // Check if one of the blocks is effected by gravity, and if so, set that indicator. + m.checkGravityAffectedBlocks(); pMines.getMineManager().saveMine( m ); @@ -517,140 +465,98 @@ private void deleteBlock( CommandSender sender, PrisonMines pMines, Mine m, Pris } -// /** -// * Delete only the first occurrence of a block with the given BlockType. -// * -// * @param sender -// * @param pMines -// * @param m -// * @param blockType -// */ -// private void deleteBlock( CommandSender sender, PrisonMines pMines, Mine m, BlockType blockType ) -// { -// BlockOld rBlock = null; -// for ( BlockOld block : m.getBlocks() ) { -// if ( block.getType() == blockType ) { -// rBlock = block; -// break; -// } -// } -// if ( m.getBlocks().remove( rBlock )) { -// -// // Check if one of the blocks is effected by gravity, and if so, set that indicator. -// m.checkGravityAffectedBlocks(); -// -// pMines.getMineManager().saveMine( m ); -// -// pMines.getMinesMessages().getLocalizable("block_deleted") -// .withReplacements(blockType.name(), m.getTag()).sendTo(sender); -// } -// } - public void searchBlockCommand(CommandSender sender, - String search, - String page, - String blockSeachCommand, - String commandBlockAdd, - String targetText ) { - - PrisonMines pMines = PrisonMines.getInstance(); - if (search == null) - { - pMines.getMinesMessages().getLocalizable("block_search_blank").sendTo(sender); - } - - ChatDisplay display = null; - - display = prisonBlockSearchBuilder(search, page, true, - blockSeachCommand, commandBlockAdd, targetText ); + String search, + String page, + String blockSeachCommand, + String commandBlockAdd, + String targetText ) { + + PrisonMines pMines = PrisonMines.getInstance(); + if (search == null) + { + pMines.getMinesMessages().getLocalizable("block_search_blank").sendTo(sender); + } + + ChatDisplay display = null; + + display = prisonBlockSearchBuilder(search, page, true, + blockSeachCommand, commandBlockAdd, targetText, + !sender.isPlayer() ); display.send(sender); - //pMines.getMineManager().clearCache(); } public void searchBlockAllCommand(CommandSender sender, - String search, - String page, - String blockSeachCommand, - String commandBlockAdd, - String targetText ) { - - PrisonMines pMines = PrisonMines.getInstance(); - if (search == null) - { - pMines.getMinesMessages().getLocalizable("block_search_blank").sendTo(sender); - } - - ChatDisplay display = null; + String search, + String page, + String blockSeachCommand, + String commandBlockAdd, + String targetText ) { - display = prisonBlockSearchBuilder(search, page, false, - blockSeachCommand, commandBlockAdd, targetText ); + PrisonMines pMines = PrisonMines.getInstance(); + if (search == null) + { + pMines.getMinesMessages().getLocalizable("block_search_blank").sendTo(sender); + } + + ChatDisplay display = null; + + display = prisonBlockSearchBuilder(search, page, false, + blockSeachCommand, commandBlockAdd, targetText, + !sender.isPlayer() ); + + display.send(sender); - display.send(sender); - - //pMines.getMineManager().clearCache(); } private ChatDisplay prisonBlockSearchBuilder(String search, String page, boolean restrictToBlocks, String commandBlockSearch, String commandBlockAdd, - String targetText ) + String targetText, + boolean console ) { - PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); - List blocks = prisonBlockTypes.getBlockTypes( search, restrictToBlocks ); - - CommandPagedData cmdPageData = new CommandPagedData( - "/" + commandBlockSearch + " " + search, blocks.size(), - 0, page ); - - // Same page logic as in mines info -// int curPage = 1; -// int pageSize = 10; -// int pages = (blocks.size() / pageSize) + 1; -// try -// { -// curPage = Integer.parseInt(page); -// } -// catch ( NumberFormatException e ) -// { -// // Ignore: Not an integer, will use the default value. -// } -// curPage = ( curPage < 1 ? 1 : (curPage > pages ? pages : curPage )); -// int pageStart = (curPage - 1) * pageSize; -// int pageEnd = ((pageStart + pageSize) > blocks.size() ? blocks.size() : pageStart + pageSize); - - - ChatDisplay display = new ChatDisplay("Block Search (" + blocks.size() + ")"); - display.addText("&8Click a block to add it to a " + targetText + "."); - - BulletedListComponent.BulletedListBuilder builder = - new BulletedListComponent.BulletedListBuilder(); - for ( int i = cmdPageData.getPageStart(); i < cmdPageData.getPageEnd(); i++ ) - { - PrisonBlock block = blocks.get(i); - FancyMessage msg = - new FancyMessage( - String.format("&7%s %s (%s)", - Integer.toString(i), block.getBlockNameSearch(), - (block.isBlock() ? "block" : "item") -// block.getAltName(), - )) - .suggest("/" + commandBlockAdd + " " + getLastMineReferenced() + - " " + block.getBlockNameSearch() + " %") - .tooltip("&7Click to add block to a " + targetText + "."); - builder.add(msg); - } - display.addComponent(builder.build()); - - // This command plus parameters used: -// String pageCmd = "/mines block search " + search; - - cmdPageData.generatePagedCommandFooter( display ); - - return display; + PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); + List blocks = prisonBlockTypes.getBlockTypes( search, restrictToBlocks ); + + CommandPagedData cmdPageData = new CommandPagedData( + "/" + commandBlockSearch + " " + search, blocks.size(), + 0, page ); + + + ChatDisplay display = new ChatDisplay("Block Search (" + blocks.size() + ")"); + display.addText("&8Click a block to add it to a " + targetText + "."); + + BulletedListComponent.BulletedListBuilder builder = + new BulletedListComponent.BulletedListBuilder(); + + int start = console ? 0 : cmdPageData.getPageStart(); + int end = console ? blocks.size() : cmdPageData.getPageEnd(); + for ( int i = start; i < end; i++ ) + { + PrisonBlock block = blocks.get(i); + FancyMessage msg = + new FancyMessage( + String.format("&7%s %s (%s)", + Integer.toString(i), block.getBlockNameSearch(), + (block.isBlock() ? "block" : "item") + )) + .suggest("/" + commandBlockAdd + " " + getLastMineReferenced() + + " " + block.getBlockNameSearch() + " %") + .tooltip("&7Click to add block to a " + targetText + "."); + builder.add(msg); + } + display.addComponent(builder.build()); + + if ( !console ) { + + cmdPageData.generatePagedCommandFooter( display ); + } + + return display; } @@ -664,8 +570,8 @@ public void listBlockCommand(CommandSender sender, Mine m = pMines.getMine(mineName); if ( m == null ) { - sender.sendMessage( "Invalid mine name." ); - return; + sender.sendMessage( "Invalid mine name." ); + return; } DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); @@ -699,8 +605,8 @@ public void listBlockCommand(CommandSender sender, if ( blockSize == 0 ) { - String message = blockSize != 0 ? null : " &cNo Blocks Defined"; - chatDisplay.addText( message ); + String message = blockSize != 0 ? null : " &cNo Blocks Defined"; + chatDisplay.addText( message ); } chatDisplay.send(sender); @@ -721,124 +627,123 @@ public void constraintsBlockCommand(CommandSender sender, Mine m = pMines.getMine(mineName); if ( m == null ) { - sender.sendMessage( - String.format( "&7The specified mine named &3%s &7 does not exist. " + - "Please try again.", - (mineName == null ? "null" : mineName) )); - return; + sender.sendMessage( + String.format( "&7The specified mine named &3%s &7 does not exist. " + + "Please try again.", + (mineName == null ? "null" : mineName) )); + return; } if ( constraint == null || !"max".equalsIgnoreCase( constraint ) && !"min".equalsIgnoreCase( constraint ) && !"excludeTop".equalsIgnoreCase( constraint ) && !"excludeBottom".equalsIgnoreCase( constraint ) ) { - sender.sendMessage( - String.format( "Valid contraint values are [min max excludeTop excludeBottom]. " + - "ExcludeTop and ExcludeBottom are expressed in the number of layers. " + - "Was [%s]", - (constraint == null ? "null" : constraint) )); - listBlockCommand(sender, m.getTag() ); - return; + sender.sendMessage( + String.format( "Valid contraint values are [min max excludeTop excludeBottom]. " + + "ExcludeTop and ExcludeBottom are expressed in the number of layers. " + + "Was [%s]", + (constraint == null ? "null" : constraint) )); + listBlockCommand(sender, m.getTag() ); + return; } if ( blockName == null || !m.hasBlock( blockName ) ) { - sender.sendMessage( - String.format( "&7The block name &3%s &7 does not exist in the specified mine. " + - "Please try again.", - (blockName == null ? "null" : blockName) )); - listBlockCommand(sender, m.getTag() ); - return; + sender.sendMessage( + String.format( "&7The block name &3%s &7 does not exist in the specified mine. " + + "Please try again.", + (blockName == null ? "null" : blockName) )); + listBlockCommand(sender, m.getTag() ); + return; } if ( value < 0 ) { - sender.sendMessage( - String.format( "&7The specified value cannot be less than zero. [%s] " + - "Please try again.", - Integer.toString( value ) )); - listBlockCommand(sender, m.getTag() ); - return; + sender.sendMessage( + String.format( "&7The specified value cannot be less than zero. [%s] " + + "Please try again.", + Integer.toString( value ) )); + listBlockCommand(sender, m.getTag() ); + return; } if ( m.getBounds() != null && value > m.getBounds().getTotalBlockCount() ) { - sender.sendMessage( - String.format( "&7The specified value cannot be more than the total number " + - "of blocks in the mine. value = [%s] total blocks = [%s] " + - "Please try again.", - Integer.toString( value ), - Integer.toString( m.getBounds().getTotalBlockCount() ) )); - listBlockCommand(sender, m.getTag() ); - return; + sender.sendMessage( + String.format( "&7The specified value cannot be more than the total number " + + "of blocks in the mine. value = [%s] total blocks = [%s] " + + "Please try again.", + Integer.toString( value ), + Integer.toString( m.getBounds().getTotalBlockCount() ) )); + listBlockCommand(sender, m.getTag() ); + return; } - - PrisonBlockStatusData block = null; - - block = m.getPrisonBlock( blockName ); - - - - if ( "min".equalsIgnoreCase( constraint ) ) { - if ( block.getConstraintMax() != 0 && value > block.getConstraintMax() ) { - sender.sendMessage( - String.format( "&7The specified value for the min constraint cannot " + - "be more than the max constraint value. value = [%s] max= %s " + - "Please try again.", - Integer.toString( value ), - Integer.toString( block.getConstraintMax() ) )); - listBlockCommand(sender, m.getTag() ); - return; - - } - block.setConstraintMin( value ); - } - if ( "max".equalsIgnoreCase( constraint ) ) { - if ( block.getConstraintMin() != 0 && value < block.getConstraintMin() ) { - sender.sendMessage( - String.format( "&7The specified value for the max constraint cannot " + - "be less than the min constraint value. value = [%s] min= %s " + - "Please try again.", - Integer.toString( value ), - Integer.toString( block.getConstraintMin() ) )); - listBlockCommand(sender, m.getTag() ); - return; - - } - block.setConstraintMax( value ); - } - if ( "excludeTop".equalsIgnoreCase( constraint ) ) { - if ( block.getConstraintExcludeBottomLayers() != 0 && - value > block.getConstraintExcludeBottomLayers() ) { - sender.sendMessage( - String.format( "&7The specified value for the ExcludeTop layers constraint cannot " + - "be more than the ExcludeBottom layers constraint value. " + - "value = [%s] ExcludeBottom layers= %s " + - "Please try again.", - Integer.toString( value ), - Integer.toString( block.getConstraintExcludeBottomLayers() ) )); - listBlockCommand(sender, m.getTag() ); - return; - - } - block.setConstraintExcludeTopLayers( value ); - } - if ( "excludeBottom".equalsIgnoreCase( constraint ) ) { - if ( block.getConstraintExcludeTopLayers() != 0 && - value < block.getConstraintExcludeTopLayers() ) { - sender.sendMessage( - String.format( "&7The specified value for the ExcludeBottom layers constraint cannot " + - "be less than the ExcludeTop layers constraint value. " + - "value = [%s] ExcludeTop layers= %s " + - "Please try again.", - Integer.toString( value ), - Integer.toString( block.getConstraintExcludeTopLayers() ) )); - listBlockCommand(sender, m.getTag() ); - return; - - } - block.setConstraintExcludeBottomLayers( value ); - } - - + + PrisonBlockStatusData block = null; + + block = m.getPrisonBlock( blockName ); + + + + if ( "min".equalsIgnoreCase( constraint ) ) { + if ( block.getConstraintMax() != 0 && value > block.getConstraintMax() ) { + sender.sendMessage( + String.format( "&7The specified value for the min constraint cannot " + + "be more than the max constraint value. value = [%s] max= %s " + + "Please try again.", + Integer.toString( value ), + Integer.toString( block.getConstraintMax() ) )); + listBlockCommand(sender, m.getTag() ); + return; + + } + block.setConstraintMin( value ); + } + if ( "max".equalsIgnoreCase( constraint ) ) { + if ( block.getConstraintMin() != 0 && value < block.getConstraintMin() ) { + sender.sendMessage( + String.format( "&7The specified value for the max constraint cannot " + + "be less than the min constraint value. value = [%s] min= %s " + + "Please try again.", + Integer.toString( value ), + Integer.toString( block.getConstraintMin() ) )); + listBlockCommand(sender, m.getTag() ); + return; + + } + block.setConstraintMax( value ); + } + if ( "excludeTop".equalsIgnoreCase( constraint ) ) { + if ( block.getConstraintExcludeBottomLayers() != 0 && + value > block.getConstraintExcludeBottomLayers() ) { + sender.sendMessage( + String.format( "&7The specified value for the ExcludeTop layers constraint cannot " + + "be more than the ExcludeBottom layers constraint value. " + + "value = [%s] ExcludeBottom layers= %s " + + "Please try again.", + Integer.toString( value ), + Integer.toString( block.getConstraintExcludeBottomLayers() ) )); + listBlockCommand(sender, m.getTag() ); + return; + + } + block.setConstraintExcludeTopLayers( value ); + } + if ( "excludeBottom".equalsIgnoreCase( constraint ) ) { + if ( block.getConstraintExcludeTopLayers() != 0 && + value < block.getConstraintExcludeTopLayers() ) { + sender.sendMessage( + String.format( "&7The specified value for the ExcludeBottom layers constraint cannot " + + "be less than the ExcludeTop layers constraint value. " + + "value = [%s] ExcludeTop layers= %s " + + "Please try again.", + Integer.toString( value ), + Integer.toString( block.getConstraintExcludeTopLayers() ) )); + listBlockCommand(sender, m.getTag() ); + return; + + } + block.setConstraintExcludeBottomLayers( value ); + } + pMines.getMineManager().saveMine( m ); @@ -847,12 +752,85 @@ public void constraintsBlockCommand(CommandSender sender, m.getTag(), constraint, (value == 0 ? "disabled" : Integer.toString( value ) )); - sender.sendMessage( message ); - } + + + + public void preventDropsBlockCommand(CommandSender sender, String mineName, String blockName, + String preventDrops) { + + + setLastMineReferenced(mineName); + + PrisonMines pMines = PrisonMines.getInstance(); + Mine m = pMines.getMine(mineName); + + boolean isPreventDrops = false; + + if ( m == null ) { + sender.sendMessage( + String.format( "&7The specified mine named &3%s &7 does not exist. " + + "Please try again.", + (mineName == null ? "null" : mineName) )); + return; + } + + if ( blockName == null || !m.hasBlock( blockName ) ) { + sender.sendMessage( + String.format( "&7The block name &3%s &7 does not exist in the specified mine. " + + "Please try again.", + (blockName == null ? "null" : blockName) )); + listBlockCommand(sender, m.getTag() ); + return; + } + + if ( preventDrops == null || + !preventDrops.equalsIgnoreCase("true") && !preventDrops.equalsIgnoreCase("false") ) { + sender.sendMessage( + String.format( "&7The parameter 'preventDrops' must be boolean: 'true' or 'false'. " + + "Found: [%s]", + (preventDrops == null ? "null" : preventDrops) )); + listBlockCommand(sender, m.getTag() ); + return; + } + + + isPreventDrops = Boolean.parseBoolean( preventDrops ); + + + PrisonBlockStatusData block = null; + + block = m.getPrisonBlock( blockName ); + + + if ( block.isPreventDrops() == isPreventDrops ) { + sender.sendMessage( + String.format( "&7The specified value prevent drops has not changed. " + + "Please try again." + )); + listBlockCommand(sender, m.getTag() ); + return; + } + + block.setPreventDrops( isPreventDrops ); + + + + pMines.getMineManager().saveMine( m ); + + + String message = String.format( "&7Mine &3%s&7's setting for prevent drops for block &3%s &7has been " + + "set to &3%s.", + m.getTag(), block.getBlockName(), + Boolean.toString(isPreventDrops) ); + + + sender.sendMessage( message ); + + } public void listBlockLayerStatsCommand( CommandSender sender, String mineName ) { @@ -865,8 +843,7 @@ public void listBlockLayerStatsCommand( CommandSender sender, String mineName ) Output.get().logInfo( "Mine %s Block Layer Stats:", m.getName() ); - List layers = m.getTargetBlockStatsPerLevel(); - for ( String layer : layers ) { + List layers = m.getTargetBlockStatsPerLevel(); for ( String layer : layers ) { Output.get().logInfo( " " + layer ); } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommandMessages.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommandMessages.java index 6281b61fd..52cbcd957 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommandMessages.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesCommandMessages.java @@ -70,4 +70,16 @@ protected void teleportFailedMsg( CommandSender sender ) { .sendTo( sender ); } + + protected String teleportSuccessMsg( String mineName ) { + // &3Telport failed. Are you sure you're a Player? + String msg = PrisonMines.getInstance().getMinesMessages() + .getLocalizable( "teleport" ) + .withReplacements( + mineName ) + .localize(); + + return msg; + } + } 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 8e7ced08c..055e9b92f 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 @@ -34,15 +34,16 @@ import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.commands.CommandPagedData; import tech.mcprison.prison.commands.Wildcard; +import tech.mcprison.prison.file.JsonFileIO; import tech.mcprison.prison.internal.CommandSender; import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.internal.World; 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; -import tech.mcprison.prison.mines.data.MineData; -import tech.mcprison.prison.mines.data.MineData.MineNotificationMode; +import tech.mcprison.prison.mines.data.Mine.MineNotificationMode; import tech.mcprison.prison.mines.data.MineScheduler.MineResetActions; import tech.mcprison.prison.mines.data.MineScheduler.MineResetScheduleType; import tech.mcprison.prison.mines.data.PrisonSortableResults; @@ -75,7 +76,7 @@ * @author Dylan M. Perks */ public class MinesCommands - extends MinesImportCommands { + extends MinesWorldGuardCommands { public MinesCommands() { super( "MinesCommands" ); @@ -84,26 +85,26 @@ public MinesCommands() { @Command(identifier = "mines command", onlyPlayers = false, permissions = "prison.commands") public void mineCommandSubcommands(CommandSender sender) { - sender.dispatchCommand( "mines command help" ); + sender.dispatchCommand( "mines command help" ); } @Command(identifier = "mines set", onlyPlayers = false, permissions = "prison.commands") public void minesSetSubcommands(CommandSender sender) { - sender.dispatchCommand( "mines set help" ); + sender.dispatchCommand( "mines set help" ); } /* * NOTE: The mines import commands are from the class MinesImportCommands. - * The command handler setups is here, but the code is within that class. + * The command handler setups are here, but the code is within that class. */ @Command(identifier = "mines import", onlyPlayers = false, permissions = "prison.commands") public void mineImport(CommandSender sender) { - sender.dispatchCommand( "mines import help" ); + sender.dispatchCommand( "mines import help" ); } @Command(identifier = "mines import jetsPrisonMines", @@ -131,7 +132,7 @@ public void minesImportJetsPrisonMines( CommandSender sender, + "'save' must be specified or the imported mines will not be saved.") String options ) { - super.importJetsPrisonMines(sender, options); + super.importJetsPrisonMines(sender, options); } @@ -145,13 +146,13 @@ public void minesImportJetsPrisonMines( CommandSender sender, @Command(identifier = "mines block", onlyPlayers = false, permissions = "prison.commands") public void mineBlockSubcommands(CommandSender sender) { - sender.dispatchCommand( "mines block help" ); + sender.dispatchCommand( "mines block help" ); } @Command(identifier = "mines blockEvent", onlyPlayers = false, permissions = "prison.commands") public void mineBlockEventSubcommands(CommandSender sender) { - sender.dispatchCommand( "mines blockEvent help" ); + sender.dispatchCommand( "mines blockEvent help" ); } @Override @@ -165,7 +166,7 @@ public void addBlockCommand(CommandSender sender, @Arg(name = "chance", description = "The percent chance (out of 100) that this block will occur.") double chance) { - super.addBlockCommand( sender, mineName, block, chance ); + super.addBlockCommand( sender, mineName, block, chance ); } @@ -182,7 +183,7 @@ public void setBlockCommand(CommandSender sender, @Arg(name = "chance", description = "The percent chance (out of 100) that this block will occur.") double chance) { - super.setBlockCommand( sender, mineName, block, chance ); + super.setBlockCommand( sender, mineName, block, chance ); } @Override @@ -192,7 +193,7 @@ public void delBlockCommand(CommandSender sender, @Arg(name = "mineName", description = "The name of the mine to edit.") String mineName, @Arg(name = "block", def = "AIR", description = "The block's name") String block) { - super.delBlockCommand( sender, mineName, block ); + super.delBlockCommand( sender, mineName, block ); } @Command(identifier = "mines block search", permissions = "mines.block", @@ -207,7 +208,7 @@ public void searchBlockCommand(CommandSender sender, @Arg(name = "page", def = "1", description = "Page of search results (optional)") String page ) { - super.searchBlockCommand( sender, search, page, + super.searchBlockCommand( sender, search, page, "mines block search", "mines block add", "mine" ); @@ -219,7 +220,7 @@ public void searchBlockAllCommand(CommandSender sender, @Arg(name = "search", def = " ", description = "Any part of the block's, or item's name.") String search, @Arg(name = "page", def = "1", description = "Page of search results (optional)") String page ) { - super.searchBlockAllCommand( sender, search, page, + super.searchBlockAllCommand( sender, search, page, "mines block searchAll", "mines block add", "mine" ); @@ -232,7 +233,7 @@ public void listBlockLayerStatsCommand( CommandSender sender, @Arg(name = "mineName", description = "The name of the mine to generate block layer stats for.") String mineName ) { - super.listBlockLayerStatsCommand( sender, mineName ); + super.listBlockLayerStatsCommand( sender, mineName ); } @@ -242,7 +243,7 @@ public void listBlockLayerStatsCommand( CommandSender sender, public void listBlockCommand(CommandSender sender, @Arg(name = "mineName", description = "The name of the mine to view.") String mineName ) { - super.listBlockCommand( sender, mineName ); + super.listBlockCommand( sender, mineName ); } @Override @@ -255,18 +256,37 @@ public void listBlockCommand(CommandSender sender, + "read as 'excludeBottom from layers 15 and lower'.") public void constraintsBlockCommand(CommandSender sender, @Arg(name = "mineName", description = "The name of the mine to view.") String mineName, - @Arg(name = "blockNme", description = "The block's name") String blockName, + @Arg(name = "blockName", description = "The block's name") String blockName, @Arg(name = "contraint", description = "Constraint to apply " + "[min max excludeTop excludeBottom]", def = "max") String constraint, @Arg(name = "value", description = "The value to assign to this constraint. " + "A value of 0 will remove the constraint.") int value ) { - super.constraintsBlockCommand( sender, mineName, blockName, constraint, value ); + super.constraintsBlockCommand( sender, mineName, blockName, constraint, value ); } + @Override + @Command(identifier = "mines block preventDrops", permissions = "mines.block", + description = "The specified block will not drop anything. It can be mined, but it will " + + "not result in giving the player anything for mining it. Not even money. " + + "This can be used in combination with block commands to create effects " + + "such as Lucky Blocks.") + public void preventDropsBlockCommand(CommandSender sender, + @Arg(name = "mineName", description = "The name of the mine to view.") String mineName, + @Arg(name = "blockName", description = "The block's name") String blockName, + @Arg(name = "preventDrops", description = "Prevent the block from dropping anything " + + "and prevent payment for the breakage. A value of 'true' will prevent the drops. " + + "[true false]", + def = "false") String preventDrops ) { + + super.preventDropsBlockCommand( sender, mineName, blockName, preventDrops ); + } + + + @Command(identifier = "mines create", description = "Creates a new mine, or even a virtual mine. " + @@ -289,61 +309,61 @@ public void createCommand(CommandSender sender, "you want to create. " + "[virtual noPlaceholderUpdate]") String options ) { - options = options == null ? "" : options.trim(); - - boolean virtual = mineName.toLowerCase().contains( "virtual" ); - if ( virtual && !options.isEmpty() ) { - // The option virtual was used in the mineName. Swap fields. - mineName = options.contains( " " ) ? options.split( " " )[0] : options; - } - else { - virtual = options.toLowerCase().contains( "virtual" ); - } - boolean updatePlaceholders = !options.toLowerCase().contains( "noplaceholderupdate" ); - - if ( mineName == null || mineName.contains( " " ) || mineName.trim().length() == 0 ) { - sendMessage( sender, "&3Names cannot contain spaces or be empty. &b[&d" + mineName + "&b]" ); - return; - } - mineName = mineName.trim(); - - Player player = sender.getPlatformPlayer(); - - if ( !virtual && (player == null || !player.isOnline())) { - sendMessage( sender, "&3You must be a player in the game to run this command. " + - "You also need to have selected an area with the `/mines wand` tool. " ); - return; - } - - PrisonMines pMines = PrisonMines.getInstance(); - - if (PrisonMines.getInstance().getMine(mineName) != null) { - pMines.getMinesMessages().getLocalizable("mine_exists") - .sendTo(sender, LogLevel.ERROR); - return; - } - - Selection selection = null; - - // virtual mine will skip the setting of the boundaries, but it will make - // the mine unusable. - if ( !virtual ) { - - selection = Prison.get().getSelectionManager().getSelection(player); - if (!selection.isComplete()) { - pMines.getMinesMessages().getLocalizable("select_bounds") - .sendTo(sender, LogLevel.ERROR); - return; - } - - if (!selection.getMin().getWorld().getName() - .equalsIgnoreCase(selection.getMax().getWorld().getName())) { - pMines.getMinesMessages().getLocalizable("world_diff") - .sendTo(sender, LogLevel.ERROR); - return; - } - } - + options = options == null ? "" : options.trim(); + + boolean virtual = mineName.toLowerCase().contains( "virtual" ); + if ( virtual && !options.isEmpty() ) { + // The option virtual was used in the mineName. Swap fields. + mineName = options.contains( " " ) ? options.split( " " )[0] : options; + } + else { + virtual = options.toLowerCase().contains( "virtual" ); + } + boolean updatePlaceholders = !options.toLowerCase().contains( "noplaceholderupdate" ); + + if ( mineName == null || mineName.contains( " " ) || mineName.trim().length() == 0 ) { + sendMessage( sender, "&3Names cannot contain spaces or be empty. &b[&d" + mineName + "&b]" ); + return; + } + mineName = mineName.trim(); + + Player player = sender.getPlatformPlayer(); + + if ( !virtual && (player == null || !player.isOnline())) { + sendMessage( sender, "&3You must be a player in the game to run this command. " + + "You also need to have selected an area with the `/mines wand` tool. " ); + return; + } + + PrisonMines pMines = PrisonMines.getInstance(); + + if (PrisonMines.getInstance().getMine(mineName) != null) { + pMines.getMinesMessages().getLocalizable("mine_exists") + .sendTo(sender, LogLevel.ERROR); + return; + } + + Selection selection = null; + + // virtual mine will skip the setting of the boundaries, but it will make + // the mine unusable. + if ( !virtual ) { + + selection = Prison.get().getSelectionManager().getSelection(player); + if (!selection.isComplete()) { + pMines.getMinesMessages().getLocalizable("select_bounds") + .sendTo(sender, LogLevel.ERROR); + return; + } + + if (!selection.getMin().getWorld().getName() + .equalsIgnoreCase(selection.getMax().getWorld().getName())) { + pMines.getMinesMessages().getLocalizable("world_diff") + .sendTo(sender, LogLevel.ERROR); + return; + } + } + setLastMineReferenced(mineName); @@ -356,27 +376,27 @@ public void createCommand(CommandSender sender, } if ( mine.isVirtual() ) { - sendMessage( sender, "&3Virtual mine created: use command " + - "&7'/mines set area help'&3 set an area within a world to " + - "enable as a normal mine." ); + sendMessage( sender, "&3Virtual mine created: use command " + + "&7'/mines set area help'&3 set an area within a world to " + + "enable as a normal mine." ); } else { - pMines.getMinesMessages().getLocalizable("mine_created").sendTo(sender); + pMines.getMinesMessages().getLocalizable("mine_created").sendTo(sender); } if ( !virtual && sender != null && sender instanceof Player ) { - // Delete the selection: - Prison.get().getSelectionManager().clearSelection((Player) sender); + // Delete the selection: + Prison.get().getSelectionManager().clearSelection((Player) sender); } } private void sendMessage( CommandSender sender, String message ) { - if ( sender == null ) { - Output.get().logInfo( message ); - } - else { - sender.sendMessage( message ); - } + if ( sender == null ) { + Output.get().logInfo( message ); + } + else { + sender.sendMessage( message ); + } } @Command(identifier = "mines rename", description = "Rename a mine.", @@ -391,35 +411,35 @@ public void renameCommand(CommandSender sender, return; } - if ( newName == null || newName.contains( " " ) || newName.trim().length() == 0 ) { - sender.sendMessage( "&3New mine name cannot contain spaces or be empty. &b[&d" + newName + "&b]" ); - return; - } - newName = newName.trim(); - - PrisonMines pMines = PrisonMines.getInstance(); - - if ( pMines.getMine(newName) != null ) { - sender.sendMessage( "&3Invalid new mine name. Another mine has that name. &b[&d" + newName + "&b]" ); - return; - - } - - Mine mine = pMines.getMine(mineName); - - setLastMineReferenced(newName); - - - pMines.getMineManager().rename(mine, newName); - - - Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); - - - sender.sendMessage( String.format( "&3Mine &d%s &3was successfully renamed to &d%s&3.", mineName, newName) ); - - pMines.getMinesMessages().getLocalizable("mine_created").sendTo(sender); - + if ( newName == null || newName.contains( " " ) || newName.trim().length() == 0 ) { + sender.sendMessage( "&3New mine name cannot contain spaces or be empty. &b[&d" + newName + "&b]" ); + return; + } + newName = newName.trim(); + + PrisonMines pMines = PrisonMines.getInstance(); + + if ( pMines.getMine(newName) != null ) { + sender.sendMessage( "&3Invalid new mine name. Another mine has that name. &b[&d" + newName + "&b]" ); + return; + + } + + Mine mine = pMines.getMine(mineName); + + setLastMineReferenced(newName); + + + pMines.getMineManager().rename(mine, newName); + + + Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); + + + sender.sendMessage( String.format( "&3Mine &d%s &3was successfully renamed to &d%s&3.", mineName, newName) ); + + pMines.getMinesMessages().getLocalizable("mine_created").sendTo(sender); + } @@ -434,48 +454,48 @@ public void mineAccessByRankCommand(CommandSender sender, @Arg(name = "mineName", description = "The name of the mine, or *all* for all mines. [*all*]") String mineName, @Arg(name = "enable", description = "Enable the mineAccessByRank: [enable, disable]") String enable ) { - if ( enable == null || !"enable".equalsIgnoreCase( enable ) && !"disable".equalsIgnoreCase( enable ) ) { - - sender.sendMessage( "&cInvalid option. &7The parameter &3enable &7can only have the values of " + - "'enable' or 'disable'. Please try again." ); - return; - } - - boolean accessEnabled = "enable".equalsIgnoreCase( enable ); - - PrisonMines pMines = PrisonMines.getInstance(); - - if ( mineName != null && "*all*".equalsIgnoreCase( mineName ) ) { - int minesUpdated = 0; - int minesNoChange = 0; - int minesWithNoRanks = 0; - - for ( Mine m :pMines.getMines() ) { - if ( m.getRank() == null ) { - minesWithNoRanks++; - } - else if ( m.isMineAccessByRank() == accessEnabled ) { - minesNoChange++; - } - else { - minesUpdated++; - - m.setMineAccessByRank( accessEnabled ); - pMines.getMineManager().saveMine(m); - } - } - - String message = String.format( "&7%s Mine Access by Rank changes were applied to all Mines. " + - "%d were updated. %d had no changes. %d had no ranks so could not be set.", - - (accessEnabled ? "Enabling" : "Disabling"), - minesUpdated, minesNoChange, minesWithNoRanks - ); - - sender.sendMessage( message ); - - return; - } + if ( enable == null || !"enable".equalsIgnoreCase( enable ) && !"disable".equalsIgnoreCase( enable ) ) { + + sender.sendMessage( "&cInvalid option. &7The parameter &3enable &7can only have the values of " + + "'enable' or 'disable'. Please try again." ); + return; + } + + boolean accessEnabled = "enable".equalsIgnoreCase( enable ); + + PrisonMines pMines = PrisonMines.getInstance(); + + if ( mineName != null && "*all*".equalsIgnoreCase( mineName ) ) { + int minesUpdated = 0; + int minesNoChange = 0; + int minesWithNoRanks = 0; + + for ( Mine m :pMines.getMines() ) { + if ( m.getRank() == null ) { + minesWithNoRanks++; + } + else if ( m.isMineAccessByRank() == accessEnabled ) { + minesNoChange++; + } + else { + minesUpdated++; + + m.setMineAccessByRank( accessEnabled ); + pMines.getMineManager().saveMine(m); + } + } + + String message = String.format( "&7%s Mine Access by Rank changes were applied to all Mines. " + + "%d were updated. %d had no changes. %d had no ranks so could not be set.", + + (accessEnabled ? "Enabling" : "Disabling"), + minesUpdated, minesNoChange, minesWithNoRanks + ); + + sender.sendMessage( message ); + + return; + } if (!performCheckMineExists(sender, mineName)) { return; @@ -518,49 +538,49 @@ public void tpAccessByRankCommand(CommandSender sender, @Arg(name = "mineName", description = "The name of the mine, or *all* for all mines. [*all*]") String mineName, @Arg(name = "enable", description = "Enable the tpAccessByRank: [enable, disable]") String enable ) { - if ( enable == null || !"enable".equalsIgnoreCase( enable ) && !"disable".equalsIgnoreCase( enable ) ) { - - sender.sendMessage( "&cInvalid option. &7The parameter &3enable &7can only have the values of " + - "'enable' or 'disable'. Please try again." ); - return; - } - - boolean accessEnabled = "enable".equalsIgnoreCase( enable ); - - PrisonMines pMines = PrisonMines.getInstance(); - - - if ( mineName != null && "*all*".equalsIgnoreCase( mineName ) ) { - int minesUpdated = 0; - int minesNoChange = 0; - int minesWithNoRanks = 0; - - for ( Mine m :pMines.getMines() ) { - if ( m.getRank() == null ) { - minesWithNoRanks++; - } - else if ( m.isTpAccessByRank() == accessEnabled ) { - minesNoChange++; - } - else { - minesUpdated++; - - m.setTpAccessByRank( accessEnabled ); - pMines.getMineManager().saveMine(m); - } - } - - String message = String.format( "&7%s Mine TP Access by Rank changes were applied to all Mines. " + - "%d were updated. %d had no changes. %d had no ranks so could not be set.", - - (accessEnabled ? "Enabling" : "Disabling"), - minesUpdated, minesNoChange, minesWithNoRanks - ); - - sender.sendMessage( message ); - - return; - } + if ( enable == null || !"enable".equalsIgnoreCase( enable ) && !"disable".equalsIgnoreCase( enable ) ) { + + sender.sendMessage( "&cInvalid option. &7The parameter &3enable &7can only have the values of " + + "'enable' or 'disable'. Please try again." ); + return; + } + + boolean accessEnabled = "enable".equalsIgnoreCase( enable ); + + PrisonMines pMines = PrisonMines.getInstance(); + + + if ( mineName != null && "*all*".equalsIgnoreCase( mineName ) ) { + int minesUpdated = 0; + int minesNoChange = 0; + int minesWithNoRanks = 0; + + for ( Mine m :pMines.getMines() ) { + if ( m.getRank() == null ) { + minesWithNoRanks++; + } + else if ( m.isTpAccessByRank() == accessEnabled ) { + minesNoChange++; + } + else { + minesUpdated++; + + m.setTpAccessByRank( accessEnabled ); + pMines.getMineManager().saveMine(m); + } + } + + String message = String.format( "&7%s Mine TP Access by Rank changes were applied to all Mines. " + + "%d were updated. %d had no changes. %d had no ranks so could not be set.", + + (accessEnabled ? "Enabling" : "Disabling"), + minesUpdated, minesNoChange, minesWithNoRanks + ); + + sender.sendMessage( message ); + + return; + } if (!performCheckMineExists(sender, mineName)) { return; @@ -570,15 +590,15 @@ else if ( m.isTpAccessByRank() == accessEnabled ) { if ( mine.getRank() == null ) { - sender.sendMessage( "&cThis mine must be linked to a Rank before you can enable this feature." ); - return; + sender.sendMessage( "&cThis mine must be linked to a Rank before you can enable this feature." ); + return; } if ( mine.isTpAccessByRank() == accessEnabled ) { - sender.sendMessage( - String.format( "&cInvalid setting. &7The mine's setting tpAccessByRank has not been " + - "changed. The mine already is set to the value of: [%s]", enable ) ); - return; + sender.sendMessage( + String.format( "&cInvalid setting. &7The mine's setting tpAccessByRank has not been " + + "changed. The mine already is set to the value of: [%s]", enable ) ); + return; } @@ -601,12 +621,12 @@ public void spawnpointCommand(CommandSender sender, @Arg(name = "options", def = "set", description = "Options: Option to set or remove a spawn. [set *remove*]") String options ) { - Player player = sender.getPlatformPlayer(); - - if (player == null || !player.isOnline()) { - sender.sendMessage( "&3You must be a player in the game to run this command." ); - return; - } + Player player = sender.getPlatformPlayer(); + + if (player == null || !player.isOnline()) { + sender.sendMessage( "&3You must be a player in the game to run this command." ); + return; + } if (!performCheckMineExists(sender, mineName)) { return; @@ -617,13 +637,13 @@ public void spawnpointCommand(CommandSender sender, if ( mine.isVirtual() ) { - sender.sendMessage( "&cMine is a virtual mine&7. Use &a/mines set area &7to enable the mine." ); - return; + sender.sendMessage( "&cMine is a virtual mine&7. Use &a/mines set area &7to enable the mine." ); + return; } if ( !mine.isEnabled() ) { - sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); - return; + sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); + return; } if (!mine.getWorld().isPresent()) { @@ -643,13 +663,13 @@ public void spawnpointCommand(CommandSender sender, setLastMineReferenced(mineName); if ( options != null && options.toLowerCase().contains( "*remove*" ) ) { - mine.setSpawn( null ); - pMines.getMinesMessages().getLocalizable("spawn_removed").sendTo(sender); + mine.setSpawn( null ); + pMines.getMinesMessages().getLocalizable("spawn_removed").sendTo(sender); } else { - mine.setSpawn(((Player) sender).getLocation()); - pMines.getMinesMessages().getLocalizable("spawn_set").sendTo(sender); + mine.setSpawn(((Player) sender).getLocation()); + pMines.getMinesMessages().getLocalizable("spawn_set").sendTo(sender); } pMines.getMineManager().saveMine(mine); @@ -668,12 +688,12 @@ public void tagCommand(CommandSender sender, } if ( tag == null || tag.trim().length() == 0 ) { - sender.sendMessage( "&cTag name must be a valid value. To remove use a value of &anull&c." ); - return; + sender.sendMessage( "&cTag name must be a valid value. To remove use a value of &anull&c." ); + return; } if ( tag.equalsIgnoreCase( "null" ) ) { - tag = null; + tag = null; } PrisonMines pMines = PrisonMines.getInstance(); @@ -683,8 +703,8 @@ public void tagCommand(CommandSender sender, mine.getTag() != null && mine.getTag().equalsIgnoreCase( tag )) { - sender.sendMessage( "&cThe new tag name is the same as what it was. No change was made." ); - return; + sender.sendMessage( "&cThe new tag name is the same as what it was. No change was made." ); + return; } mine.setTag( tag ); @@ -695,14 +715,14 @@ public void tagCommand(CommandSender sender, if ( tag == null ) { - sender.sendMessage( - String.format( "&cThe tag name was cleared for the mine %s.", - mine.getTag() ) ); + sender.sendMessage( + String.format( "&cThe tag name was cleared for the mine %s.", + mine.getTag() ) ); } else { - sender.sendMessage( - String.format( "&cThe tag name was changed to %s for the mine %s.", - tag, mine.getTag() ) ); + sender.sendMessage( + String.format( "&cThe tag name was changed to %s for the mine %s.", + tag, mine.getTag() ) ); } } @@ -718,18 +738,18 @@ public void sortOrderCommand(CommandSender sender, "of -1 or [supress] will prevent the mine from beign included in most listings.", def = "0" ) String sortOrder ) { - int order = 0; - - if (!performCheckMineExists(sender, mineName)) { - return; - } - - if ( sortOrder == null ) { - sortOrder = "0"; - } - else if ( "suppress".equalsIgnoreCase( sortOrder.trim() ) ) { - sortOrder = "-1"; - } + int order = 0; + + if (!performCheckMineExists(sender, mineName)) { + return; + } + + if ( sortOrder == null ) { + sortOrder = "0"; + } + else if ( "suppress".equalsIgnoreCase( sortOrder.trim() ) ) { + sortOrder = "-1"; + } try { order = Integer.parseInt( sortOrder ); @@ -744,26 +764,26 @@ else if ( "suppress".equalsIgnoreCase( sortOrder.trim() ) ) { order = -1; } - PrisonMines pMines = PrisonMines.getInstance(); - Mine mine = pMines.getMine(mineName); - - if ( order == mine.getSortOrder()) { - sender.sendMessage( "&cThe new sort order is the same as what it was. No change was made." ); - return; - } - - mine.setSortOrder( order ); - - setLastMineReferenced(mineName); - - pMines.getMineManager().saveMine(mine); - - String suppressedMessage = order == -1 ? "This mine will be suppressed from most listings." : ""; - sender.sendMessage( - String.format( "&cThe sort order was changed to %s for the mine %s. %s", - Integer.toString( mine.getSortOrder() ), mine.getTag(), - suppressedMessage ) ); - + PrisonMines pMines = PrisonMines.getInstance(); + Mine mine = pMines.getMine(mineName); + + if ( order == mine.getSortOrder()) { + sender.sendMessage( "&cThe new sort order is the same as what it was. No change was made." ); + return; + } + + mine.setSortOrder( order ); + + setLastMineReferenced(mineName); + + pMines.getMineManager().saveMine(mine); + + String suppressedMessage = order == -1 ? "This mine will be suppressed from most listings." : ""; + sender.sendMessage( + String.format( "&cThe sort order was changed to %s for the mine %s. %s", + Integer.toString( mine.getSortOrder() ), mine.getTag(), + suppressedMessage ) ); + } @@ -780,73 +800,70 @@ public void deleteCommand(CommandSender sender, // They have 1 minute to confirm. long now = System.currentTimeMillis(); if ( getConfirmTimestamp() != null && ((now - getConfirmTimestamp()) < 1000 * 60 ) && - confirm != null && "confirm".equalsIgnoreCase( confirm )) { - setConfirmTimestamp( null ); - - PrisonMines pMines = PrisonMines.getInstance(); - - Mine mine = pMines.getMine(mineName); - - // should be able to delete disabled and virtual mines: -// if ( !mine.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - - // Remove from the manager: - pMines.getMineManager().removeMine(mine); - - // Terminate the running task for mine resets. Will allow it to be garbage collected. - mine.terminateJob(); - - setLastMineReferenced(null); - - - Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); - - - pMines.getMinesMessages().getLocalizable("mine_deleted").sendTo(sender); - - } + confirm != null && "confirm".equalsIgnoreCase( confirm )) { + + setConfirmTimestamp( null ); + + PrisonMines pMines = PrisonMines.getInstance(); + + Mine mine = pMines.getMine(mineName); + + // Remove from the manager: + pMines.getMineManager().removeMine(mine); + + // Terminate the running task for mine resets. Will allow it to be garbage collected. + mine.terminateJob(); + + setLastMineReferenced(null); + + + Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); + + + pMines.getMinesMessages().getLocalizable("mine_deleted").sendTo(sender); + + } else if ( getConfirmTimestamp() == null || ((now - getConfirmTimestamp()) >= 1000 * 60 ) ) { - setConfirmTimestamp( now ); - - ChatDisplay chatDisplay = new ChatDisplay("&cDelete " + mineName); - BulletedListComponent.BulletedListBuilder builder = new BulletedListComponent.BulletedListBuilder(); - builder.add( new FancyMessage( - "&3Confirm the deletion of this mine" ) - .suggest("/mines delete " + mineName + " cancel")); - - builder.add( new FancyMessage( - "&3Click &eHERE&3 to display the command" ) - .suggest("/mines delete " + mineName + " cancel")); - - builder.add( new FancyMessage( - "&3Enter: &7/mines delete " + mineName + " confirm" ) - .suggest("/mines delete " + mineName + " cancel")); - - builder.add( new FancyMessage( - "&3Then change &ecancel&3 to &econfirm&3." ) - .suggest("/mines delete " + mineName + " cancel")); - - builder.add( new FancyMessage("You have 1 minute to respond.")); - - chatDisplay.addComponent(builder.build()); - chatDisplay.send(sender); + setConfirmTimestamp( now ); + + ChatDisplay chatDisplay = new ChatDisplay("&cDelete " + mineName); + BulletedListComponent.BulletedListBuilder builder = new BulletedListComponent.BulletedListBuilder(); + builder.add( new FancyMessage( + "&3Confirm the deletion of this mine" ) + .suggest("/mines delete " + mineName + " cancel")); + + builder.add( new FancyMessage( + "&3Click &eHERE&3 to display the command" ) + .suggest("/mines delete " + mineName + " cancel")); + + builder.add( new FancyMessage( + "&3Enter: &7/mines delete " + mineName + " confirm" ) + .suggest("/mines delete " + mineName + " cancel")); + + builder.add( new FancyMessage( + "&3Then change &ecancel&3 to &econfirm&3." ) + .suggest("/mines delete " + mineName + " cancel")); + + builder.add( new FancyMessage("You have 1 minute to respond.")); + + chatDisplay.addComponent(builder.build()); + chatDisplay.send(sender); - } else if (confirm != null && "cancel".equalsIgnoreCase( confirm )) { - setConfirmTimestamp( null ); + } + else if (confirm != null && "cancel".equalsIgnoreCase( confirm )) { - ChatDisplay display = new ChatDisplay("&cDelete " + mineName); + setConfirmTimestamp( null ); + + ChatDisplay display = new ChatDisplay("&cDelete " + mineName); display.addText("&8Delete canceled."); display.send( sender ); } else { - ChatDisplay display = new ChatDisplay("&cDelete " + mineName); - display.addText("&8Delete confirmation failed. Try again."); - - display.send( sender ); + ChatDisplay display = new ChatDisplay("&cDelete " + mineName); + display.addText("&8Delete confirmation failed. Try again."); + + display.send( sender ); } } @@ -860,6 +877,7 @@ public void infoCommand(CommandSender sender, @Arg(name = "page", def = "1", description = "Page of search results (optional) [1-n, ALL]") String page ) { + if (!performCheckMineExists(sender, mineName)) { return; } @@ -868,7 +886,7 @@ public void infoCommand(CommandSender sender, setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); - MineManager mMan = pMines.getMineManager(); + MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); @@ -880,23 +898,6 @@ public void infoCommand(CommandSender sender, 1, page ); -// // Same page logic as in mines block search: -// int curPage = 1; -// int pageSize = 10; -// int pages = (m.getBlocks().size() / pageSize) + 1; -// try -// { -// curPage = Integer.parseInt(page); -// } -// catch ( NumberFormatException e ) -// { -// // Ignore: Not an integer, will use the default value. -// } -// curPage = ( curPage < 1 ? 1 : (curPage > pages ? pages : curPage )); -// int pageStart = (curPage - 1) * pageSize; -// int pageEnd = ((pageStart + pageSize) > m.getBlocks().size() ? m.getBlocks().size() : pageStart + pageSize); - - ChatDisplay chatDisplay = mineInfoDetails( sender, mMan.isMineStats(), m, cmdPageData ); @@ -909,42 +910,34 @@ public void infoCommand(CommandSender sender, chatDisplay.send(sender); - // If show all, then include the mine's commands and blockEvents: - // These are different commands, so they will be in different chatDisplay objects - // so cannot weave them together: - // if ( cmdPageData.isShowAll() ) { - //commandList( sender, m.getName() ); - - //blockEventList( sender, m.getName() ); - // } } public void allMinesInfoDetails( StringBuilder sb ) { - PrisonMines pMines = PrisonMines.getInstance(); - MineManager mMan = pMines.getMineManager(); - - List mines = new ArrayList<>(); - mines.addAll( mMan.getMines() ); - Collections.sort( mines ); - - for ( Mine mine : mines ) { - - Prison.get().getPrisonStatsUtil().printFooter( sb ); - - JumboTextFont.makeJumboFontText( mine.getName(), sb ); - sb.append( "\n" ); - - CommandPagedData cmdPageData = new CommandPagedData( - "/mines info " + mine.getName(), mine.getPrisonBlocks().size(), - 1, "all" ); - - ChatDisplay chatDisplay = mineInfoDetails( null, mMan.isMineStats(), mine, cmdPageData ); - - sb.append( chatDisplay.toStringBuilder() ); - } - - Prison.get().getPrisonStatsUtil().printFooter( sb ); + PrisonMines pMines = PrisonMines.getInstance(); + MineManager mMan = pMines.getMineManager(); + + List mines = new ArrayList<>(); + mines.addAll( mMan.getMines() ); + Collections.sort( mines ); + + for ( Mine mine : mines ) { + + Prison.get().getPrisonStatsUtil().printFooter( sb ); + + JumboTextFont.makeJumboFontText( mine.getName(), sb ); + sb.append( "\n" ); + + CommandPagedData cmdPageData = new CommandPagedData( + "/mines info " + mine.getName(), mine.getPrisonBlocks().size(), + 1, "all" ); + + ChatDisplay chatDisplay = mineInfoDetails( null, mMan.isMineStats(), mine, cmdPageData ); + + sb.append( chatDisplay.toStringBuilder() ); + } + + Prison.get().getPrisonStatsUtil().printFooter( sb ); } @@ -953,428 +946,393 @@ private ChatDisplay mineInfoDetails( CommandSender sender, boolean isMineStats, DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); DecimalFormat fFmt = Prison.get().getDecimalFormat("#,##0.00"); - ChatDisplay chatDisplay = new ChatDisplay("&bMine: &3" + m.getName()); + ChatDisplay chatDisplay = new ChatDisplay("&bMine: &3" + m.getTag()); chatDisplay.addSupportHyperLinkData( "Mine %s", m.getName() ); { - RowComponent row = new RowComponent(); - row.addTextComponent("&7Server runtime: %s ", - Prison.get().getServerRuntimeFormatted() ); - - double tps = Prison.get().getPrisonTPS().getAverageTPS(); - String tpsFmt = tps >= 18.5 ? "&a" : - tps >= 16.0 ? "&e" : - tps >= 14.0 ? "&6" : - "&c"; - row.addTextComponent("&7TPS: %s%s", - tpsFmt, - fFmt.format( tps)); - - chatDisplay.addComponent( row ); + RowComponent row = new RowComponent(); + row.addTextComponent("&7Server runtime: %s ", + Prison.get().getServerRuntimeFormatted() ); + + double tps = Prison.get().getPrisonTPS().getAverageTPS(); + String tpsFmt = tps >= 18.5 ? "&a" : + tps >= 16.0 ? "&e" : + tps >= 14.0 ? "&6" : + "&c"; + row.addTextComponent("&7TPS: %s%s", + tpsFmt, + fFmt.format( tps)); + + chatDisplay.addComponent( row ); } // Display Mine Info only: if ( cmdPageData.getCurPage() == 1 ) { - if ( m.isVirtual() ) { - chatDisplay.addText("&cWarning!! This mine is &lVirtual&r&c!! &7Use &3/mines set area &7to enable." ); - } - - if ( !m.isEnabled() ) { - chatDisplay.addText("&cWarning!! This mine is &lDISABLED&r&c!!" ); - } - - - boolean mineAccessByRank = m.isMineAccessByRank(); - boolean tpAccessByRank = m.isTpAccessByRank(); - - if ( mineAccessByRank && tpAccessByRank ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Mine Access by Rank. TP Access by Rank." ); - chatDisplay.addComponent( row ); - } - else if ( !mineAccessByRank && tpAccessByRank ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3TP Access by Rank." ); - chatDisplay.addComponent( row ); - } - if ( mineAccessByRank && !tpAccessByRank ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Mine Access by Rank." ); - chatDisplay.addComponent( row ); - } - - if ( !mineAccessByRank ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Mine Access Permission: &7%s &3(Consider using Access by Rank)", - ( m.getAccessPermission() == null ? "&2none" : m.getAccessPermission() ) ); - chatDisplay.addComponent( row ); - } - - - { - RowComponent row = new RowComponent(); - - String noTagMessag = String.format( "&7(not set)" ); - row.addTextComponent("&3Tag: &7%-11s ", - m.getTag() == null ? noTagMessag : m.getTag()); - - if ( m.getRank() == null ) { - row.addTextComponent( "&3No rank is linked to this mine." ); - } - else { - row.addTextComponent( "&3Rank: &7%s", m.getRank() ); - } - - - chatDisplay.addComponent( row ); - } - - + if ( m.isVirtual() ) { + chatDisplay.addText("&cWarning!! This mine is &lVirtual&r&c!! &7Use &3/mines set area &7to enable." ); + } + + if ( !m.isEnabled() ) { + chatDisplay.addText("&cWarning!! This mine is &lDISABLED&r&c!!" ); + } + + + boolean mineAccessByRank = m.isMineAccessByRank(); + boolean tpAccessByRank = m.isTpAccessByRank(); + + if ( mineAccessByRank && tpAccessByRank ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Mine Access by Rank. TP Access by Rank." ); + chatDisplay.addComponent( row ); + } + else if ( !mineAccessByRank && tpAccessByRank ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3TP Access by Rank." ); + chatDisplay.addComponent( row ); + } + if ( mineAccessByRank && !tpAccessByRank ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Mine Access by Rank." ); + chatDisplay.addComponent( row ); + } + + if ( !mineAccessByRank ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Mine Access Permission: &7%s &3(Consider using Access by Rank)", + ( m.getAccessPermission() == null ? "&2none" : m.getAccessPermission() ) ); + chatDisplay.addComponent( row ); + } + + + { + RowComponent row = new RowComponent(); + + String noTagMessag = String.format( "&7(not set)" ); + row.addTextComponent("&3Tag: &7%-11s ", + m.getTag() == null ? noTagMessag : m.getTag()); + + if ( m.getRank() == null ) { + row.addTextComponent( "&3No rank is linked to this mine." ); + } + else { + row.addTextComponent( "&3Rank: &7%s", m.getRank() ); + } + + + chatDisplay.addComponent( row ); + } + + + + + + if ( !m.isVirtual() ) { + String worldName = m.getWorld().isPresent() ? m.getWorld().get().getName() : "&cmissing"; + Player player = sender == null ? null : sender.getPlatformPlayer(); + chatDisplay.addText("&3World: &7%-10s &3Center: &7%s &3%s &7%s", + worldName, + m.getBounds().getCenter().toBlockCoordinates(), + (player == null ? "" : "Distance:"), + (player == null ? "" : fFmt.format( m.getBounds().getDistance3d( player.getLocation() ) )) + ); + + + String minCoords = m.getBounds().getMin().toBlockCoordinates(); + String maxCoords = m.getBounds().getMax().toBlockCoordinates(); + chatDisplay.addText("&3Bounds: &7%s &8to &7%s", minCoords, maxCoords); + + String spawnPoint = m.getSpawn() != null ? m.getSpawn().toBlockCoordinates() : "&cnot set"; + chatDisplay.addText("&3Spawnpoint: &7%s", spawnPoint); + + } + + + + + if ( !m.isVirtual() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Size: &7%d&8x&7%d&8x&7%d ", Math.round(m.getBounds().getWidth()), + Math.round(m.getBounds().getHeight()), Math.round(m.getBounds().getLength()) ); + + row.addTextComponent( "&3Volume: &7%s &3Blocks", + dFmt.format( Math.round(m.getBounds().getTotalBlockCount())) ); + chatDisplay.addComponent( row ); + } + + + if ( !m.isVirtual() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Blocks Remaining: &7%s %s%% ", + dFmt.format( m.getRemainingBlockCount() ), + fFmt.format( m.getPercentRemainingBlockCount() ) ); + + chatDisplay.addComponent( row ); + } + + + { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Liner: &7%s", + m.getLinerData().toInfoString() ); + chatDisplay.addComponent( row ); + } + + + + if ( !cmdPageData.isShowAll() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Mine Command Count: &7%d &3BlockEvent Count: &7%d", + m.getResetCommands().size(), + m.getBlockEvents().size() ); + chatDisplay.addComponent( row ); + } + + + + + int resetTime = m.getResetTime(); + + if ( resetTime <= 0 ) { + RowComponent row = new RowComponent(); + + row.addTextComponent( "&3Automatic Resets are &7Disabled" ); + chatDisplay.addComponent( row ); + } + else { + RowComponent row = new RowComponent(); + double rtMinutes = resetTime / 60.0D; + row.addTextComponent( + "&3Reset time: &7%s &3Secs (&7%.2f &3Mins) Reset Count: &7%s ", + Integer.toString(resetTime), + rtMinutes, + dFmt.format(m.getResetCount()) ); + chatDisplay.addComponent( row ); + } + + + if ( !m.isVirtual() && resetTime > 0 ) { + RowComponent row = new RowComponent(); + + long targetResetTime = m.getTargetResetTime(); + double remaining = ( targetResetTime <= 0 ? 0d : + (targetResetTime - System.currentTimeMillis()) / 1000d); + double rtMinutes = remaining / 60.0D; + + row.addTextComponent( "&3Time Until Next Reset: &7%s &3Secs (&7%.2f &3Mins)", + dFmt.format( remaining ), rtMinutes ); + chatDisplay.addComponent( row ); + } + + + + + if ( !m.isVirtual() ) { + if ( m.getResetThresholdPercent() == 0 && cmdPageData.isShowAll() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Reset Threshold: &cDISABLED"); + chatDisplay.addComponent( row ); + } + else if ( m.getResetThresholdPercent() > 0 ) { + RowComponent row = new RowComponent(); + + double blocks = m.getBounds().getTotalBlockCount() * + m.getResetThresholdPercent() / 100.0d; + row.addTextComponent( "&3Reset Threshold: &7%s &3Percent (&7%s &3blocks)", + fFmt.format( m.getResetThresholdPercent() ), + dFmt.format( blocks ) ); + chatDisplay.addComponent( row ); + } + + } + + + + { + + if ( m.isZeroBlockResetDisabled() && cmdPageData.isShowAll() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Reset Delay: &cDISABLED"); + chatDisplay.addComponent( row ); + } + else if ( !m.isZeroBlockResetDisabled() ) { + RowComponent row = new RowComponent(); + if ( m.getResetThresholdPercent() == 0 ) { + row.addTextComponent( "&3Reset Delay (zero blocks): &7%s &3Seconds", + fFmt.format( m.getZeroBlockResetDelaySec() )); + } + else { + row.addTextComponent( "&3Reset Delay (&s Percent Threshold): &7%s &3Seconds", + fFmt.format( m.getResetThresholdPercent() ), + fFmt.format( m.getZeroBlockResetDelaySec() )); + } + chatDisplay.addComponent( row ); + } + + } + + + + + if ( resetTime > 0 && m.isSkipResetEnabled() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( + "&3Reset Skip: &2Enabled&3: &3Threshold: &7%s &3SkipLimit: &7%s &3SkipCount: &7%s", + fFmt.format( m.getSkipResetPercent() ), + dFmt.format( m.getSkipResetBypassLimit() ), + dFmt.format( m.getSkipResetBypassCount() ) ); + chatDisplay.addComponent( row ); + + } + else if ( resetTime > 0 && cmdPageData.isShowAll() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Reset Skip if no Mining Activity: &cnot enabled"); + chatDisplay.addComponent( row ); + } + + + + if ( resetTime > 0 ) + { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Notification Mode: &7%s &7%s", + m.getNotificationMode().name(), + ( m.getNotificationMode() == MineNotificationMode.radius ? + dFmt.format( m.getNotificationRadius() ) + " blocks" : "" ) ); + chatDisplay.addComponent( row ); + } + + if ( resetTime > 0 && m.isUseNotificationPermission() || + resetTime > 0 && !m.isUseNotificationPermission() && cmdPageData.isShowAll() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Notifications Filtered by Permissions: %s", + ( m.isUseNotificationPermission() ? + m.getMineNotificationPermissionName() : "&dDisabled" ) ); + chatDisplay.addComponent( row ); + } + + + + + + if ( m.isMineSweeperEnabled() ) { + + // stats for mine sweeper activity: + long mineSweeperAvgMs = ( m.getMineSweeperCount() == 0 ? 0 : m.getMineSweeperTotalMs() / m.getMineSweeperCount()); + + String mineSweeperBlks = PlaceholdersUtil.formattedKmbtSISize(m.getMineSweeperBlocksChanged(), fFmt, " " ); + + // Format with input requiring seconds: + String totalRunTime = PlaceholdersUtil.formattedTime( m.getMineSweeperTotalMs() / 1000d ); + + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Mine Sweeper: &2Enabled&3: runs: %s Avg ms: %s Time: %s Blks: %s ", + dFmt.format( m.getMineSweeperCount() ), dFmt.format( mineSweeperAvgMs ), + totalRunTime, + mineSweeperBlks ); + chatDisplay.addComponent( row ); + + if ( m.getStatsMineSweeperTaskMs().size() > 0 ) { + RowComponent row2 = new RowComponent(); + row2.addTextComponent( "&3 %s ", m.statsMessageMineSweeper() ); + chatDisplay.addComponent( row2 ); + } + + } + else if ( cmdPageData.isShowAll() ) { + RowComponent row = new RowComponent(); + row.addTextComponent( "&3Mine Sweeper: &cDisabled&3 "); + chatDisplay.addComponent( row ); + } + + + + + String statsMsg = m.statsMessage(); + if ( !m.isVirtual() && (cmdPageData.isShowAll() || isMineStats) && + statsMsg != null && statsMsg.length() > 0 ) { + + int idx = statsMsg.indexOf("BlockUpdateTime:"); + int idx2 = statsMsg.indexOf("ResetPages:", idx); + + String stats1 = statsMsg.substring(0, idx ); + String stats2 = statsMsg.substring( idx, idx2 ); + String stats3 = statsMsg.substring( idx2 ); + + { + RowComponent rowStats = new RowComponent(); + rowStats.addTextComponent( " -- &7 Reset Stats :: &3" ); + rowStats.addTextComponent( stats1 ); + chatDisplay.addComponent(rowStats); + } + { + RowComponent rowStats = new RowComponent(); + rowStats.addTextComponent( " -- &7 Reset Stats :: &3" ); + rowStats.addTextComponent( stats2 ); + chatDisplay.addComponent(rowStats); + } + { + RowComponent rowStats = new RowComponent(); + rowStats.addTextComponent( " -- &7 Reset Stats :: &3" ); + rowStats.addTextComponent( stats3 ); + chatDisplay.addComponent(rowStats); + } + + + } + + + + if ( m.getResetCommands() != null && m.getResetCommands().size() > 0 ) { + + BulletedListComponent.BulletedListBuilder builder = new BulletedListComponent.BulletedListBuilder(); + + FancyMessage msg = new FancyMessage(String.format("&3Reset Commands: &7%s", + dFmt.format( m.getResetCommands().size() ))) + .suggest("/mines command list " + m.getName()) + .tooltip("&7Click to list to view the reset commands."); + + builder.add(msg); + + chatDisplay.addComponent( builder.build() ); + } + + + } - - - if ( !m.isVirtual() ) { - String worldName = m.getWorld().isPresent() ? m.getWorld().get().getName() : "&cmissing"; - Player player = sender == null ? null : sender.getPlatformPlayer(); - chatDisplay.addText("&3World: &7%-10s &3Center: &7%s &3%s &7%s", - worldName, - m.getBounds().getCenter().toBlockCoordinates(), - (player == null ? "" : "Distance:"), - (player == null ? "" : fFmt.format( m.getBounds().getDistance3d( player.getLocation() ) )) - ); - - - String minCoords = m.getBounds().getMin().toBlockCoordinates(); - String maxCoords = m.getBounds().getMax().toBlockCoordinates(); - chatDisplay.addText("&3Bounds: &7%s &8to &7%s", minCoords, maxCoords); - - String spawnPoint = m.getSpawn() != null ? m.getSpawn().toBlockCoordinates() : "&cnot set"; - chatDisplay.addText("&3Spawnpoint: &7%s", spawnPoint); - - } - + + if ( cmdPageData.isShowAll() || cmdPageData.getCurPage() > 1 ) { + chatDisplay.addText("&3Blocks:"); + chatDisplay.addText("&8Click on a block's name to edit its chances of appearing..." ); + + BulletedListComponent list = getBlocksList(m, cmdPageData, true ); + chatDisplay.addComponent(list); + } + + if ( cmdPageData.isShowAll() ) { + // Include all the commands for this mine: + ChatDisplay commandDisplay = minesCommandList( m ); + chatDisplay.addChatDisplay( commandDisplay ); + -// chatDisplay.text("&3Size: &7%d&8x&7%d&8x&7%d", Math.round(m.getBounds().getWidth()), -// Math.round(m.getBounds().getHeight()), Math.round(m.getBounds().getLength())); - - if ( !m.isVirtual() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Size: &7%d&8x&7%d&8x&7%d ", Math.round(m.getBounds().getWidth()), - Math.round(m.getBounds().getHeight()), Math.round(m.getBounds().getLength()) ); - - row.addTextComponent( "&3Volume: &7%s &3Blocks", - dFmt.format( Math.round(m.getBounds().getTotalBlockCount())) ); - chatDisplay.addComponent( row ); - } - - - if ( !m.isVirtual() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Blocks Remaining: &7%s %s%% ", - dFmt.format( m.getRemainingBlockCount() ), - fFmt.format( m.getPercentRemainingBlockCount() ) ); - - chatDisplay.addComponent( row ); - } - - - { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Liner: &7%s", - m.getLinerData().toInfoString() ); - chatDisplay.addComponent( row ); - } - - - - if ( !cmdPageData.isShowAll() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Mine Command Count: &7%d &3BlockEvent Count: &7%d", - m.getResetCommands().size(), - m.getBlockEvents().size() ); - chatDisplay.addComponent( row ); - } - - - - - int resetTime = m.getResetTime(); - - if ( resetTime <= 0 ) { - RowComponent row = new RowComponent(); - - row.addTextComponent( "&3Automatic Resets are &7Disabled" ); - chatDisplay.addComponent( row ); - } - else { - RowComponent row = new RowComponent(); - double rtMinutes = resetTime / 60.0D; - row.addTextComponent( - "&3Reset time: &7%s &3Secs (&7%.2f &3Mins) Reset Count: &7%s ", - Integer.toString(resetTime), - rtMinutes, - dFmt.format(m.getResetCount()) ); - chatDisplay.addComponent( row ); - } - -// { -// RowComponent row = new RowComponent(); -// row.addTextComponent( "&3Mine Reset Count: &7%s ", -// dFmt.format(m.getResetCount()) ); -// -//// if ( m.isUsePagingOnReset() ) { -//// row.addTextComponent( " &7-= &5Reset Paging Enabled &7=-" ); -//// } -//// else if ( cmdPageData.isShowAll() ) { -//// row.addTextComponent( " &7-= &3Reset Paging Disabled &7=-" ); -//// } -// -// chatDisplay.addComponent( row ); -// -//// double resetTimeSeconds = m.getStatsResetTimeMS() / 1000.0; -//// if ( !m.isUsePagingOnReset() && resetTimeSeconds > 0.5 ) { -//// String resetTimeSec = PlaceholdersUtil.formattedTime( resetTimeSeconds ); -//// chatDisplay.addText("&5 Warning: &3Reset time is &7%s&3, which is high. " + -//// "It is recommened that you try to enable &7/mines set resetPaging help", -//// resetTimeSec ); -//// } -// } - - if ( !m.isVirtual() && resetTime > 0 ) { - RowComponent row = new RowComponent(); - - long targetResetTime = m.getTargetResetTime(); - double remaining = ( targetResetTime <= 0 ? 0d : - (targetResetTime - System.currentTimeMillis()) / 1000d); - double rtMinutes = remaining / 60.0D; - - row.addTextComponent( "&3Time Until Next Reset: &7%s &3Secs (&7%.2f &3Mins)", - dFmt.format( remaining ), rtMinutes ); - chatDisplay.addComponent( row ); - } - - - - - if ( !m.isVirtual() ) { - if ( m.getResetThresholdPercent() == 0 && cmdPageData.isShowAll() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Reset Threshold: &cDISABLED"); - chatDisplay.addComponent( row ); - } - else if ( m.getResetThresholdPercent() > 0 ) { - RowComponent row = new RowComponent(); - - double blocks = m.getBounds().getTotalBlockCount() * - m.getResetThresholdPercent() / 100.0d; - row.addTextComponent( "&3Reset Threshold: &7%s &3Percent (&7%s &3blocks)", - fFmt.format( m.getResetThresholdPercent() ), - dFmt.format( blocks ) ); - chatDisplay.addComponent( row ); - } - - } - + // Include all the blockEvent commands: + ChatDisplay blockEventDisplay = new ChatDisplay("BlockEvent Commands for Mine " + m.getTag()); + blockEventDisplay.addText("&8Hover over values for more information and clickable actions."); - - { - - if ( m.isZeroBlockResetDisabled() && cmdPageData.isShowAll() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Reset Delay: &cDISABLED"); - chatDisplay.addComponent( row ); - } - else if ( !m.isZeroBlockResetDisabled() ) { - RowComponent row = new RowComponent(); - if ( m.getResetThresholdPercent() == 0 ) { - row.addTextComponent( "&3Reset Delay (zero blocks): &7%s &3Seconds", - fFmt.format( m.getZeroBlockResetDelaySec() )); - } - else { - row.addTextComponent( "&3Reset Delay (&s Percent Threshold): &7%s &3Seconds", - fFmt.format( m.getResetThresholdPercent() ), - fFmt.format( m.getZeroBlockResetDelaySec() )); - } - chatDisplay.addComponent( row ); - } - - } - + generateBlockEventListing( m, blockEventDisplay, false ); + + blockEventDisplay.addComponent(new FancyMessageComponent( + new FancyMessage("&7[&a+&7] Add").suggest("/mines blockEvent add " + m.getName() + " [chance] [perm] [cmd] /") + .tooltip("&7Add a new BockEvent command."))); - - - if ( resetTime > 0 && m.isSkipResetEnabled() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( - "&3Reset Skip: &2Enabled&3: &3Threshold: &7%s &3SkipLimit: &7%s &3SkipCount: &7%s", - fFmt.format( m.getSkipResetPercent() ), - dFmt.format( m.getSkipResetBypassLimit() ), - dFmt.format( m.getSkipResetBypassCount() ) ); - chatDisplay.addComponent( row ); - -// if ( m.getSkipResetBypassCount() > 0 ) { -// RowComponent row2 = new RowComponent(); -// row2.addTextComponent( " &3Skipping Enabled: Skip Count: &7%s", -// dFmt.format( m.getSkipResetBypassCount() )); -// chatDisplay.addComponent( row2 ); -// } - } - else if ( resetTime > 0 && cmdPageData.isShowAll() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Reset Skip if no Mining Activity: &cnot enabled"); - chatDisplay.addComponent( row ); - } - - - - if ( resetTime > 0 ) - { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Notification Mode: &7%s &7%s", - m.getNotificationMode().name(), - ( m.getNotificationMode() == MineNotificationMode.radius ? - dFmt.format( m.getNotificationRadius() ) + " blocks" : "" ) ); - chatDisplay.addComponent( row ); - } - - if ( resetTime > 0 && m.isUseNotificationPermission() || - resetTime > 0 && !m.isUseNotificationPermission() && cmdPageData.isShowAll() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Notifications Filtered by Permissions: %s", - ( m.isUseNotificationPermission() ? - m.getMineNotificationPermissionName() : "&dDisabled" ) ); - chatDisplay.addComponent( row ); - } - - - - - - if ( m.isMineSweeperEnabled() ) { - - // stats for mine sweeper activity: - long mineSweeperAvgMs = ( m.getMineSweeperCount() == 0 ? 0 : m.getMineSweeperTotalMs() / m.getMineSweeperCount()); - - String mineSweeperBlks = PlaceholdersUtil.formattedKmbtSISize(m.getMineSweeperBlocksChanged(), fFmt, " " ); - - // Format with input requiring seconds: - String totalRunTime = PlaceholdersUtil.formattedTime( m.getMineSweeperTotalMs() / 1000d ); - - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Mine Sweeper: &2Enabled&3: runs: %s Avg ms: %s Time: %s Blks: %s ", - dFmt.format( m.getMineSweeperCount() ), dFmt.format( mineSweeperAvgMs ), - totalRunTime, - mineSweeperBlks ); - chatDisplay.addComponent( row ); - - if ( m.getStatsMineSweeperTaskMs().size() > 0 ) { - RowComponent row2 = new RowComponent(); - row2.addTextComponent( "&3 %s ", m.statsMessageMineSweeper() ); - chatDisplay.addComponent( row2 ); - } - - } - else if ( cmdPageData.isShowAll() ) { - RowComponent row = new RowComponent(); - row.addTextComponent( "&3Mine Sweeper: &cDisabled&3 "); - chatDisplay.addComponent( row ); - } - - - - - String statsMsg = m.statsMessage(); - if ( !m.isVirtual() && (cmdPageData.isShowAll() || isMineStats) && - statsMsg != null && statsMsg.length() > 0 ) { - - int idx = statsMsg.indexOf("BlockUpdateTime:"); - int idx2 = statsMsg.indexOf("ResetPages:", idx); - - String stats1 = statsMsg.substring(0, idx ); - String stats2 = statsMsg.substring( idx, idx2 ); - String stats3 = statsMsg.substring( idx2 ); - - { - RowComponent rowStats = new RowComponent(); - rowStats.addTextComponent( " -- &7 Reset Stats :: &3" ); - rowStats.addTextComponent( stats1 ); - chatDisplay.addComponent(rowStats); - } - { - RowComponent rowStats = new RowComponent(); - rowStats.addTextComponent( " -- &7 Reset Stats :: &3" ); - rowStats.addTextComponent( stats2 ); - chatDisplay.addComponent(rowStats); - } - { - RowComponent rowStats = new RowComponent(); - rowStats.addTextComponent( " -- &7 Reset Stats :: &3" ); - rowStats.addTextComponent( stats3 ); - chatDisplay.addComponent(rowStats); - } - - -// rowStats.addTextComponent( m.statsMessage() ); - } - - - - if ( m.getResetCommands() != null && m.getResetCommands().size() > 0 ) { -// RowComponent row = new RowComponent(); -// row.addTextComponent( "&3Reset Commands: &7%s ", -// dFmt.format( m.getResetCommands().size() ) ); - - BulletedListComponent.BulletedListBuilder builder = new BulletedListComponent.BulletedListBuilder(); - - FancyMessage msg = new FancyMessage(String.format("&3Reset Commands: &7%s", - dFmt.format( m.getResetCommands().size() ))) - .suggest("/mines command list " + m.getName()) - .tooltip("&7Click to list to view the reset commands."); - - builder.add(msg); - - chatDisplay.addComponent( builder.build() ); - } - - - } - - - if ( cmdPageData.isShowAll() || cmdPageData.getCurPage() > 1 ) { - - chatDisplay.addText("&3Blocks:"); - chatDisplay.addText("&8Click on a block's name to edit its chances of appearing..." ); - - BulletedListComponent list = getBlocksList(m, cmdPageData, true ); - chatDisplay.addComponent(list); - } - - if ( cmdPageData.isShowAll() ) { - - // Include all the commands for this mine: - ChatDisplay commandDisplay = minesCommandList( m ); - chatDisplay.addChatDisplay( commandDisplay ); - - - // Include all the blockEvent commands: - ChatDisplay blockEventDisplay = new ChatDisplay("BlockEvent Commands for " + m.getTag()); - blockEventDisplay.addText("&8Hover over values for more information and clickable actions."); - - generateBlockEventListing( m, blockEventDisplay, false ); - - blockEventDisplay.addComponent(new FancyMessageComponent( - new FancyMessage("&7[&a+&7] Add").suggest("/mines blockEvent add " + m.getName() + " [chance] [perm] [cmd] /") - .tooltip("&7Add a new BockEvent command."))); - - chatDisplay.addChatDisplay( blockEventDisplay ); - } - - return chatDisplay; - } + chatDisplay.addChatDisplay( blockEventDisplay ); + } + + return chatDisplay; + } @@ -1398,43 +1356,43 @@ public void resetCommand(CommandSender sender, boolean force = false; if ( options.contains( "nocommands" )) { - options = options.replace( "nocommands", "" ).trim(); - resetActions.add( MineResetActions.NO_COMMANDS ); + options = options.replace( "nocommands", "" ).trim(); + resetActions.add( MineResetActions.NO_COMMANDS ); } if ( options.contains( "details" ) ) { - options = options.replace( "details", "" ).trim(); - resetActions.add( MineResetActions.DETAILS ); + options = options.replace( "details", "" ).trim(); + resetActions.add( MineResetActions.DETAILS ); } if ( options.contains( "force" ) ) { - options = options.replace( "force", "" ).trim(); - force = true; + options = options.replace( "force", "" ).trim(); + force = true; } // The value of chained is an internal value and should not be shown to users: if ( options.contains( "chained" ) ) { - options = options.replace( "chained", "" ).trim(); - resetActions.add( MineResetActions.CHAINED_RESETS ); + options = options.replace( "chained", "" ).trim(); + resetActions.add( MineResetActions.CHAINED_RESETS ); } if ( !options.trim().isEmpty() ) { - sender.sendMessage( "&cInvalid value for &7options&c. " + - "&3The only valid options are: [&7noCommands details&3] or blanks. " + - "[&7" + options + "&3] mine = [&7" + mineName + "&3]" ); - return; + sender.sendMessage( "&cInvalid value for &7options&c. " + + "&3The only valid options are: [&7noCommands details&3] or blanks. " + + "[&7" + options + "&3] mine = [&7" + mineName + "&3]" ); + return; } PrisonMines pMines = PrisonMines.getInstance(); if ( mineName != null && "*all*".equalsIgnoreCase( mineName ) ) { - pMines.resetAllMines( resetType, resetActions ); - return; + pMines.resetAllMines( resetType, resetActions ); + return; } if ( mineName != null && "*cancel*".equalsIgnoreCase( mineName ) ) { - pMines.cancelResetAllMines(); - return; + pMines.cancelResetAllMines(); + return; } @@ -1449,50 +1407,50 @@ public void resetCommand(CommandSender sender, if ( m.isVirtual() ) { - sender.sendMessage( "&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine." ); - return; + sender.sendMessage( "&cInvalid option. This mine is a virtual mine&7. Use &a/mines set area &7to enable the mine." ); + return; } if ( !m.isEnabled() ) { - sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); - return; + sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); + return; } if ( !m.getMineStateMutex().isMinable() && force ) { - sender.sendMessage( - String.format( - "&cMine is currently being reset. &7An unlock is being forced to allow " - + "a new reset." ) - ); - - // Force the reset by setting the mineResetStartTimestamp to 10 mins ago: - m.setMineResetStartTimestamp( System.currentTimeMillis() - 10 * 60000 ); + sender.sendMessage( + String.format( + "&cMine is currently being reset. &7An unlock is being forced to allow " + + "a new reset." ) + ); + + // Force the reset by setting the mineResetStartTimestamp to 10 mins ago: + m.setMineResetStartTimestamp( System.currentTimeMillis() - 10 * 60000 ); } else if ( !m.getMineStateMutex().isMinable() ) { - long resetDuration = m.getMineResetStartTimestamp() == -1 ? 0 : + long resetDuration = m.getMineResetStartTimestamp() == -1 ? 0 : System.currentTimeMillis() - m.getMineResetStartTimestamp(); - DecimalFormat dFmt = Prison.get().getDecimalFormatDouble(); - - sender.sendMessage( - String.format( - "&cMine is currently being reset. &7Will try to force an unlock to allow " - + "a new reset. May have to wait 3 minutes before the Mutex is releasable. " - + "The mine was reset %s seconds ago.", - dFmt.format( resetDuration / 1000.0d ) ) + DecimalFormat dFmt = Prison.get().getDecimalFormatDouble(); + + sender.sendMessage( + String.format( + "&cMine is currently being reset. &7Will try to force an unlock to allow " + + "a new reset. May have to wait 3 minutes before the Mutex is releasable. " + + "The mine was reset %s seconds ago.", + dFmt.format( resetDuration / 1000.0d ) ) ); } try { - m.manualReset( resetType, resetActions ); + m.manualReset( resetType, resetActions ); } catch (Exception e) { - pMines.getMinesMessages().getLocalizable("mine_reset_fail") - .withReplacements( m.getName() ) - .sendTo(sender); + pMines.getMinesMessages().getLocalizable("mine_reset_fail") + .withReplacements( m.getName() ) + .sendTo(sender); Output.get().logError("Couldn't reset mine " + mineName, e); return; } @@ -1512,40 +1470,40 @@ public void listCommand(CommandSender sender, @Arg(name = "page", def = "1", description = "Page of search results (optional) [1-n, ALL]") String page ) { - Player player = sender.getPlatformPlayer(); - - MineSortOrder sortOrder = MineSortOrder.fromString( sort ); - - // If sort was invalid, double check to see if it is a page number or ALL: - if ( sortOrder == MineSortOrder.invalid ) { - sortOrder = MineSortOrder.sortOrder; - - if ( sort != null && "ALL".equalsIgnoreCase( sort )) { - // The user did not specify a sort order, but instead this is the page number - // so fix it for them: - page = "ALL"; - } - else if ( sort != null ) { - try { - int test = Integer.parseInt( sort ); - - // This is actually the page number so default to alpha sort: - page = Integer.toString( test ); - } - catch ( NumberFormatException e ) { - // Oof... this isn't a page number, so report an error. - sender.sendMessage( "Invalid sort order. Use a valid sort order " + - "or a page number such as [1-n, ALL]" ); - } - } - } - - ChatDisplay display = new ChatDisplay("Mines"); - display.addText("&8Click a mine's name to see more information."); - - - getMinesList( display, sortOrder, page, player ); - + Player player = sender.getPlatformPlayer(); + + MineSortOrder sortOrder = MineSortOrder.fromString( sort ); + + // If sort was invalid, double check to see if it is a page number or ALL: + if ( sortOrder == MineSortOrder.invalid ) { + sortOrder = MineSortOrder.sortOrder; + + if ( sort != null && "ALL".equalsIgnoreCase( sort )) { + // The user did not specify a sort order, but instead this is the page number + // so fix it for them: + page = "ALL"; + } + else if ( sort != null ) { + try { + int test = Integer.parseInt( sort ); + + // This is actually the page number so default to alpha sort: + page = Integer.toString( test ); + } + catch ( NumberFormatException e ) { + // Oof... this isn't a page number, so report an error. + sender.sendMessage( "Invalid sort order. Use a valid sort order " + + "or a page number such as [1-n, ALL]" ); + } + } + } + + ChatDisplay display = new ChatDisplay("Mines"); + display.addText("&8Click a mine's name to see more information."); + + + getMinesList( display, sortOrder, page, player ); + display.send(sender); @@ -1554,30 +1512,22 @@ else if ( sort != null ) { public void getMinesList( ChatDisplay display, MineSortOrder sortOrder, String page, Player player ) { PrisonMines pMines = PrisonMines.getInstance(); - MineManager mMan = pMines.getMineManager(); - - - // Get mines in the correct sorted order and suppress the mines if they should - PrisonSortableResults sortedMines = pMines.getMines( sortOrder ); - - display.addText( "&3 Mines listed: &7%s &3Mines suppressed: &7%s", - sortedMines.getSortedList().size(), - sortedMines.getSortedSuppressedList().size()); - - if ( sortedMines.getSortedSuppressedList().size() > 0 ) { - display.addText( "&8To view suppressed mines sort by: %s", - sortedMines.getSuppressedListSortTypes() ); - } + MineManager mMan = pMines.getMineManager(); + + + // Get mines in the correct sorted order and suppress the mines if they should + PrisonSortableResults sortedMines = pMines.getMines( sortOrder ); + + display.addText( "&3 Mines listed: &7%s &3Mines suppressed: &7%s", + sortedMines.getSortedList().size(), + sortedMines.getSortedSuppressedList().size()); + + if ( sortedMines.getSortedSuppressedList().size() > 0 ) { + display.addText( "&8To view suppressed mines sort by: %s", + sortedMines.getSuppressedListSortTypes() ); + } -// // Sort first by name, then blocks mined so final sort order will be: -// // Most blocks mined, then alphabetical -// mineList.sort( (a, b) -> a.getName().compareToIgnoreCase( b.getName()) ); -// -// // for now hold off on sorting by total blocks mined. -// if ( "active".equalsIgnoreCase( sort )) { -// mineList.sort( (a, b) -> Long.compare(b.getTotalBlocksMined(), a.getTotalBlocksMined()) ); -// } CommandPagedData cmdPageData = new CommandPagedData( "/mines list " + sortOrder.name(), sortedMines.getSortedList().size(), @@ -1586,10 +1536,9 @@ public void getMinesList( ChatDisplay display, MineSortOrder sortOrder, String p BulletedListComponent list = getMinesLineItemList(sortedMines, player, cmdPageData, mMan.isMineStats()); - display.addComponent(list); - - cmdPageData.generatePagedCommandFooter( display ); - + display.addComponent(list); + + cmdPageData.generatePagedCommandFooter( display ); } @@ -1597,231 +1546,193 @@ public void getMinesList( ChatDisplay display, MineSortOrder sortOrder, String p private BulletedListComponent getMinesLineItemList( PrisonSortableResults sortedMines, Player player, CommandPagedData cmdPageData, boolean isMineStatsEnabled ) { - BulletedListComponent.BulletedListBuilder builder = - new BulletedListComponent.BulletedListBuilder(); - - - DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - DecimalFormat fFmt = Prison.get().getDecimalFormat("#,##0.00"); - - int count = 0; + BulletedListComponent.BulletedListBuilder builder = + new BulletedListComponent.BulletedListBuilder(); + + + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + DecimalFormat fFmt = Prison.get().getDecimalFormat("#,##0.00"); + + int count = 0; for (Mine m : sortedMines.getSortedList()) { if ( cmdPageData == null || count++ >= cmdPageData.getPageStart() && count <= cmdPageData.getPageEnd() ) { - RowComponent row = new RowComponent(); - - //row.addTextComponent( m.getWorldName() + " " ); - - if ( m.getSortOrder() < 1 ) { -// row.addTextComponent( " " ); - -// row.addFancy( -// new FancyMessage( String.format("&3(&b%s&3) ", -// "X") ) -// .tooltip("&7Sort order: Suppressed")); - } - else { - row.addFancy( - new FancyMessage( String.format("&3(&b%s&3) ", - Integer.toString( m.getSortOrder() )) ) - .tooltip("&7Sort order.")); - } - - - String name = m.getName(); - if ( name.length() < 6 ) { - name += " ".substring( 0, (6-name.length()) ); - } - row.addFancy( - new FancyMessage( String.format("&7%s ", name) ) - .command("/mines info " + m.getName()) - .tooltip("&7Mine " + m.getTag() + ": Click to view more info.")); - - - if ( m.getTag() != null && m.getTag().trim().length() > 0 ) { - String tag = m.getTag(); - String tagNoColor = Text.stripColor( tag ); - if ( tagNoColor.length() < 6 ) { - tag += " ".substring( 0, (6 - tagNoColor.length()) ); - } - row.addTextComponent( "%s ", tag ); - } - - - if ( !m.isVirtual() ) { - row.addFancy( - new FancyMessage("&eTP ").command("/mines tp " + m.getName()) - .tooltip("&7Click to TP to the mine")); - } - - - row.addTextComponent( " &3(&2R: " ); - - if ( !m.isVirtual() && m.getResetTime() > 0 ) { - row.addFancy( - new FancyMessage( - String.format( "&7%s &3sec &3/ ", dFmt.format(m.getRemainingTimeSec()))) - - .tooltip( "Estimated time in seconds before the mine resets" ) ); -// row.addTextComponent( " sec &3(&b" ); - } - - - if ( m.getResetTime() <= 0 ) { - - row.addFancy( - new FancyMessage( - String.format( "&7disabled )&b" )) - .tooltip( "Auto resets have been disabled." ) ); - } - else { - - row.addFancy( - new FancyMessage( - String.format( "&7%s &3sec )&b", dFmt.format(m.getResetTime()) )) - .tooltip( "Reset time in seconds" ) ); - } -// row.addTextComponent( " sec&3)&b" ); - - if ( !m.isVirtual() && player != null && - m.getBounds().withinSameWorld( player.getLocation() ) ) { - - double distance = m.getBounds().getDistance3d(player.getLocation()); - -// row.addTextComponent( " &3Dist: &7"); - row.addFancy( - new FancyMessage( - String.format( " &3Dist: &7%s", fFmt.format( distance )) ). - tooltip("Distance to the Mine") ); - - } - - //builder.add(row.getFancy()); - - if ( m.isVirtual() ) { - - row.addTextComponent( "&6Virtual Mine" ); - } - - else { -// RowComponent row2 = new RowComponent(); -// row2.addTextComponent( " &3Rem: " ); - - // Right justify the total blocks mined, with 1000's separators: - String blocksMined = " " + dFmt.format( m.getTotalBlocksMined() ); -// String blocksMined = " " + dFmt.format( m.getTotalBlocksMined() ); - blocksMined = blocksMined.substring( blocksMined.length() - 8); - - row.addFancy( - new FancyMessage( String.format(" %s &3Rem: ", blocksMined)). - tooltip( "Blocks mined" ) ); - - row.addFancy( - new FancyMessage(fFmt.format(m.getPercentRemainingBlockCount())). - tooltip( "Percent Blocks Remaining" ) ); - - row.addTextComponent( "%% &3RCnt: &7" ); - - row.addFancy( - new FancyMessage(dFmt.format(m.getResetCount())). - tooltip( "Times the mine was reset." ) ); - - if ( !m.isVirtual() ) { - - row.addTextComponent( " &3 Vol: &7" ); - row.addFancy( - new FancyMessage(dFmt.format(m.getBounds().getTotalBlockCount())). - tooltip( "Volume in Blocks" ) ); - } - - - - - - boolean hasCmds = m.getResetCommands().size() > 0; - if ( hasCmds ) { - row.addFancy( - new FancyMessage( String.format(" &cCmds: &7%s ", - Integer.toString( m.getResetCommands().size() )) ) - .command("/mines commands list " + m.getName()) - .tooltip("&7Click to view commands.")); - } - - - - boolean hasBlockEvents = m.getBlockEvents().size() > 0; - if ( hasBlockEvents ) { - row.addFancy( - new FancyMessage( String.format(" &cbEvs: &7%s ", - Integer.toString( m.getBlockEvents().size() )) ) - .command("/mines blockEvent list " + m.getName()) - .tooltip("&7Click to view blockEvents.")); - } - - - - if ( m.isVirtual() ) { - row.addFancy( - new FancyMessage( "&cVIRTUAL " ) - .command("/mines set area " + m.getName()) - .tooltip("&7Click to set the mine's area to make it a real mine. ")); - } - - - if ( !m.isEnabled() ) { - row.addFancy( - new FancyMessage( "&cDISABLED!! " ) - .command("/mines info " + m.getName()) - .tooltip("&7Click to view possible reason why the mine is " + - "disabled. World may not exist? ")); - } - - -// if ( m.isUsePagingOnReset() ) { -// row.addFancy( -// new FancyMessage("&5Paged ") -// .tooltip("&7Paging Used during Mine Reset")); -// } - - - -// String noteMode = m.getNotificationMode().name() + -// ( m.getNotificationMode() == MineNotificationMode.radius ? -// " " + dFmt.format( m.getNotificationRadius() ) : "" ); -// row.addFancy( -// new FancyMessage(noteMode).tooltip( "Notification Mode" ) ); -// -// row.addTextComponent( "&7 - &b" ); -// -// row.addFancy( -// new FancyMessage(m.getBounds().getDimensions()).tooltip( "Size of Mine" ) ); -// -// row.addTextComponent( "&7 - &b"); - - - } - - builder.add(row.getFancy()); - - - if ( !m.isVirtual() && isMineStatsEnabled ) { - RowComponent rowStats = new RowComponent(); - - rowStats.addTextComponent( " -- &7 Stats :: " ); - - rowStats.addTextComponent( m.statsMessage() ); - - builder.add(rowStats.getFancy()); - } + RowComponent row = new RowComponent(); + + + if ( m.getSortOrder() < 1 ) { + + } + else { + row.addFancy( + new FancyMessage( String.format("&3(&b%s&3) ", + Integer.toString( m.getSortOrder() )) ) + .tooltip("&7Sort order.")); + } + + + String name = m.getName(); + if ( name.length() < 6 ) { + name += " ".substring( 0, (6-name.length()) ); + } + row.addFancy( + new FancyMessage( String.format("&7%s ", name) ) + .command("/mines info " + m.getName()) + .tooltip("&7Mine " + m.getTag() + ": Click to view more info.")); + + + if ( m.getTag() != null && m.getTag().trim().length() > 0 ) { + String tag = m.getTag(); + String tagNoColor = Text.stripColor( tag ); + if ( tagNoColor.length() < 6 ) { + tag += " ".substring( 0, (6 - tagNoColor.length()) ); + } + row.addTextComponent( "%s ", tag ); + } + + + if ( !m.isVirtual() ) { + row.addFancy( + new FancyMessage("&eTP ").command("/mines tp " + m.getName()) + .tooltip("&7Click to TP to the mine")); + } + + + row.addTextComponent( " &3(&2R: " ); + + if ( !m.isVirtual() && m.getResetTime() > 0 ) { + row.addFancy( + new FancyMessage( + String.format( "&7%s &3sec &3/ ", dFmt.format(m.getRemainingTimeSec()))) + + .tooltip( "Estimated time in seconds before the mine resets" ) ); + } + + + if ( m.getResetTime() <= 0 ) { + + row.addFancy( + new FancyMessage( + String.format( "&7disabled )&b" )) + .tooltip( "Auto resets have been disabled." ) ); + } + else { + + row.addFancy( + new FancyMessage( + String.format( "&7%s &3sec )&b", dFmt.format(m.getResetTime()) )) + .tooltip( "Reset time in seconds" ) ); + } + + if ( !m.isVirtual() && player != null && + m.getBounds().withinSameWorld( player.getLocation() ) ) { + + double distance = m.getBounds().getDistance3d(player.getLocation()); + + row.addFancy( + new FancyMessage( + String.format( " &3Dist: &7%s", fFmt.format( distance )) ). + tooltip("Distance to the Mine") ); + + } + + + if ( m.isVirtual() ) { + + row.addTextComponent( "&6Virtual Mine" ); + } + + else { + + // Right justify the total blocks mined, with 1000's separators: + String blocksMined = " " + dFmt.format( m.getTotalBlocksMined() ); + blocksMined = blocksMined.substring( blocksMined.length() - 8); + + row.addFancy( + new FancyMessage( String.format(" %s &3Rem: ", blocksMined)). + tooltip( "Blocks mined" ) ); + + row.addFancy( + new FancyMessage(fFmt.format(m.getPercentRemainingBlockCount())). + tooltip( "Percent Blocks Remaining" ) ); + + row.addTextComponent( "%% &3RCnt: &7" ); + + row.addFancy( + new FancyMessage(dFmt.format(m.getResetCount())). + tooltip( "Times the mine was reset." ) ); + + if ( !m.isVirtual() ) { + + row.addTextComponent( " &3 Vol: &7" ); + row.addFancy( + new FancyMessage(dFmt.format(m.getBounds().getTotalBlockCount())). + tooltip( "Volume in Blocks" ) ); + } + + + + boolean hasCmds = m.getResetCommands().size() > 0; + if ( hasCmds ) { + row.addFancy( + new FancyMessage( String.format(" &cCmds: &7%s ", + Integer.toString( m.getResetCommands().size() )) ) + .command("/mines commands list " + m.getName()) + .tooltip("&7Click to view commands.")); + } + + + + boolean hasBlockEvents = m.getBlockEvents().size() > 0; + if ( hasBlockEvents ) { + row.addFancy( + new FancyMessage( String.format(" &cbEvs: &7%s ", + Integer.toString( m.getBlockEvents().size() )) ) + .command("/mines blockEvent list " + m.getName()) + .tooltip("&7Click to view blockEvents.")); + } + + + + if ( m.isVirtual() ) { + row.addFancy( + new FancyMessage( "&cVIRTUAL " ) + .command("/mines set area " + m.getName()) + .tooltip("&7Click to set the mine's area to make it a real mine. ")); + } + + + if ( !m.isEnabled() ) { + row.addFancy( + new FancyMessage( "&cDISABLED!! " ) + .command("/mines info " + m.getName()) + .tooltip("&7Click to view possible reason why the mine is " + + "disabled. World may not exist? ")); + } + + + + } + + builder.add(row.getFancy()); + + + if ( !m.isVirtual() && isMineStatsEnabled ) { + RowComponent rowStats = new RowComponent(); + + rowStats.addTextComponent( " -- &7 Stats :: " ); + + rowStats.addTextComponent( m.statsMessage() ); + + builder.add(rowStats.getFancy()); + } } } -// display.addComponent(builder.build()); - return builder.build(); } @@ -1880,39 +1791,34 @@ public void skipResetCommand(CommandSender sender, PrisonMines pMines = PrisonMines.getInstance(); -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - boolean skipEnabled = "enabled".equalsIgnoreCase( enabled ) || "enable".equalsIgnoreCase( enabled ); double skipPercent = 80.0d; int skipBypassLimit = 50; try { - skipPercent = Double.parseDouble( percent ); - if ( skipPercent < 0.0d ) { - skipPercent = 0.0d; - } else if ( skipPercent > 100.0d ) { - skipPercent = 100.0d; - } - } - catch ( NumberFormatException e1 ) { - Output.get().sendWarn( sender,"&7Invalid percentage. Not a number. " + - "Was &b%s&7.", (enabled == null ? "&c-blank-" : enabled) ); - return; + skipPercent = Double.parseDouble( percent ); + if ( skipPercent < 0.0d ) { + skipPercent = 0.0d; + } else if ( skipPercent > 100.0d ) { + skipPercent = 100.0d; } + } + catch ( NumberFormatException e1 ) { + Output.get().sendWarn( sender,"&7Invalid percentage. Not a number. " + + "Was &b%s&7.", (enabled == null ? "&c-blank-" : enabled) ); + return; + } try { - skipBypassLimit = Integer.parseInt( bypassLimit ); - if ( skipBypassLimit < 1 ) { - skipBypassLimit = 1; - } - } - catch ( NumberFormatException e1 ) { - Output.get().sendWarn( sender,"&7Invalid bypass limit. Not number. " + - "Was &b%s&7.", (bypassLimit == null ? "-blank-" : bypassLimit) ); - } + skipBypassLimit = Integer.parseInt( bypassLimit ); + if ( skipBypassLimit < 1 ) { + skipBypassLimit = 1; + } + } + catch ( NumberFormatException e1 ) { + Output.get().sendWarn( sender,"&7Invalid bypass limit. Not number. " + + "Was &b%s&7.", (bypassLimit == null ? "-blank-" : bypassLimit) ); + } int updates = 0; String mName = "&7*all*&r"; @@ -1975,115 +1881,106 @@ public void skipResetCommand(CommandSender sender, public void resetTimeCommand(CommandSender sender, @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. " + + "With a minimum value of "+ Mine.MINE_RESET__TIME_SEC__MINIMUM + " seconds. " + "Using '*disable*' will turn off the auto reset. Use of " + "*default* will set the time to " + - MineData.MINE_RESET__TIME_SEC__DEFAULT + " seconds. " + Mine.MINE_RESET__TIME_SEC__DEFAULT + " seconds. " + "[*default* *disable*]" ) String time ) { - int resetTime = MineData.MINE_RESET__TIME_SEC__DEFAULT; - - PrisonMines pMines = PrisonMines.getInstance(); - - if ( "*disable*".equalsIgnoreCase( time ) ) { - resetTime = -1; - } - else if ( "*default*".equalsIgnoreCase( time ) ) { - // use the default time - } - else { - try { - if ( time != null && time.trim().length() > 0 ) { - resetTime = Integer.parseInt( time ); - } - } - catch ( NumberFormatException e ) { - Output.get().sendWarn( sender, - "&7Invalid resetTime value for &b%s&7. Must be an integer value of &b%d &7or greater. [&b%s&7]", - mineName, MineData.MINE_RESET__TIME_SEC__MINIMUM, time ); - return; - } - } - 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 ); - return; - } - - if ( "*all*".equalsIgnoreCase( mineName ) ) { - - for ( Mine mine : pMines.getMines() ) { - if ( mine.getResetTime() != resetTime ) { - - mine.setResetTime( resetTime ); - - pMines.getMineManager().saveMine( mine ); - - if ( resetTime == -1 ) { - - Output.get().logInfo( "&7Automatic resets have been disabled for mine %s.", mine.getTag() ); - } - else { - // User's message: - Output.get().sendInfo( sender, "&7mines set resettime: &b%s &7resetTime set to &b%d", - mine.getTag(), resetTime ); - - // Server Log message: - Player player = sender.getPlatformPlayer(); - Output.get().logInfo( "&bmines set resettime&7: &b%s &7set &b%s &7resetTime to &b%d", - (player == null ? "console" : player.getDisplayName()), mine.getTag(), resetTime ); - } - } - } - - return; - } + int resetTime = Mine.MINE_RESET__TIME_SEC__DEFAULT; + + PrisonMines pMines = PrisonMines.getInstance(); + + if ( "*disable*".equalsIgnoreCase( time ) ) { + resetTime = -1; + } + else if ( "*default*".equalsIgnoreCase( time ) ) { + // use the default time + } + else { + try { + if ( time != null && time.trim().length() > 0 ) { + resetTime = Integer.parseInt( time ); + } + } + catch ( NumberFormatException e ) { + Output.get().sendWarn( sender, + "&7Invalid resetTime value for &b%s&7. Must be an integer value of &b%d &7or greater. [&b%s&7]", + mineName, Mine.MINE_RESET__TIME_SEC__MINIMUM, time ); + return; + } + } + if ( !"*disable*".equalsIgnoreCase( time ) && resetTime < Mine.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, Mine.MINE_RESET__TIME_SEC__MINIMUM, resetTime ); + return; + } + + if ( "*all*".equalsIgnoreCase( mineName ) ) { + + for ( Mine mine : pMines.getMines() ) { + if ( mine.getResetTime() != resetTime ) { + + mine.setResetTime( resetTime ); + + pMines.getMineManager().saveMine( mine ); + + if ( resetTime == -1 ) { + + Output.get().logInfo( "&7Automatic resets have been disabled for mine %s.", mine.getTag() ); + } + else { + // User's message: + Output.get().sendInfo( sender, "&7mines set resettime: &b%s &7resetTime set to &b%d", + mine.getTag(), resetTime ); + + // Server Log message: + Player player = sender.getPlatformPlayer(); + Output.get().logInfo( "&bmines set resettime&7: &b%s &7set &b%s &7resetTime to &b%d", + (player == null ? "console" : player.getDisplayName()), mine.getTag(), resetTime ); + } + } + } + + return; + } if (performCheckMineExists(sender, mineName)) { - setLastMineReferenced(mineName); - - Mine m = pMines.getMine(mineName); - - if ( "*disable*".equalsIgnoreCase( time ) ) { - - m.setResetTime( -1 ); - - pMines.getMineManager().saveMine( m ); - - Output.get().logInfo( "&7Automatic resets have been disabled for mine %s.", m.getTag() ); - - return; - } - - -// if ( 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 ); -// } else - { -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - - m.setResetTime( resetTime ); - - pMines.getMineManager().saveMine( m ); - - // User's message: - Output.get().sendInfo( sender, "&7mines set resettime: &b%s &7resetTime set to &b%d", m.getTag(), resetTime ); - - // Server Log message: - Player player = sender.getPlatformPlayer(); - Output.get().logInfo( "&bmines set resettime&7: &b%s &7set &b%s &7resetTime to &b%d", - (player == null ? "console" : player.getDisplayName()), m.getTag(), resetTime ); - } + setLastMineReferenced(mineName); + + Mine m = pMines.getMine(mineName); + + if ( "*disable*".equalsIgnoreCase( time ) ) { + + m.setResetTime( -1 ); + + pMines.getMineManager().saveMine( m ); + + Output.get().logInfo( "&7Automatic resets have been disabled for mine %s.", m.getTag() ); + + return; + } + + + { + + m.setResetTime( resetTime ); + + pMines.getMineManager().saveMine( m ); + + // User's message: + Output.get().sendInfo( sender, "&7mines set resettime: &b%s &7resetTime set to &b%d", m.getTag(), resetTime ); + + // Server Log message: + Player player = sender.getPlatformPlayer(); + Output.get().logInfo( "&bmines set resettime&7: &b%s &7set &b%s &7resetTime to &b%d", + (player == null ? "console" : player.getDisplayName()), m.getTag(), resetTime ); + } - } + } } @@ -2114,59 +2011,52 @@ public void zeroBlockResetDelayCommand(CommandSender sender, ) { - if ( "*all*".equalsIgnoreCase( mineName ) || - performCheckMineExists(sender, mineName)) { - - double resetTime = - time != null && "disable".equalsIgnoreCase( time ) ? -1.0d : - 0.0d; - - try { - - if ( resetTime != -1.0d && time != null && time.trim().length() > 0 ) { - resetTime = Double.parseDouble( time ); - - // Only displaying two decimal positions, since 0.01 is 10 ms. - // Anything less than 0.01 is set to ZERO so it does not mess with anything unseen. - // Also any value less than 0.05 is basically zero since this value has to be - // converted to ticks. - if ( resetTime < 0.01d ) { - resetTime = 0.0d; - } - } - } - catch ( NumberFormatException e ) { - Output.get().sendWarn( sender, - "&7Invalid zeroBlockResetDelay value for &b%s&7. Must be an double value of &b0.00 &7or " + - "greater. [&b%s&7]", - mineName, time ); - return; - } - - PrisonMines pMines = PrisonMines.getInstance(); - - if ( !"*all*".equalsIgnoreCase( mineName ) ) { - setLastMineReferenced(mineName); - - Mine m = pMines.getMine(mineName); - - minesSetResetDelay(sender, resetTime, pMines, m); - } - else { - - for ( Mine m : pMines.getMines() ) { - minesSetResetDelay(sender, resetTime, pMines, m); - } - } - - -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - - - } + if ( "*all*".equalsIgnoreCase( mineName ) || + performCheckMineExists(sender, mineName)) { + + double resetTime = + time != null && "disable".equalsIgnoreCase( time ) ? -1.0d : + 0.0d; + + try { + + if ( resetTime != -1.0d && time != null && time.trim().length() > 0 ) { + resetTime = Double.parseDouble( time ); + + // Only displaying two decimal positions, since 0.01 is 10 ms. + // Anything less than 0.01 is set to ZERO so it does not mess with anything unseen. + // Also any value less than 0.05 is basically zero since this value has to be + // converted to ticks. + if ( resetTime < 0.01d ) { + resetTime = 0.0d; + } + } + } + catch ( NumberFormatException e ) { + Output.get().sendWarn( sender, + "&7Invalid zeroBlockResetDelay value for &b%s&7. Must be an double value of &b0.00 &7or " + + "greater. [&b%s&7]", + mineName, time ); + return; + } + + PrisonMines pMines = PrisonMines.getInstance(); + + if ( !"*all*".equalsIgnoreCase( mineName ) ) { + setLastMineReferenced(mineName); + + Mine m = pMines.getMine(mineName); + + minesSetResetDelay(sender, resetTime, pMines, m); + } + else { + + for ( Mine m : pMines.getMines() ) { + minesSetResetDelay(sender, resetTime, pMines, m); + } + } + + } } private void minesSetResetDelay(CommandSender sender, double resetTime, PrisonMines pMines, Mine m) { @@ -2216,30 +2106,25 @@ public void resetThresholdPercentCommand(CommandSender sender, ) { if ( "*all*".equalsIgnoreCase( mineName ) || - performCheckMineExists(sender, mineName)) { + performCheckMineExists(sender, mineName)) { - PrisonMines pMines = PrisonMines.getInstance(); - - if ( !"*all*".equalsIgnoreCase( mineName ) ) { - setLastMineReferenced(mineName); - - Mine m = pMines.getMine(mineName); - - changeMinePercentThreshold(sender, percent, pMines, m); - } - else { - for ( Mine m : pMines.getMines() ) { - - changeMinePercentThreshold(sender, percent, pMines, m); + PrisonMines pMines = PrisonMines.getInstance(); + + if ( !"*all*".equalsIgnoreCase( mineName ) ) { + setLastMineReferenced(mineName); + + Mine m = pMines.getMine(mineName); + + changeMinePercentThreshold(sender, percent, pMines, m); + } + else { + for ( Mine m : pMines.getMines() ) { + + changeMinePercentThreshold(sender, percent, pMines, m); } - } - -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - - } + } + + } } private void changeMinePercentThreshold(CommandSender sender, String percent, PrisonMines pMines, Mine m) { @@ -2299,7 +2184,7 @@ public void setNotificationCommand(CommandSender sender, @Arg(name = "mineName", description = "The name of the mine to edit, or '*all*' to " + "apply to all mines. [*all*]") String mineName, @Arg(name = "mode", def="displayOptions", description = "The notification mode " - + "to use: [disabled within radius]") + + "to use: [disabled within radius world server]") String mode, @Arg(name = "radius", def="0", description = "The distance from the center of the mine to notify players of a reset." ) String radius @@ -2307,70 +2192,63 @@ public void setNotificationCommand(CommandSender sender, ) { - MineNotificationMode noteMode = MineNotificationMode.fromString( mode, MineNotificationMode.displayOptions ); - - if ( noteMode == MineNotificationMode.displayOptions ) { - sender.sendMessage( "&7Select a Mode: &bdisabled&7, &bwithin &7the mine, &bradius " + - "&7from center of mine." ); - return; - } - - long noteRadius = 0L; - if ( noteMode == MineNotificationMode.radius ) { - if ( radius == null || radius.trim().length() == 0 ) { - noteRadius = MineData.MINE_RESET__BROADCAST_RADIUS_BLOCKS; - } else { - try { - noteRadius = Long.parseLong( radius ); - - if ( noteRadius < 1 ) { - noteRadius = MineData.MINE_RESET__BROADCAST_RADIUS_BLOCKS; - DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - Output.get().sendWarn( sender, "&7Invalid radius value. " + - "Must be an positive non-zero integer. Using the default value: &b%s &7[&b%s&7]", - dFmt.format(MineData.MINE_RESET__BROADCAST_RADIUS_BLOCKS), radius ); - return; - } - } - catch ( NumberFormatException e ) { - e.printStackTrace(); - Output.get().sendWarn( sender, "&7Invalid notification radius. " + - "Must be an positive non-zero integer. [&b%s&7]", - radius ); - return; - } - } - } - - PrisonMines pMines = PrisonMines.getInstance(); - - if ( "*all*".equalsIgnoreCase( mineName ) ) { - - int count = 0; - for ( Mine m : pMines.getMines() ) - { - - if ( changeMineNotification( sender, mineName, noteMode, noteRadius, pMines, m, true ) ) { - count++; - } + MineNotificationMode noteMode = MineNotificationMode.fromString( mode, MineNotificationMode.displayOptions ); + + if ( noteMode == MineNotificationMode.displayOptions ) { + sender.sendMessage( "&7Select a Mode: &bdisabled&7, &bwithin &7the mine, &bradius " + + "&7from center of mine&7, &bworld&7, &bserver&7." ); + return; + } + + long noteRadius = 0L; + if ( noteMode == MineNotificationMode.radius ) { + if ( radius == null || radius.trim().length() == 0 ) { + noteRadius = Mine.MINE_RESET__BROADCAST_RADIUS_BLOCKS; + } else { + try { + noteRadius = Long.parseLong( radius ); + + if ( noteRadius < 1 ) { + noteRadius = Mine.MINE_RESET__BROADCAST_RADIUS_BLOCKS; + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + Output.get().sendWarn( sender, "&7Invalid radius value. " + + "Must be an positive non-zero integer. Using the default value: &b%s &7[&b%s&7]", + dFmt.format(Mine.MINE_RESET__BROADCAST_RADIUS_BLOCKS), radius ); + return; + } + } + catch ( NumberFormatException e ) { + e.printStackTrace(); + Output.get().sendWarn( sender, "&7Invalid notification radius. " + + "Must be an positive non-zero integer. [&b%s&7]", + radius ); + return; + } + } + } + + PrisonMines pMines = PrisonMines.getInstance(); + + if ( "*all*".equalsIgnoreCase( mineName ) ) { + + int count = 0; + for ( Mine m : pMines.getMines() ) { + + if ( changeMineNotification( sender, mineName, noteMode, noteRadius, pMines, m, true ) ) { + count++; + } } - - Output.get().sendInfo( sender, "&7Notification mode was changed for &b%d&7 mines.", - count ); - } - - else if (performCheckMineExists(sender, mineName)) { - setLastMineReferenced(mineName); - - Mine m = pMines.getMine(mineName); - -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - - - changeMineNotification( sender, mineName, noteMode, noteRadius, pMines, m, false ); + + Output.get().sendInfo( sender, "&7Notification mode was changed for &b%d&7 mines.", + count ); + } + + else if (performCheckMineExists(sender, mineName)) { + setLastMineReferenced(mineName); + + Mine m = pMines.getMine(mineName); + + changeMineNotification( sender, mineName, noteMode, noteRadius, pMines, m, false ); } } @@ -2416,40 +2294,32 @@ public void setNotificationPermissionCommand(CommandSender sender, ) { - - if ( !action.equalsIgnoreCase( "enable" ) && !action.equalsIgnoreCase( "disable" )) { - sender.sendMessage( "&7Invalid value for action: [enable, disable]" ); - return; - } - - if ( "*all*".equalsIgnoreCase( mineName ) || - performCheckMineExists(sender, mineName)) { + if ( !action.equalsIgnoreCase( "enable" ) && !action.equalsIgnoreCase( "disable" )) { + sender.sendMessage( "&7Invalid value for action: [enable, disable]" ); + return; + } - PrisonMines pMines = PrisonMines.getInstance(); - - if ( "*all*".equalsIgnoreCase( mineName ) ) { - setLastMineReferenced(mineName); - - Mine m = pMines.getMine(mineName); - - minesSetNotificationPerm(sender, action, pMines, m); - } - else { - - for ( Mine m : pMines.getMines() ) { - minesSetNotificationPerm(sender, action, pMines, m); - } - } - -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - - - - } - } + if ( "*all*".equalsIgnoreCase( mineName ) || + performCheckMineExists(sender, mineName)) { + + PrisonMines pMines = PrisonMines.getInstance(); + + if ( "*all*".equalsIgnoreCase( mineName ) ) { + setLastMineReferenced(mineName); + + Mine m = pMines.getMine(mineName); + + minesSetNotificationPerm(sender, action, pMines, m); + } + else { + + for ( Mine m : pMines.getMines() ) { + minesSetNotificationPerm(sender, action, pMines, m); + } + } + + } + } private void minesSetNotificationPerm(CommandSender sender, String action, PrisonMines pMines, Mine m) { if ( action.equalsIgnoreCase( "enable" ) && !m.isUseNotificationPermission() ) { @@ -2499,23 +2369,22 @@ public void setMinePermissionCommand(CommandSender sender, if ( "*all*".equalsIgnoreCase( mineName ) || performCheckMineExists(sender, mineName)) { - PrisonMines pMines = PrisonMines.getInstance(); - - if ( "*all*".equalsIgnoreCase( mineName ) ) { - - for ( Mine m : pMines.getMines() ) { - - minesSetAccessPermission(sender, permission, pMines, m); - } - } - else { - setLastMineReferenced(mineName); - Mine m = pMines.getMine(mineName); - - minesSetAccessPermission(sender, permission, pMines, m); - } + PrisonMines pMines = PrisonMines.getInstance(); + + if ( "*all*".equalsIgnoreCase( mineName ) ) { + + for ( Mine m : pMines.getMines() ) { + + minesSetAccessPermission(sender, permission, pMines, m); + } + } + else { + setLastMineReferenced(mineName); + Mine m = pMines.getMine(mineName); + + minesSetAccessPermission(sender, permission, pMines, m); + } - } } @@ -2571,116 +2440,81 @@ public void setMineRankCommand(CommandSender sender, ) { - PrisonMines pMines = PrisonMines.getInstance(); - - if ( mineName != null && "*all*".equalsIgnoreCase( mineName ) ) { - - for ( Mine mine : pMines.getMines() ) { + PrisonMines pMines = PrisonMines.getInstance(); + + if ( mineName != null && "*all*".equalsIgnoreCase( mineName ) ) { + + for ( Mine mine : pMines.getMines() ) { if ( "*none*".equalsIgnoreCase( rankName ) && mine.getRank() != null ) { - // First unlink the preexisting mine and rank: - String removedRankName = mine.getRank().getName(); - - // unlinkModuleElement will do the saving - Prison.get().getPlatform().unlinkModuleElements( mine, mine.getRank() ); - - sender.sendMessage( String.format( "&3Rank &7%s &3has been removed from mine &7%s", - removedRankName, mine.getTag() )); + // First unlink the preexisting mine and rank: + String removedRankName = mine.getRank().getName(); + + // unlinkModuleElement will do the saving + Prison.get().getPlatform().unlinkModuleElements( mine, mine.getRank() ); + + sender.sendMessage( String.format( "&3Rank &7%s &3has been removed from mine &7%s", + removedRankName, mine.getTag() )); } else if ( "*mineName*".equalsIgnoreCase( rankName ) ) { - - boolean success = Prison.get().getPlatform().linkModuleElements( mine, - ModuleElementType.RANK, mine.getName() ); - - if ( !success ) { - sender.sendMessage( String.format( - "&3Invalid Rank Name for mine %s: &7%s", mine.getName(), mine.getName() )); - } - else { - sender.sendMessage( String.format( "&3Rank &7%s &3has been linked to mine &7%s", - rankName, mine.getTag() )); - } + + boolean success = Prison.get().getPlatform().linkModuleElements( mine, + ModuleElementType.RANK, mine.getName() ); + + if ( !success ) { + sender.sendMessage( String.format( + "&3Invalid Rank Name for mine %s: &7%s", mine.getName(), mine.getName() )); + } + else { + sender.sendMessage( String.format( "&3Rank &7%s &3has been linked to mine &7%s", + rankName, mine.getTag() )); + } } } - - return; - } - + + return; + } + if (performCheckMineExists(sender, mineName)) { - setLastMineReferenced(mineName); - - Mine m = pMines.getMine(mineName); - + setLastMineReferenced(mineName); + + Mine m = pMines.getMine(mineName); + if ( rankName == null || rankName.trim().length() == 0 ) { - sender.sendMessage( "&cRank name is required." ); - return; + sender.sendMessage( "&cRank name is required." ); + return; } if ( m.getRank() != null ) { - // First unlink the preexisting mine and rank: - String removedRankName = m.getRank().getName(); - - // unlinkModuleElement will do the saving - Prison.get().getPlatform().unlinkModuleElements( m, m.getRank() ); - - sender.sendMessage( String.format( "&3Rank &7%s &3has been removed from mine &7%s", - removedRankName, m.getTag() )); + // First unlink the preexisting mine and rank: + String removedRankName = m.getRank().getName(); + + // unlinkModuleElement will do the saving + Prison.get().getPlatform().unlinkModuleElements( m, m.getRank() ); + + sender.sendMessage( String.format( "&3Rank &7%s &3has been removed from mine &7%s", + removedRankName, m.getTag() )); } if ( !"*none*".equalsIgnoreCase( rankName ) ) { - boolean success = Prison.get().getPlatform().linkModuleElements( m, - ModuleElementType.RANK, rankName ); - - if ( !success ) { - sender.sendMessage( String.format( "&3Invalid Rank Name: &7%s", rankName )); - } - else { - sender.sendMessage( String.format( "&3Rank &7%s &3has been linked to mine &7%s", - rankName, m.getTag() )); - } + boolean success = Prison.get().getPlatform().linkModuleElements( m, + ModuleElementType.RANK, rankName ); + + if ( !success ) { + sender.sendMessage( String.format( "&3Invalid Rank Name: &7%s", rankName )); + } + else { + sender.sendMessage( String.format( "&3Rank &7%s &3has been linked to mine &7%s", + rankName, m.getTag() )); + } } } } - -/* - * Remove this command since the same functionality exists in /mines set rank: - * This will be removed shortly once the replacement is confirmed to work well. - * - * @Command(identifier = "mines set norank", permissions = "mines.set", - * description = "Unlinks a rank from a mine") - * public void setMineNoRankCommand(CommandSender sender, - * @Arg(name = "mineName", description = "The name of the mine.") String mineName - * - * ) { - * - * if (performCheckMineExists(sender, mineName)) { - * setLastMineReferenced(mineName); - * - * PrisonMines pMines = PrisonMines.getInstance(); - * Mine m = pMines.getMine(mineName); - * - * if ( m.getRank() == null ) { - * sender.sendMessage( "&cThis mine has no ranks to unlink." ); - * return; - * } - * - * ModuleElement rank = m.getRank(); - * - * Prison.get().getPlatform().unlinkModuleElements( m, m.getRank() ); - * - * - * sender.sendMessage( String.format( "&3Rank &7%s &3has been removed from mine &7%s", - * rank.getName(), m.getName() )); - * - * } - * } - * - */ @Command(identifier = "mines set area", permissions = "mines.set", @@ -2707,93 +2541,83 @@ public void redefineCommand(CommandSender sender, def = "---") String options ) { - if (!performCheckMineExists(sender, mineName)) { - return; - } + if (!performCheckMineExists(sender, mineName)) { + return; + } PrisonMines pMines = PrisonMines.getInstance(); Mine m = pMines.getMine(mineName); Player player = sender.getPlatformPlayer(); -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } Selection selection = null; if ( source != null && "feet".equalsIgnoreCase( source ) ) { - selection = new Selection( player.getLocation(), player.getLocation()); + selection = new Selection( player.getLocation(), player.getLocation()); } else if ( source == null || "wand".equalsIgnoreCase( source ) ) { - selection = Prison.get().getSelectionManager().getSelection( player ); + selection = Prison.get().getSelectionManager().getSelection( player ); } else if ( source == null || "virtual".equalsIgnoreCase( source ) ) { - // do nothing... don't set selection: + // do nothing... don't set selection: } else { - sender.sendMessage( "&3Valid values for &2source &3are &7wand&3, " + - "&7feet&3, and &7virtual&3." ); - return; + sender.sendMessage( "&3Valid values for &2source &3are &7wand&3, " + + "&7feet&3, and &7virtual&3." ); + return; } if ( selection == null ) { - // Revert the mine to a virtual mine: - - setLastMineReferenced(mineName); - - if ( m.isVirtual() ) { - // Already a virtual mine so exit: - String message = "Mine &7" + m.getName() + " &3is already virtual. No changes have been made."; - sender.sendMessage( message ); - - return; - } - - // Make a backup of the mine save file before making virtual: - File backupFile = pMines.getMineManager().backupMine( m ); - - String messageBu = "Mine &7" + m.getName() + " &3has " + - ( backupFile.exists() ? "been successfully" : "failed to be" ) + - " backed up: " + backupFile.getAbsolutePath(); - sender.sendMessage( messageBu ); - Output.get().logInfo( messageBu ); - - if ( !backupFile.exists() ) { - Output.get().logInfo( "Since the backup Failed, mine " + m.getName() + " cannot be " + - "virtualized." ); - - return; - } - - // Setting bounds to null will also set spawn to null, the two world fields to null, and - // make the mine virtual and disale the mine too: - m.setBounds( null ); -// m.setSpawn( null ); -// -// m.setWorld( null ); -// m.setWorldName( null ); -// -// m.setVirtual( true ); - - m.getJobStack().clear(); - - // TODO Possibly may need to kill existing jobs and/or set a mutex state of VIRTUAL? - m.getMineStateMutex(); - - pMines.getMineManager().saveMine( m ); - - String message = "Mine &7" + m.getName() + " &3has been set to virtual. "; - sender.sendMessage( message ); - - return; + // Revert the mine to a virtual mine: + + setLastMineReferenced(mineName); + + if ( m.isVirtual() ) { + // Already a virtual mine so exit: + String message = "Mine &7" + m.getName() + " &3is already virtual. No changes have been made."; + sender.sendMessage( message ); + + return; + } + + // Make a backup of the mine save file before making virtual: + File backupFile = pMines.getMineManager().backupMine( m ); + + String messageBu = "Mine &7" + m.getName() + " &3has " + + ( backupFile != null && backupFile.exists() ? "been successfully" : "failed to be" ) + + " backed up: " + (backupFile != null ? backupFile.getAbsolutePath() : "none"); + sender.sendMessage( messageBu ); + Output.get().logInfo( messageBu ); + + if ( !backupFile.exists() ) { + Output.get().logInfo( "Since the backup Failed, mine " + m.getName() + " cannot be " + + "virtualized." ); + + return; + } + + // Setting bounds to null will also set spawn to null, the two world fields to null, and + // make the mine virtual and disale the mine too: + m.setBounds( null ); + + m.getJobStack().clear(); + + // TODO Possibly may need to kill existing jobs and/or set a mutex state of VIRTUAL? + m.getMineStateMutex(); + + pMines.getMineManager().saveMine( m ); + + String message = "Mine &7" + m.getName() + " &3has been set to virtual. "; + sender.sendMessage( message ); + + return; } if (!selection.isComplete()) { - pMines.getMinesMessages().getLocalizable("select_bounds") - .sendTo(sender); + pMines.getMinesMessages().getLocalizable("select_bounds") + .sendTo(sender); return; } @@ -2808,27 +2632,27 @@ else if ( source == null || "virtual".equalsIgnoreCase( source ) ) { Bounds selectedBounds = selection.asBounds(); if ( Output.get().isDebug() ) { - String msg = String.format( "MinesSetArea Preset: Mine: %s Bounds: %s - %s ", - m.getName(), - selectedBounds.getMin().toWorldCoordinates(), - selectedBounds.getMax().toWorldCoordinates() - ); - Output.get().logInfo( msg ); + String msg = String.format( "MinesSetArea Preset: Mine: %s Bounds: %s - %s ", + m.getName(), + selectedBounds.getMin().toWorldCoordinates(), + selectedBounds.getMax().toWorldCoordinates() + ); + Output.get().logInfo( msg ); } if ( selectedBounds.getTotalBlockCount() > 50000 && (options == null || !options.toLowerCase().contains( "confirm" ) && !options.toLowerCase().contains( "yes" )) ) { - String message = String.format( "&7Warning: This mine has a size of %s. If this is " + - "intentional, then please re-submit this command with adding the " + - "keyword of either 'confirm' or 'yes' to the end of the command. ", - dFmt.format( selectedBounds.getTotalBlockCount() ) ); - sender.sendMessage( message ); - return; + String message = String.format( "&7Warning: This mine has a size of %s. If this is " + + "intentional, then please re-submit this command with adding the " + + "keyword of either 'confirm' or 'yes' to the end of the command. ", + dFmt.format( selectedBounds.getTotalBlockCount() ) ); + sender.sendMessage( message ); + return; } else if ( options.toLowerCase().contains( "confirm" ) || options.toLowerCase().contains( "yes" ) ) { - options = options.replace( "(?i)confirm|yes", "" ).trim(); + options = options.replace( "(?i)confirm|yes", "" ).trim(); } // TODO check to see if they are the same boundaries, if not, don't change... @@ -2841,7 +2665,7 @@ else if ( options.toLowerCase().contains( "confirm" ) || // Before setting the bounds, clear everything by setting them to nulls: // Setting bounds to null will also set spawn to null, the two world fields to null, and - // make the mine virtual and disable the mine too: + // make the mine virtual and disable the mine too: m.setBounds( null ); m.getJobStack().clear(); @@ -2850,18 +2674,15 @@ else if ( options.toLowerCase().contains( "confirm" ) || // Setting the bounds when it's virtual will configure all the internals: m.setBounds(selectedBounds); - - if ( wasVirtual ) { - - - String message = String.format( "&3The mine &7%s &3 is no longer a virutal mine " + - "and has been enabled with an area of &7%s &3blocks.", - m.getTag(), dFmt.format( m.getBounds().getTotalBlockCount() )); - - sender.sendMessage( message ); - Output.get().logInfo( message ); + + String message = String.format( "&3The mine &7%s &3 is no longer a virutal mine " + + "and has been enabled with an area of &7%s &3blocks.", + m.getTag(), dFmt.format( m.getBounds().getTotalBlockCount() )); + + sender.sendMessage( message ); + Output.get().logInfo( message ); } pMines.getMineManager().saveMine( m ); @@ -2871,50 +2692,49 @@ else if ( options.toLowerCase().contains( "confirm" ) || // Delete the selection: Prison.get().getSelectionManager().clearSelection((Player) sender); - //pMines.getMineManager().clearCache(); // adjustSize to zero to reset set all liners: if ( m.getLinerData() != null ) { - m.adjustSize( Edges.walls, 0 ); - - if ( options.length() > 0 ) { - String[] opts = options.split( " " ); - - // Try to set the size of the wall: Increase by: - if ( opts.length > 0 ) { - try { - int size = Integer.parseInt( opts[0] ); - setSizeCommand( sender, mineName, "walls", size ); - } - catch ( Exception e ) { - // ignore error - } - } - - // Try to set the size of the bottom: Increase by: - if ( opts.length > 1 ) { - try { - int size = Integer.parseInt( opts[1] ); - setSizeCommand( sender, mineName, "bottom", size ); - } - catch ( Exception e ) { - // ignore error - } - } - - // Try to set the size of the wall: Increase by: - if ( opts.length > 2 ) { - try { - int size = Integer.parseInt( opts[2] ); - setSizeCommand( sender, mineName, "top", size ); - } - catch ( Exception e ) { - // ignore error - } - } - - } + m.adjustSize( Edges.walls, 0 ); + + if ( options.length() > 0 ) { + String[] opts = options.split( " " ); + + // Try to set the size of the wall: Increase by: + if ( opts.length > 0 ) { + try { + int size = Integer.parseInt( opts[0] ); + setSizeCommand( sender, mineName, "walls", size ); + } + catch ( Exception e ) { + // ignore error + } + } + + // Try to set the size of the bottom: Increase by: + if ( opts.length > 1 ) { + try { + int size = Integer.parseInt( opts[1] ); + setSizeCommand( sender, mineName, "bottom", size ); + } + catch ( Exception e ) { + // ignore error + } + } + + // Try to set the size of the wall: Increase by: + if ( opts.length > 2 ) { + try { + int size = Integer.parseInt( opts[2] ); + setSizeCommand( sender, mineName, "top", size ); + } + catch ( Exception e ) { + // ignore error + } + } + + } } } @@ -2930,26 +2750,26 @@ public void backupMineCommand(CommandSender sender, @Arg(name = "mineName", description = "The name of the mine to edit.") String mineName ) { - if (!performCheckMineExists(sender, mineName)) { - return; - } + if (!performCheckMineExists(sender, mineName)) { + return; + } PrisonMines pMines = PrisonMines.getInstance(); Mine m = pMines.getMine(mineName); - // Make a backup of the mine save file before making virtual: - File backupFile = pMines.getMineManager().backupMine( m ); - - String messageBu = "Mine &7" + m.getName() + " &3has " + - ( backupFile.exists() ? "been successfully" : "failed to be" ) + - " backed up: " + backupFile.getAbsolutePath(); - - if ( sender.isPlayer() ) { - sender.sendMessage( messageBu ); - } - Output.get().logInfo( messageBu ); - + // Make a backup of the mine save file before making virtual: + File backupFile = pMines.getMineManager().backupMine( m ); + + String messageBu = "Mine &7" + m.getName() + " &3has " + + ( backupFile != null && backupFile.exists() ? "been successfully" : "failed to be" ) + + " backed up: " + (backupFile != null ? backupFile.getAbsolutePath() : "none"); + + if ( sender.isPlayer() ) { + sender.sendMessage( messageBu ); + } + Output.get().logInfo( messageBu ); + } @@ -2967,24 +2787,24 @@ public void setTracerCommand(CommandSender sender, + "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(); + 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; + sender.sendMessage( "&cMine is a virtual mine&7. Use &a/mines set area &7to enable the mine." ); + return; } mine.enableTracer( resetType ); @@ -3002,40 +2822,35 @@ public void setSizeCommand(CommandSender sender, ) { - if (!performCheckMineExists(sender, mineName)) { - return; - } - - Edges e = Edges.fromString( edge ); - if ( e == null ) { - sender.sendMessage( "&cInvalid edge value. [top, bottom, north, east, south, west, walls]" ); - return; - } - - if ( amount == 0 ) { - sender.sendMessage( "&cSize of mine will not be changed. Will refresh the liner." ); -// return; - } - -// if ( adjustment == null || "smaller".equalsIgnoreCase( adjustment ) || "larger".equalsIgnoreCase( adjustment ) ) { -// sender.sendMessage( "&cInvalid adjustment. [larger, smaller]" ); -// return; -// } - - 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.adjustSize( e, amount ); - - pMines.getMineManager().saveMine( mine ); - - + if (!performCheckMineExists(sender, mineName)) { + return; + } + + Edges e = Edges.fromString( edge ); + if ( e == null ) { + sender.sendMessage( "&cInvalid edge value. [top, bottom, north, east, south, west, walls]" ); + return; + } + + if ( amount == 0 ) { + sender.sendMessage( "&cSize of mine will not be changed. Will refresh the liner." ); + } + + + 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.adjustSize( e, amount ); + + pMines.getMineManager().saveMine( mine ); + + } @@ -3049,34 +2864,34 @@ public void moveMineCommand(CommandSender sender, ) { - if (!performCheckMineExists(sender, mineName)) { - return; - } - - Edges edge = Edges.fromString( direction ); - if ( edge == null || edge == Edges.walls ) { - sender.sendMessage( "&cInvalid direction value. [top, bottom, north, east, south, west]" ); - return; - } - - if ( amount < 1 ) { - sender.sendMessage( "&cInvalid amount. Must be 1 or more." ); - return; - } - - - PrisonMines pMines = PrisonMines.getInstance(); - Mine mine = pMines.getMine(mineName); - - if ( mine.isVirtual() ) { - sender.sendMessage( "&cMine is a virtual mine&7. Use &a/mines set area &7to enable the mine." ); - return; - } - + if (!performCheckMineExists(sender, mineName)) { + return; + } + + Edges edge = Edges.fromString( direction ); + if ( edge == null || edge == Edges.walls ) { + sender.sendMessage( "&cInvalid direction value. [top, bottom, north, east, south, west]" ); + return; + } + + if ( amount < 1 ) { + sender.sendMessage( "&cInvalid amount. Must be 1 or more." ); + return; + } - mine.moveMine( edge, amount ); - pMines.getMineManager().saveMine( mine ); + 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.moveMine( edge, amount ); + + pMines.getMineManager().saveMine( mine ); } @Command(identifier = "mines set liner", permissions = "mines.set", @@ -3100,148 +2915,99 @@ public void setLinerCommand(CommandSender sender, ) { - if ( mineName != null && "?".equals( mineName ) || - pattern != null && "?".equals( pattern ) || edge != null && "?".equals( edge )) { - - sender.sendMessage( "&cAvailable Edges: &3[&7top bottom north east south west walls&3]" ); - sender.sendMessage( "&3Available Patterns: [&7" + LinerPatterns.toStringAll() + "&3]" ); - sender.sendMessage( "&cUse 'ladderType' for the Edge: &3[&7none normal wide jumbo full&3] Where 'normal' is " + - "1 to 3 ladders wide. 'Wide' is up to 5 wide. 'Jumbo' is up to 7 wide. And 'full' is the full width." ); - return; - } - - if ( !"*all*".equalsIgnoreCase( mineName ) && !performCheckMineExists(sender, mineName)) { - return; - } - - Edges e = Edges.fromString( edge ); - LinerPatterns linerPattern = LinerPatterns.fromString( pattern ); - LadderType ladderType = ( e == null && edge != null && edge.equalsIgnoreCase( "ladderType" ) ? - LadderType.fromString( pattern ) : null ); - - - - if ( e == null && ladderType == null ) { - sender.sendMessage( "&cInvalid edge value. &3[&7top bottom north east south west walls&3]" ); - sender.sendMessage( "&cUse 'ladderType' for the Edge with &3[&7none normal wide jumbo full&3] as the patterns." ); - return; - } - - if ( linerPattern == null && ladderType == null ) { - sender.sendMessage( "&cInvalid pattern.&3 Select one of these: [&7" + - LinerPatterns.toStringAll() + "&3]" ); - return; - } - - boolean isForced = false; - if ( force != null && !"force".equalsIgnoreCase( force ) && !"no".equalsIgnoreCase( force ) ) { - sender.sendMessage( - String.format( "&3The valid values for &7force &3 are &7force&3 and &7no&3. " + - "Was &2[&7%s&2]", force ) ); - } - else if ( "force".equalsIgnoreCase( force ) ) { - isForced = true; - } - - PrisonMines pMines = PrisonMines.getInstance(); - - List mines = new ArrayList<>(); - - if ( "*all*".equalsIgnoreCase( mineName ) ) { - mines.addAll( pMines.getMines() ); - } - else { - mines.add( pMines.getMine(mineName) ); - - } - - for ( Mine mine : mines ) - { - boolean resetLiner = false; - -// if ( mine.isVirtual() ) { -// sender.sendMessage( "&cMine is a virtual mine.&7 Use &a/mines set area &7to enable the mine." ); -// return; -// } - if ( ladderType != null ) { - mine.getLinerData().setLadderType( ladderType ); - sender.sendMessage( "&7The liner's ladderType has been set to '" + ladderType.name() + - "' for mine " + mine.getName() ); - - resetLiner = true; - } - else if ( linerPattern == LinerPatterns.removeAll ) { - - mine.getLinerData().removeAll(); - sender.sendMessage( "&7All liners have been removed from mine " + mine.getName() ); - } - else if ( linerPattern == LinerPatterns.remove ) { - mine.getLinerData().remove( e ); - sender.sendMessage( "&7The liner for the " + e.name() + " has been removed from mine " + mine.getName() ); - } - else { - mine.getLinerData().setLiner( e, linerPattern, isForced ); - - resetLiner = true; - } - - pMines.getMineManager().saveMine( mine ); + if ( mineName != null && "?".equals( mineName ) || + pattern != null && "?".equals( pattern ) || edge != null && "?".equals( edge )) { + + sender.sendMessage( "&cAvailable Edges: &3[&7top bottom north east south west walls&3]" ); + sender.sendMessage( "&3Available Patterns: [&7" + LinerPatterns.toStringAll() + "&3]" ); + sender.sendMessage( "&cUse 'ladderType' for the Edge: &3[&7none normal wide jumbo full&3] Where 'normal' is " + + "1 to 3 ladders wide. 'Wide' is up to 5 wide. 'Jumbo' is up to 7 wide. And 'full' is the full width." ); + return; + } + + if ( !"*all*".equalsIgnoreCase( mineName ) && !performCheckMineExists(sender, mineName)) { + return; + } + + Edges e = Edges.fromString( edge ); + LinerPatterns linerPattern = LinerPatterns.fromString( pattern ); + LadderType ladderType = ( e == null && edge != null && edge.equalsIgnoreCase( "ladderType" ) ? + LadderType.fromString( pattern ) : null ); + + - // Do not try to update the liner if it's a virtual mine: - if ( resetLiner && !mine.isVirtual() ) { - - new MineLinerBuilder( mine, e, linerPattern, isForced ); - } + if ( e == null && ladderType == null ) { + sender.sendMessage( "&cInvalid edge value. &3[&7top bottom north east south west walls&3]" ); + sender.sendMessage( "&cUse 'ladderType' for the Edge with &3[&7none normal wide jumbo full&3] as the patterns." ); + return; + } + + if ( linerPattern == null && ladderType == null ) { + sender.sendMessage( "&cInvalid pattern.&3 Select one of these: [&7" + + LinerPatterns.toStringAll() + "&3]" ); + return; + } + + boolean isForced = false; + if ( force != null && !"force".equalsIgnoreCase( force ) && !"no".equalsIgnoreCase( force ) ) { + sender.sendMessage( + String.format( "&3The valid values for &7force &3 are &7force&3 and &7no&3. " + + "Was &2[&7%s&2]", force ) ); + } + else if ( "force".equalsIgnoreCase( force ) ) { + isForced = true; + } + + PrisonMines pMines = PrisonMines.getInstance(); + + List mines = new ArrayList<>(); + + if ( "*all*".equalsIgnoreCase( mineName ) ) { + mines.addAll( pMines.getMines() ); + } + else { + mines.add( pMines.getMine(mineName) ); + + } + + for ( Mine mine : mines ) { + boolean resetLiner = false; + + if ( ladderType != null ) { + mine.getLinerData().setLadderType( ladderType ); + sender.sendMessage( "&7The liner's ladderType has been set to '" + ladderType.name() + + "' for mine " + mine.getName() ); + + resetLiner = true; + } + else if ( linerPattern == LinerPatterns.removeAll ) { + + mine.getLinerData().removeAll(); + sender.sendMessage( "&7All liners have been removed from mine " + mine.getName() ); + } + else if ( linerPattern == LinerPatterns.remove ) { + mine.getLinerData().remove( e ); + sender.sendMessage( "&7The liner for the " + e.name() + " has been removed from mine " + mine.getName() ); + } + else { + mine.getLinerData().setLiner( e, linerPattern, isForced ); + + resetLiner = true; + } + + pMines.getMineManager().saveMine( mine ); + + // Do not try to update the liner if it's a virtual mine: + if ( resetLiner && !mine.isVirtual() ) { + + new MineLinerBuilder( mine, e, linerPattern, isForced ); + } } } -// @Command(identifier = "mines set resetpaging", permissions = "mines.resetpaging", -// description = "Enable paging during a mine reset.") -// public void setMineResetPagingCommand(CommandSender sender, -// @Arg(name = "mineName", description = "The name of the mine to edit.") String mineName, -// @Arg(name = "paging", def="disabled", -// description = "Enable or disable paging [disable, enable]") -// String paging -// ) { -// -// if (performCheckMineExists(sender, mineName)) { -// setLastMineReferenced(mineName); -// -// PrisonMines pMines = PrisonMines.getInstance(); -// Mine m = pMines.getMine(mineName); -// -//// if ( !m.isEnabled() ) { -//// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -//// return; -//// } -// -// if ( paging == null || !"disable".equalsIgnoreCase( paging ) && !"enable".equalsIgnoreCase( paging ) ) { -// sender.sendMessage( "&cInvalid paging option&7. Use &adisable&7 or &aenable&7" ); -// return; -// } -// -// if ( "disable".equalsIgnoreCase( paging ) && m.isUsePagingOnReset() ) { -// m.setUsePagingOnReset( false ); -// pMines.getMineManager().saveMine( m ); -// sender.sendMessage( String.format( "&7Mine Reset Paging has been disabled for mine %s.", m.getTag()) ); -// } -// else if ( "enable".equalsIgnoreCase( paging ) && !m.isUsePagingOnReset() ) { -// m.setUsePagingOnReset( true ); -// pMines.getMineManager().saveMine( m ); -// sender.sendMessage( String.format( "&7Mine Reset Paging has been enabled for mine %s.", m.getTag()) ); -// } -// else { -// sender.sendMessage( String.format( "&7Mine Reset Paging status has not changed for mine %s.", m.getTag()) ); -// -// } -// -// } -// } - - @Command(identifier = "mines set mineSweeper", permissions = "mines.set", description = "Enable the Mine Sweeper task that is used to update the block counts " + "in the mine if there is another plugin that is breaking blocks and " + @@ -3260,63 +3026,64 @@ public void setMineSweeperCommand(CommandSender sender, String mineSweeper ) { - if ( mineSweeper == null || !"disable".equalsIgnoreCase( mineSweeper ) && - !"enable".equalsIgnoreCase( mineSweeper ) ) { - sender.sendMessage( "&cInvalid paging option&7. Use &adisable&7 or &aenable&7" ); - return; - } - - PrisonMines pMines = PrisonMines.getInstance(); - - if ( mineName != null && "*all*".equalsIgnoreCase( mineName ) ) { - - for ( Mine mine : pMines.getMines() ) { - if ( "disable".equalsIgnoreCase( mineSweeper ) && mine.isMineSweeperEnabled() ) { - mine.setMineSweeperEnabled( false ); - pMines.getMineManager().saveMine( mine ); - sender.sendMessage( String.format( "&7Mine Sweeper has been disabled for mine %s.", mine.getTag()) ); - } - else if ( "enable".equalsIgnoreCase( mineSweeper ) && !mine.isMineSweeperEnabled() ) { - mine.setMineSweeperEnabled( true ); - pMines.getMineManager().saveMine( mine ); - sender.sendMessage( String.format( "&7Mine Sweeper has been enabled for mine %s.", mine.getTag()) ); - } - } - - return; - } - + if ( mineSweeper == null || !"disable".equalsIgnoreCase( mineSweeper ) && + !"enable".equalsIgnoreCase( mineSweeper ) ) { + sender.sendMessage( "&cInvalid paging option&7. Use &adisable&7 or &aenable&7" ); + return; + } + + PrisonMines pMines = PrisonMines.getInstance(); + + if ( mineName != null && "*all*".equalsIgnoreCase( mineName ) ) { + + for ( Mine mine : pMines.getMines() ) { + if ( "disable".equalsIgnoreCase( mineSweeper ) && mine.isMineSweeperEnabled() ) { + mine.setMineSweeperEnabled( false ); + pMines.getMineManager().saveMine( mine ); + sender.sendMessage( String.format( "&7Mine Sweeper has been disabled for mine %s.", mine.getTag()) ); + } + else if ( "enable".equalsIgnoreCase( mineSweeper ) && !mine.isMineSweeperEnabled() ) { + mine.setMineSweeperEnabled( true ); + pMines.getMineManager().saveMine( mine ); + sender.sendMessage( String.format( "&7Mine Sweeper has been enabled for mine %s.", mine.getTag()) ); + } + } + + return; + } + if (performCheckMineExists(sender, mineName)) { - setLastMineReferenced(mineName); - - Mine m = pMines.getMine(mineName); + setLastMineReferenced(mineName); + + Mine m = pMines.getMine(mineName); if ( "disable".equalsIgnoreCase( mineSweeper ) && m.isMineSweeperEnabled() ) { - m.setMineSweeperEnabled( false ); - pMines.getMineManager().saveMine( m ); - sender.sendMessage( String.format( "&7Mine Sweeper has been disabled for mine %s.", m.getTag()) ); + m.setMineSweeperEnabled( false ); + pMines.getMineManager().saveMine( m ); + sender.sendMessage( String.format( "&7Mine Sweeper has been disabled for mine %s.", m.getTag()) ); } else if ( "enable".equalsIgnoreCase( mineSweeper ) && !m.isMineSweeperEnabled() ) { - m.setMineSweeperEnabled( true ); - pMines.getMineManager().saveMine( m ); - sender.sendMessage( String.format( "&7Mine Sweeper has been enabled for mine %s.", m.getTag()) ); + m.setMineSweeperEnabled( true ); + pMines.getMineManager().saveMine( m ); + sender.sendMessage( String.format( "&7Mine Sweeper has been enabled for mine %s.", m.getTag()) ); } else { sender.sendMessage( String.format( "&7Mine Sweeper status has not changed for mine %s.", m.getTag()) ); } - } + } } - @Command(identifier = "mines tp", description = "TP to the mine. Will default to the mine's " + + @Command(identifier = "mines tp", onlyPlayers = false, + description = "TP to the mine. Will default to the mine's " + "spawn location if set, but can specify the target [spawn, mine]. Instead of a mine " + "name, 'list' will show all mines you have access to. OPs and console can " + "TP other online players to a specified mine. Access for non-OPs can be setup through " + "'/mines set tpAccessByRank help` is preferred over permissions.", - aliases = "mtp", + aliases = "mtp", altPermissions = {"access-by-rank", "mines.tp", "mines.tp.[mineName]"}) public void mineTp(CommandSender sender, @Arg(name = "mineName", def="", @@ -3332,177 +3099,167 @@ public void mineTp(CommandSender sender, ) { - if ( mineName != null && - "list".equals( mineName )) { - - Player player = getPlayer( sender, playerName ); - -// Player playerAlt = getPlayer( playerName ); -// -// if ( playerAlt != null ) { -// player = playerAlt; -// } - - if ( player == null ) { - Output.get().logInfo( "Mine TP List: You must either be a player, or refer to a valid player." ); - return; - } - - Prison.get().getPlatform().listAllMines( sender, player ); - - return; - } - - - if ( mineName != null && - ("spawn".equalsIgnoreCase( mineName ) || "mine".equalsIgnoreCase( mineName )) ) { - target = mineName; - // Since the value spawn and mine are the last parameters, then we know playerName and - // mineName were not provided so set them to empty Strings: - playerName = ""; - mineName = ""; - } - - - // If playerName was not specified, then it could contain the value of target, if so, then copy - // to the target variable and set playerName to an empty String. - if ( playerName != null && - ("spawn".equalsIgnoreCase( playerName ) || "mine".equalsIgnoreCase( playerName )) ) { - target = playerName; - playerName = ""; - } - - // Only valid values are mine and spawn, if anything other than these, set value to spawn: - if ( target == null || - !("spawn".equalsIgnoreCase( target ) || "mine".equalsIgnoreCase( target )) ) { - target = "spawn"; - } - //setLastMineReferenced(mineName); - - PrisonMines pMines = PrisonMines.getInstance(); - Mine m = null; - - - if ( mineName == null || mineName.trim().isEmpty() ) { - // Need to find a "correct" mine to TP to. - - m = (Mine) Prison.get().getPlatform().getPlayerDefaultMine( sender ); - - if ( m == null ) { - - teleportNoTargetMineFoundMsg( sender ); - return; - } - } - else { - - // Load mine information first to confirm the mine exists and the parameter is correct: - if (!performCheckMineExists(sender, mineName)) { - return; - } - - - m = pMines.getMine(mineName); - } - - - - if ( m.isVirtual() ) { - teleportCannotUseVirtualMinesMsg( sender ); - return; - } - - - Player player = sender.getPlatformPlayer(); - - Player playerAlt = getOnlinePlayer( playerName ); - + if ( mineName != null && + "list".equals( mineName )) { + + Player player = playerName != null && playerName.trim().length() > 0 ? + getPlayerByName( playerName ) : + sender.getRankPlayer(); + + if ( player == null ) { + Output.get().logInfo( "Mine TP List: You must either be a player, or refer to a valid player." ); + return; + } + + Prison.get().getPlatform().listAllMines( sender, player ); + + return; + } - if ( playerName != null && playerName.trim().length() > 0 && playerAlt == null) { - teleportNamedPlayerMustBeIngameMsg( sender ); - return; - } - - - if ( (player == null || !player.isOnline()) && playerAlt != null && !playerAlt.isOnline() ) { - - teleportPlayerMustBeIngameMsg( sender ); - return; - } - - - boolean isOp = sender.isOp(); + + if ( mineName != null && + ("spawn".equalsIgnoreCase( mineName ) || "mine".equalsIgnoreCase( mineName )) ) { + target = mineName; + // Since the value spawn and mine are the last parameters, then we know playerName and + // mineName were not provided so set them to empty Strings: + playerName = ""; + mineName = ""; + } + + + // If playerName was not specified, then it could contain the value of target, if so, then copy + // to the target variable and set playerName to an empty String. + if ( playerName != null && + ("spawn".equalsIgnoreCase( playerName ) || "mine".equalsIgnoreCase( playerName )) ) { + target = playerName; + playerName = ""; + } + + // Only valid values are mine and spawn, if anything other than these, set value to spawn: + if ( target == null || + !("spawn".equalsIgnoreCase( target ) || "mine".equalsIgnoreCase( target )) ) { + target = "spawn"; + } + + PrisonMines pMines = PrisonMines.getInstance(); + Mine m = null; - if ( isOp && playerAlt != null && playerAlt.isOnline() ) { - - // The person issuing the tp command is op and they are trying to TP another player - player = playerAlt; - - // Console is trying to TP someone, the other checks do not apply: - teleportPlayer( playerAlt, m, target ); - return; - } - else if ( (player == null || !player.isOnline()) && playerAlt != null && playerAlt.isOnline() ) { - - // If the sender is console or its being ran as a rank command, and the playerName is - // a valid online player, then TP them: - - teleportPlayer( playerAlt, m, target ); - return; - } - else if ( playerAlt != null && !player.getName().equalsIgnoreCase( playerAlt.getName() ) ) { - - teleportCannotTeleportOtherPlayersMsg( sender ); - return; - } + // Reset the sender's miscText field: + sender.setMiscText( null ); + + if ( mineName == null || mineName.trim().isEmpty() ) { + // Need to find a "correct" mine to TP to. + + m = (Mine) Prison.get().getPlatform().getPlayerDefaultMine( sender ); + + if ( m == null ) { + + teleportNoTargetMineFoundMsg( sender ); + return; + } + } + else { + + // Load mine information first to confirm the mine exists and the parameter is correct: + if (!performCheckMineExists(sender, mineName)) { + return; + } + + + m = pMines.getMine(mineName); + } + + + + if ( m.isVirtual() ) { + teleportCannotUseVirtualMinesMsg( sender ); + return; + } + + + Player player = sender.getPlatformPlayer(); + + + // This is not working... it should return an online player... + Player playerAlt = getOnlinePlayer( playerName ); + + + if ( playerName != null && playerName.trim().length() > 0 && playerAlt == null) { + teleportNamedPlayerMustBeIngameMsg( sender ); + return; + } - // From here on down, cannot use playerAlt, so must use either sender or player: - if ( mineName == null || mineName.trim().isEmpty() ) { - // Need to find a "correct" mine to TP to. - - m = (Mine) Prison.get().getPlatform().getPlayerDefaultMine( sender ); - - if ( m == null ) { - - teleportNoTargetMineFoundMsg( sender ); - return; - } - } + if ( (player == null || !player.isOnline()) && playerAlt != null && !playerAlt.isOnline() ) { + + teleportPlayerMustBeIngameMsg( sender ); + return; + } + + + boolean isOp = sender.isOp(); + + if ( isOp && playerAlt != null && playerAlt.isOnline() ) { + + // The person issuing the tp command is op and they are trying to TP another player + player = playerAlt; + + // Console is trying to TP someone, the other checks do not apply: + teleportPlayer( playerAlt, m, target ); + return; + } + else if ( (player == null || !player.isOnline()) && playerAlt != null && playerAlt.isOnline() ) { + + // If the sender is console or its being ran as a rank command, and the playerName is + // a valid online player, then TP them: + + teleportPlayer( playerAlt, m, target ); + return; + } + else if ( playerAlt != null && !player.getName().equalsIgnoreCase( playerAlt.getName() ) ) { + + teleportCannotTeleportOtherPlayersMsg( sender ); + return; + } + + // From here on down, cannot use playerAlt, so must use either sender or player: + + if ( mineName == null || mineName.trim().isEmpty() ) { + // Need to find a "correct" mine to TP to. + + m = (Mine) Prison.get().getPlatform().getPlayerDefaultMine( sender ); + + if ( m == null ) { + + teleportNoTargetMineFoundMsg( sender ); + return; + } + } - // NOTE: Mine.hasTPAccess() checks for rank access and also if they have perms set. + // NOTE: Mine.hasTPAccess() checks for rank access and also if they have perms set. if ( !isOp && !m.hasTPAccess( player ) ) { - teleportUnableToTeleportMsg( sender ); - return; - + teleportUnableToTeleportMsg( sender ); + return; + } -// String minePermission = "mines.tp." + m.getName().toLowerCase(); -// if ( !isOp && -// !sender.hasPermission("mines.tp") && -// !sender.hasPermission( minePermission ) ) { -// -// Output.get() -// .sendError(sender, "Sorry. You're unable to teleport there." ); -// return; -// } - - - -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - - if ( sender.isPlayer() ) { - teleportPlayer( (Player) sender, m, target ); -// m.teleportPlayerOut( (Player) sender, target ); - } else { - teleportFailedMsg( sender ); - } + + if ( sender.isPlayer() ) { + teleportPlayer( (Player) sender, m, target ); + + String msg = teleportSuccessMsg( m.getTag() ); + + if ( sender.getMiscText() != null ) { + msg = msg + " " + sender.getMiscText(); + } + sender.sendMessage( msg ); + + } else { + teleportFailedMsg( sender ); + } } @@ -3517,66 +3274,60 @@ else if ( playerAlt != null && !player.getName().equalsIgnoreCase( playerAlt.get public void mineTpTop(CommandSender sender ) { - Player player = sender.getPlatformPlayer(); - //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, "", "", ""); - } - - + Player player = sender.getPlatformPlayer(); + + 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" ) ) { - - // if warm up enabled: - double maxDistance = Prison.get().getPlatform(). - getConfigDouble( "prison-mines.tp-warmup.movementMaxDistance", 1.0 ); - long delayInTicks = Prison.get().getPlatform(). - getConfigLong( "prison-mines.tp-warmup.delayInTicks", 20 ); - - MineTeleportWarmUpTask mineTeleportWarmUp = new MineTeleportWarmUpTask( - player, mine, target, maxDistance ); - PrisonTaskSubmitter.runTaskLater( mineTeleportWarmUp, delayInTicks ); - } - else { - - mine.teleportPlayerOut( player, target ); - - // To "move" the player out of the mine, they are elevated by one block above the surface - // so need to remove the glass block if one is spawned under them. If there is no glass - // block, then it will do nothing. - mine.submitTeleportGlassBlockRemoval(); - } - - + if ( Prison.get().getPlatform().getConfigBooleanFalse( "prison-mines.tp-warmup.enabled" ) ) { + + // if warm up enabled: + double maxDistance = Prison.get().getPlatform(). + getConfigDouble( "prison-mines.tp-warmup.movementMaxDistance", 1.0 ); + long delayInTicks = Prison.get().getPlatform(). + getConfigLong( "prison-mines.tp-warmup.delayInTicks", 20 ); + + MineTeleportWarmUpTask mineTeleportWarmUp = new MineTeleportWarmUpTask( + player, mine, target, maxDistance ); + PrisonTaskSubmitter.runTaskLater( mineTeleportWarmUp, delayInTicks ); + } + else { + + mine.teleportPlayerOut( player, target ); + + // To "move" the player out of the mine, they are elevated by one block above the surface + // so need to remove the glass block if one is spawned under them. If there is no glass + // block, then it will do nothing. + mine.submitTeleportGlassBlockRemoval(); + } } @@ -3586,22 +3337,22 @@ private void teleportPlayer( Player player, Mine mine, String target ) { "(1 tick vs. 10 ticks).") public void mineStats(CommandSender sender) { - PrisonMines pMines = PrisonMines.getInstance(); - MineManager mMan = pMines.getMineManager(); - - // toggle the stats: - mMan.setMineStats( !mMan.isMineStats() ); - - // When mine stats are enabled, then it will also enable the high resolution - // tracking of the Prison TPS: - Prison.get().getPrisonTPS().setHighResolution( mMan.isMineStats() ); - - if ( mMan.isMineStats() ) { - sender.sendMessage( - "&3Mine Stats are now enabled. Use &7/mines list&3 to view stats on last mine reset. "); - } else { - sender.sendMessage( "&3Mine stats are now disabled." ); - } + PrisonMines pMines = PrisonMines.getInstance(); + MineManager mMan = pMines.getMineManager(); + + // toggle the stats: + mMan.setMineStats( !mMan.isMineStats() ); + + // When mine stats are enabled, then it will also enable the high resolution + // tracking of the Prison TPS: + Prison.get().getPrisonTPS().setHighResolution( mMan.isMineStats() ); + + if ( mMan.isMineStats() ) { + sender.sendMessage( + "&3Mine Stats are now enabled. Use &7/mines list&3 to view stats on last mine reset. "); + } else { + sender.sendMessage( "&3Mine stats are now disabled." ); + } } @@ -3610,102 +3361,90 @@ public void mineStats(CommandSender sender) { description = "Identifies what mines you are in, or are the closest to." ) public void mineWhereAmI(CommandSender sender) { - Player player = sender.getPlatformPlayer(); - - if (player == null || !player.isOnline()) { - sender.sendMessage( "&3You must be a player in the game to run this command." ); - return; - } - - player.sendMessage( "&3Your coordinates are: &7" + player.getLocation().toBlockCoordinates() ); - - PrisonMines pMines = PrisonMines.getInstance(); - - - Mine lookingAtMine = null; - - List sightBlocks = player.getLineOfSightBlocks(); - -// Block sightBlock = player.getLineOfSightBlock(); -// Location sightLocation = sightBlock != null ? sightBlock.getLocation() : null; - - - List inMine = new ArrayList<>(); - TreeMap nearMine = new TreeMap<>(); - for ( Mine mine : pMines.getMineManager().getMines() ) { - - - // Check the first 10 blocks in the line of sight to see if any are in a mine. - // The reason why the first 10 are checked is to "look" through mine liners. - if ( lookingAtMine == null && sightBlocks.size() > 0 ) { - int cnt = 0; - for ( Block sightBlock : sightBlocks ) { - if ( mine.isInMineExact( sightBlock.getLocation() ) ) { - lookingAtMine = mine; - break; - } - if ( cnt++ < 10 ) { + Player player = sender.getPlatformPlayer(); + + if (player == null || !player.isOnline()) { + sender.sendMessage( "&3You must be a player in the game to run this command." ); + return; + } + + player.sendMessage( "&3Your coordinates are: &7" + player.getLocation().toBlockCoordinates() ); + + PrisonMines pMines = PrisonMines.getInstance(); + + + Mine lookingAtMine = null; + + List sightBlocks = player.getLineOfSightBlocks(); + + List inMine = new ArrayList<>(); + TreeMap nearMine = new TreeMap<>(); + for ( Mine mine : pMines.getMineManager().getMines() ) { + + + // Check the first 10 blocks in the line of sight to see if any are in a mine. + // The reason why the first 10 are checked is to "look" through mine liners. + if ( lookingAtMine == null && sightBlocks.size() > 0 ) { + int cnt = 0; + for ( Block sightBlock : sightBlocks ) { + if ( mine.isInMineExact( sightBlock.getLocation() ) ) { + lookingAtMine = mine; + break; + } + if ( cnt++ < 10 ) { + break; + } + } + } + + if ( !mine.isVirtual() && mine.getBounds().withinIncludeTopBottomOfMine( player.getLocation() ) ) { + inMine.add( mine ); + } + + // This is checking for within a certain distance from any mine, so we just need to use + // some arbitrary distance as a max radius. We do not want to use the individual values + // that have been set for each mine. + else if ( !mine.isVirtual() && mine.getBounds().within( player.getLocation(), + Mine.MINE_RESET__BROADCAST_RADIUS_BLOCKS) ) { + Double distance = mine.getBounds().getDistance3d( player.getLocation() ); + nearMine.put( distance.intValue(), mine ); + } + } + + if ( lookingAtMine != null ) { + double distance = lookingAtMine.getBounds().getDistance3d( player.getLocation() ); + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.0"); + sender.sendMessage( String.format( "&3You are looking at mine &7%s &3which is &7%s &3blocks away.", + lookingAtMine.getTag(), dFmt.format( distance ) ) ); + } + + if ( inMine.size() > 0 ) { + // You are in the mines: + for ( Mine m : inMine ) { + sender.sendMessage( "&3You are in mine &7" + m.getTag() ); + } + } + if ( nearMine.size() > 0 ) { + // You are near the mines: + int cnt = 0; + Set distances = nearMine.keySet(); + for ( Integer dist : distances ) { + Mine m = nearMine.get( dist ); + sender.sendMessage( "&3You are &7" + dist + " &7blocks away from the center of mine &3" + m.getTag() ); + if ( ++cnt >= 5 ) { break; } } - } -// if ( sightLocation != null && mine.isInMineExact( sightLocation )) { -// lookingAtMine = mine; -// } - - if ( !mine.isVirtual() && mine.getBounds().withinIncludeTopBottomOfMine( player.getLocation() ) ) { - inMine.add( mine ); - } - - // This is checking for within a certain distance from any mine, so we just need to use - // some arbitrary distance as a max radius. We do not want to use the individual values - // that have been set for each mine. - else if ( !mine.isVirtual() && mine.getBounds().within( player.getLocation(), - MineData.MINE_RESET__BROADCAST_RADIUS_BLOCKS) ) { - Double distance = mine.getBounds().getDistance3d( player.getLocation() ); -// Double distance = new Bounds( mine.getBounds().getCenter(), player.getLocation()).getDistance(); - nearMine.put( distance.intValue(), mine ); - } - } - - if ( lookingAtMine != null ) { - double distance = lookingAtMine.getBounds().getDistance3d( player.getLocation() ); - DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.0"); - sender.sendMessage( String.format( "&3You are looking at mine &7%s &3which is &7%s &3blocks away.", - lookingAtMine.getTag(), dFmt.format( distance ) ) ); - } - - if ( inMine.size() > 0 ) { - // You are in the mines: - for ( Mine m : inMine ) { - sender.sendMessage( "&3You are in mine &7" + m.getTag() ); - } - } - if ( nearMine.size() > 0 ) { - // You are near the mines: - int cnt = 0; - Set distances = nearMine.keySet(); - for ( Integer dist : distances ) { - Mine m = nearMine.get( dist ); - sender.sendMessage( "&3You are &7" + dist + " &7blocks away from the center of mine &3" + m.getTag() ); - if ( ++cnt >= 5 ) { - break; - } - } - - } - else if ( inMine.size() == 0 ) { - // you are not near any mines: - sender.sendMessage( "&3Sorry, you are not within " + MineData.MINE_RESET__BROADCAST_RADIUS_BLOCKS + - " blocks from any mine." ); - } + + } + else if ( inMine.size() == 0 ) { + // you are not near any mines: + sender.sendMessage( "&3Sorry, you are not within " + Mine.MINE_RESET__BROADCAST_RADIUS_BLOCKS + + " blocks from any mine." ); + } } -// private Player getPlayer( CommandSender sender ) { -// Optional player = Prison.get().getPlatform().getPlayer( sender.getName() ); -// return player.isPresent() ? player.get() : null; -// } private Player getOnlinePlayer( String playerName ) { Player player = null; @@ -3723,12 +3462,12 @@ private Player getOnlinePlayer( String playerName ) { onlyPlayers = false ) public void wandCommand(CommandSender sender) { - Player player = sender.getPlatformPlayer(); - - if (player == null || !player.isOnline()) { - sender.sendMessage( "&3You must be a player in the game to run this command." ); - return; - } + Player player = sender.getPlatformPlayer(); + + if (player == null || !player.isOnline()) { + sender.sendMessage( "&3You must be a player in the game to run this command." ); + return; + } Prison.get().getSelectionManager().bestowSelectionTool(player); sender.sendMessage( @@ -3753,7 +3492,6 @@ public void blockEventList(CommandSender sender, setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); if (m.getBlockEvents() == null || m.getBlockEvents().size() == 0) { @@ -3783,82 +3521,60 @@ private void generateBlockEventListing( Mine m, ChatDisplay display, boolean inc int rowNumber = 0; for (MineBlockEvent blockEvent : m.getBlockEvents()) { - RowComponent row = new RowComponent(); - - String chance = dFmt.format( blockEvent.getChance() ); - - row.addTextComponent( " &3Row: &d%d ", ++rowNumber ); - - FancyMessage msgPercent = new FancyMessage( String.format( "&7%s%% ", chance ) ) - .suggest( "/mines blockEvent percent " + m.getName() + " " + rowNumber + " [%]" ) - .tooltip("Percent Chance - Click to Edit"); - row.addFancy( msgPercent ); - - FancyMessage msgPerm = new FancyMessage( String.format( "&3[&7%s&3] ", - blockEvent.getPermission() ) ) - .suggest( "/mines blockEvent permission " + m.getName() + " " + rowNumber + " [permisson]" ) - .tooltip("Permission - Click to Edit"); - row.addFancy( msgPerm ); - - FancyMessage msgEventType = new FancyMessage( String.format( "&7%s", - blockEvent.getEventType().name() ) ) - .suggest( "/mines blockEvent eventType " + m.getName() + " " + rowNumber + " [eventType]" ) - .tooltip("Event Type - Click to Edit"); - row.addFancy( msgEventType ); - - if ( blockEvent.getTriggered() != null ) { - - FancyMessage msgTriggered = new FancyMessage( String.format( "&3:&7%s", - blockEvent.getTriggered() ) ) - .suggest( "/mines blockEvent triggered " + m.getName() + " " + rowNumber + " [triggered]" ) - .tooltip("Triggered - Click to Edit"); - row.addFancy( msgTriggered ); - } - - FancyMessage msgMode = new FancyMessage( String.format( " &3(&7%s&3) ", - blockEvent.getTaskMode().name() ) ) - .suggest( "/mines blockEvent mode " + m.getName() + " " + rowNumber + " [mode]" ) - .tooltip("Event Task Mode - Click to Edit"); - row.addFancy( msgMode ); - - FancyMessage msgCommand = new FancyMessage( String.format( " &a'&7%s&a'", - blockEvent.getCommand() ) ) - //.command("/mines blockEvent remove " + mineName + " " + blockEvent.getCommand() ) - .suggest( "/mines blockEvent update " + m.getName() + " " + rowNumber + " " + blockEvent.getCommand() ) - .tooltip("BlockEvent Command - Click to Edit"); - row.addFancy( msgCommand ); - - -// if ( blockEvent.getPrisonBlocks().size() > 0 ) { -// StringBuilder sb = new StringBuilder(); -// -// for ( PrisonBlock block : blockEvent.getPrisonBlocks() ) { -// if ( sb.length() > 0 ) { -// sb.append( ", " ); -// } -// sb.append( block.getBlockName() ); -// } -// if ( sb.length() > 0 ) { -// sb.insert( 0, "[" ); -// sb.append( "]" ); -// -// FancyMessage msgBlocks = new FancyMessage( sb.toString() ) -// .tooltip( "Block filters. Click block list to add another." ) -// .suggest( "/mines blockvent block add " + m.getName() + " " + -// rowNumber + " block_name" ); -// -// row.addFancy( msgBlocks ); -// } -// } - - if ( includeRemove ) { - - FancyMessage msgRemove = new FancyMessage( " &4Remove&3" ) - .suggest("/mines blockEvent remove " + m.getName() + " " + rowNumber ) - .tooltip("Click to Delete this BlockEvent"); - row.addFancy( msgRemove ); - } - + RowComponent row = new RowComponent(); + + String chance = dFmt.format( blockEvent.getChance() ); + + row.addTextComponent( " &3Row: &d%d ", ++rowNumber ); + + FancyMessage msgPercent = new FancyMessage( String.format( "&7%s%% ", chance ) ) + .suggest( "/mines blockEvent percent " + m.getName() + " " + rowNumber + " [%]" ) + .tooltip("Percent Chance - Click to Edit"); + row.addFancy( msgPercent ); + + FancyMessage msgPerm = new FancyMessage( String.format( "&3[&7%s&3] ", + blockEvent.getPermission() ) ) + .suggest( "/mines blockEvent permission " + m.getName() + " " + rowNumber + " [permisson]" ) + .tooltip("Permission - Click to Edit"); + row.addFancy( msgPerm ); + + FancyMessage msgEventType = new FancyMessage( String.format( "&7%s", + blockEvent.getEventType().name() ) ) + .suggest( "/mines blockEvent eventType " + m.getName() + " " + rowNumber + " [eventType]" ) + .tooltip("Event Type - Click to Edit"); + row.addFancy( msgEventType ); + + if ( blockEvent.getTriggered() != null ) { + + FancyMessage msgTriggered = new FancyMessage( String.format( "&3:&7%s", + blockEvent.getTriggered() ) ) + .suggest( "/mines blockEvent triggered " + m.getName() + " " + rowNumber + " [triggered]" ) + .tooltip("Triggered - Click to Edit"); + row.addFancy( msgTriggered ); + } + + FancyMessage msgMode = new FancyMessage( String.format( " &3(&7%s&3) ", + blockEvent.getTaskMode().name() ) ) + .suggest( "/mines blockEvent mode " + m.getName() + " " + rowNumber + " [mode]" ) + .tooltip("Event Task Mode - Click to Edit"); + row.addFancy( msgMode ); + + FancyMessage msgCommand = new FancyMessage( String.format( " &a'&7%s&a'", + blockEvent.getCommand() ) ) + //.command("/mines blockEvent remove " + mineName + " " + blockEvent.getCommand() ) + .suggest( "/mines blockEvent update " + m.getName() + " " + rowNumber + " " + blockEvent.getCommand() ) + .tooltip("BlockEvent Command - Click to Edit"); + row.addFancy( msgCommand ); + + + if ( includeRemove ) { + + FancyMessage msgRemove = new FancyMessage( " &4Remove&3" ) + .suggest("/mines blockEvent remove " + m.getName() + " " + rowNumber ) + .tooltip("Click to Delete this BlockEvent"); + row.addFancy( msgRemove ); + } + builder.add( row ); @@ -3866,17 +3582,17 @@ private void generateBlockEventListing( Mine m, ChatDisplay display, boolean inc String prisonBlocks = blockEvent.getPrisonBlockStrings(); if ( !prisonBlocks.isEmpty() ) { - RowComponent row2 = new RowComponent(); - - row2.addTextComponent( " " ); - - FancyMessage msgBlocks = new FancyMessage( String.format( " &bBlocks: &3[&7%s&3]", - prisonBlocks ) ) - .command("/mines blockEvent blocks " + m.getName() ) - .tooltip("Event Blocks - Click to Edit"); - row2.addFancy( msgBlocks ); - - builder.add( row2 ); + RowComponent row2 = new RowComponent(); + + row2.addTextComponent( " " ); + + FancyMessage msgBlocks = new FancyMessage( String.format( " &bBlocks: &3[&7%s&3]", + prisonBlocks ) ) + .command("/mines blockEvent blocks " + m.getName() ) + .tooltip("Event Blocks - Click to Edit"); + row2.addFancy( msgBlocks ); + + builder.add( row2 ); } } @@ -3913,7 +3629,7 @@ public void blockEventRemove(CommandSender sender, display.send(sender); - return; + return; } @@ -3923,11 +3639,11 @@ public void blockEventRemove(CommandSender sender, } if ( row > m.getBlockEvents().size() ) { - sender.sendMessage( - String.format("&7Please provide a valid row number no greater than &b%d&7. " + - "Was row=[&b%d&7]", - m.getBlockEvents().size(), (row == null ? "null" : row) )); - return; + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was row=[&b%d&7]", + m.getBlockEvents().size(), (row == null ? "null" : row) )); + return; } MineBlockEvent blockEvent = m.getBlockEvents().get( row - 1 ); @@ -3935,14 +3651,14 @@ public void blockEventRemove(CommandSender sender, if ( blockEvent != null && m.getBlockEventsRemove( blockEvent ) ) { - pMines.getMineManager().saveMine( m ); - - Output.get().sendInfo(sender, "Removed BlockEvent command '%s' from the mine '%s'.", - blockEvent.getCommand(), m.getTag()); + pMines.getMineManager().saveMine( m ); + + Output.get().sendInfo(sender, "Removed BlockEvent command '%s' from the mine '%s'.", + blockEvent.getCommand(), m.getTag()); } else { - Output.get().sendWarn(sender, - String.format("The mine %s doesn't contain that BlockEvent command. Nothing was changed.", - m.getTag())); + Output.get().sendWarn(sender, + String.format("The mine %s doesn't contain that BlockEvent command. Nothing was changed.", + m.getTag())); } // Redisplay the event list: @@ -4063,19 +3779,6 @@ public void blockEventAdd(CommandSender sender, "you can use with blockEvents") String mineName, @Arg(name = "percent", def = "100.0", description = "Percent chance between 0.0000 and 100.0") Double chance, -// @Arg(name = "permission", def = "none", -// description = "Optional permission that the player must have, or [none] for no perm." -// ) String perm, -// @Arg(name = "eventType", def = "eventTypeAll", -// description = "EventType to trigger BlockEvent: [eventTypeAll, eventBlockBreak, eventTEXplosion]" -// ) String eventType, -// @Arg(name = "triggered", def = "none", -// description = "TE Explosion Triggered sources. Requires TokenEnchant v18.11.0 or newer. [none, ...]" -// ) String triggered, -// @Arg(name = "taskMode", description = "Processing task mode to run the task as console. " + -// "Player runs as player. " + -// "[inline, inlinePlayer, sync, syncPlayer]", -// def = "inline") String mode, @Arg(name = "command") @Wildcard String command) { // Note: async is not an option since the bukkit dispatchCommand will run it as sync. @@ -4083,25 +3786,25 @@ public void blockEventAdd(CommandSender sender, if ( mineName != null && "placeholders".equalsIgnoreCase( mineName ) ) { - String placeholders = - - PrisonCommandTaskData.CustomPlaceholders.listPlaceholders( - PrisonCommandTaskData.CommandEnvironment.all_commands ) + " " + - - PrisonCommandTaskData.CustomPlaceholders.listPlaceholders( - PrisonCommandTaskData.CommandEnvironment.blockevent_commands ); - - String message = String.format( "Valid Placeholders that can be used with blockEvents: [%s]", - placeholders ); - - sender.sendMessage( message ); - return; + String placeholders = + + PrisonCommandTaskData.BlockEventCustomPlaceholders.listPlaceholders( + PrisonCommandTaskData.CommandEnvironment.all_commands ) + " " + + + PrisonCommandTaskData.BlockEventCustomPlaceholders.listPlaceholders( + PrisonCommandTaskData.CommandEnvironment.blockevent_commands ); + + String message = String.format( "Valid Placeholders that can be used with blockEvents: [%s]", + placeholders ); + + sender.sendMessage( message ); + return; } String perm = "none"; String mode = "sync"; // "inline"; - if (command.startsWith("/")) { + if (command.startsWith("/")) { command = command.replaceFirst("/", ""); } @@ -4112,103 +3815,72 @@ public void blockEventAdd(CommandSender sender, } if ( chance <= 0d || chance > 100.0d ) { - sender.sendMessage( - String.format("&7Please provide a valid value for chance " + - "between 0.0000 and 100.0. Was state=[&b%d&7]", - chance )); - return; + sender.sendMessage( + String.format("&7Please provide a valid value for chance " + + "between 0.0000 and 100.0. Was state=[&b%d&7]", + chance )); + return; } TaskMode taskMode = TaskMode.fromString( mode ); if ( mode == null || !taskMode.name().equalsIgnoreCase( mode ) ) { - sender.sendMessage( - String.format("&7Task mode is defaulting to %s. " + - "[inline, inlinePlayer, sync, syncPlayer] mode=[&b%s&7]", - taskMode.name(), mode )); - return; + sender.sendMessage( + String.format("&7Task mode is defaulting to %s. " + + "[inline, inlinePlayer, sync, syncPlayer] mode=[&b%s&7]", + taskMode.name(), mode )); + return; } if ( perm == null || perm.trim().length() == 0 || "none".equalsIgnoreCase( perm ) ) { - perm = ""; + perm = ""; } - -// BlockEventType eType = BlockEventType.fromString( eventType ); -// if ( !eType.name().equalsIgnoreCase( eventType ) ) { -// sender.sendMessage( -// String.format("&7Notice: The supplied eventType does not match the list of valid " + -// "BlockEventTypes therefore defaulting to eventTypeAll. Valid eventTypes are: " + -// "[eventTypeAll, eventBlockBreak, eventTEXplosion]", -// eventType )); -// } - -// if ( eType != BlockEventType.eventTEXplosion && triggered != null && !"none".equalsIgnoreCase( triggered ) ) { -// sender.sendMessage( "&7Notice: triggered is only valid exclusivly for eventTEXplosion. " + -// "Defaulting to none." ); -// triggered = null; -// } -// if ( triggered != null && "none".equalsIgnoreCase( triggered ) ) { -// triggered = null; -// } if ( command == null || command.trim().length() == 0 ) { - sender.sendMessage( - String.format( "&7Please provide a valid BlockEvent command: command=[%s]", command) ); - return; + sender.sendMessage( + String.format( "&7Please provide a valid BlockEvent command: command=[%s]", command) ); + return; } PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); List mines = new ArrayList<>(); if ( "*all*".equalsIgnoreCase( mineName ) ) { - mines.addAll( pMines.getMines() ); + mines.addAll( pMines.getMines() ); } else { - setLastMineReferenced(mineName); - - Mine m = pMines.getMine(mineName); - mines.add( m ); + setLastMineReferenced(mineName); + + Mine m = pMines.getMine(mineName); + mines.add( m ); } for ( Mine m : mines ) { - MineBlockEvent blockEvent = new MineBlockEvent( chance, perm, command, taskMode ); - m.getBlockEvents().add( blockEvent ); - - pMines.getMineManager().saveMine( m ); - - Output.get().sendInfo(sender, "&7Added BlockEvent command '&b%s&7' " + - "&7to the mine '&b%s&7' with " + - "the optional permission %s. Using the mode %s.", - command, m.getTag(), - perm == null || perm.trim().length() == 0 ? "&3none&7" : "'&3" + perm + "&7'", - mode ); - -// String.format("&7Notice: &3The default eventType has been set to &7all&3. If you need " + -// "to change it to something else, then use the command &7/mines blockEvent eventType help&3. " + -// "[all, blockBreak, TEXplosion] The event type is what causes the block to break. " + -// "Token Enchant's Explosion events are covered and can be focused with the " + -// "triggered parameter." ); - - -// if ( eType == BlockEventType.eventTEXplosion ) { -// sender.sendMessage( "&7Notice: &3Since the event type is for TokenEnchant's eventTEXplosion, " + -// "then you may set the value of &7triggered&7 with the command " + -// "&7/mines blockEvent triggered help&3." ); -// } + MineBlockEvent blockEvent = new MineBlockEvent( chance, perm, command, taskMode ); + m.getBlockEvents().add( blockEvent ); + + pMines.getMineManager().saveMine( m ); + + Output.get().sendInfo(sender, "&7Added BlockEvent command '&b%s&7' " + + "&7to the mine '&b%s&7' with " + + "the optional permission %s. Using the mode %s.", + command, m.getTag(), + perm == null || perm.trim().length() == 0 ? "&3none&7" : "'&3" + perm + "&7'", + mode ); + } if ( !"*all*".equalsIgnoreCase( mineName ) ) { - // Redisplay the event list: - blockEventList( sender, mineName ); + // Redisplay the event list: + blockEventList( sender, mineName ); } } @@ -4231,7 +3903,6 @@ public void blockEventPercent(CommandSender sender, setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); @@ -4254,15 +3925,15 @@ public void blockEventPercent(CommandSender sender, // try to "suggest" reading this command: // mines blockEvent percent [row] [percent] - FancyMessage msgAddBlock = new FancyMessage( String.format( - "&7%s [row] [percent]", - commandRoot ) ) - .suggest( commandRoot + " [row] [percent]" ) - .tooltip("Change the percent for the blockEvent - Click to change"); - - RowComponent rowFancy = new RowComponent(); - rowFancy.addFancy( msgAddBlock ); - display.addComponent( rowFancy ); + FancyMessage msgAddBlock = new FancyMessage( String.format( + "&7%s [row] [percent]", + commandRoot ) ) + .suggest( commandRoot + " [row] [percent]" ) + .tooltip("Change the percent for the blockEvent - Click to change"); + + RowComponent rowFancy = new RowComponent(); + rowFancy.addFancy( msgAddBlock ); + display.addComponent( rowFancy ); display.send(sender); @@ -4271,19 +3942,19 @@ public void blockEventPercent(CommandSender sender, } if ( chance <= 0d || chance > 100.0d ) { - sender.sendMessage( - String.format("&7Please provide a valid value for chance " + - "between 0.0000 and 100.0. Was state=[&b%d&7]", - chance )); - return; + sender.sendMessage( + String.format("&7Please provide a valid value for chance " + + "between 0.0000 and 100.0. Was state=[&b%d&7]", + chance )); + return; } if ( row > m.getBlockEvents().size() ) { - sender.sendMessage( - String.format("&7Please provide a valid row number no greater than &b%d&7. " + - "Was row=[&b%d&7]", - m.getBlockEvents().size(), (row == null ? "null" : row) )); - return; + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was row=[&b%d&7]", + m.getBlockEvents().size(), (row == null ? "null" : row) )); + return; } MineBlockEvent blockEvent = m.getBlockEvents().get( row - 1 ); @@ -4326,7 +3997,6 @@ public void blockEventPermission(CommandSender sender, setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); @@ -4351,34 +4021,34 @@ public void blockEventPermission(CommandSender sender, // try to "suggest" reading this command: // mines blockEvent permission [row] [permission] - FancyMessage msgAddBlock = new FancyMessage( String.format( - "&7%s [row] [permission]", - commandRoot ) ) - .suggest( commandRoot + " [row] [permission]" ) - .tooltip("Change the permission for the blockEvent - Click to change"); - - RowComponent rowFancy = new RowComponent(); - rowFancy.addFancy( msgAddBlock ); - display.addComponent( rowFancy ); - - + FancyMessage msgAddBlock = new FancyMessage( String.format( + "&7%s [row] [permission]", + commandRoot ) ) + .suggest( commandRoot + " [row] [permission]" ) + .tooltip("Change the permission for the blockEvent - Click to change"); + + RowComponent rowFancy = new RowComponent(); + rowFancy.addFancy( msgAddBlock ); + display.addComponent( rowFancy ); + + display.send(sender); - return; + return; } if ( perm == null || perm.trim().length() == 0 || "none".equalsIgnoreCase( perm ) ) { - perm = ""; + perm = ""; } if ( row > m.getBlockEvents().size() ) { - sender.sendMessage( - String.format("&7Please provide a valid row number no greater than &b%d&7. " + - "Was row=[&b%d&7]", - m.getBlockEvents().size(), (row == null ? "null" : row) )); - return; + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was row=[&b%d&7]", + m.getBlockEvents().size(), (row == null ? "null" : row) )); + return; } MineBlockEvent blockEvent = m.getBlockEvents().get( row - 1 ); @@ -4428,7 +4098,6 @@ public void blockEventEventType(CommandSender sender, setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); @@ -4450,39 +4119,38 @@ public void blockEventEventType(CommandSender sender, // try to "suggest" reading this command: // mines blockEvent eventType [row] [eventType] - FancyMessage msgAddBlock = new FancyMessage( String.format( - "&7%s [row] [eventType]", - commandRoot ) ) - .suggest( commandRoot + " [row] [eventType]" ) - .tooltip("Change the eventtype for the blockEvent - Click to change"); - - RowComponent rowFancy = new RowComponent(); - rowFancy.addFancy( msgAddBlock ); - display.addComponent( rowFancy ); - - + FancyMessage msgAddBlock = new FancyMessage( String.format( + "&7%s [row] [eventType]", + commandRoot ) ) + .suggest( commandRoot + " [row] [eventType]" ) + .tooltip("Change the eventtype for the blockEvent - Click to change"); + + RowComponent rowFancy = new RowComponent(); + rowFancy.addFancy( msgAddBlock ); + display.addComponent( rowFancy ); + display.send(sender); - return; + return; } BlockEventType eType = BlockEventType.fromString( eventType ); if ( !eType.name().equalsIgnoreCase( eventType ) ) { - sender.sendMessage( - String.format("&7Notice: The supplied eventType does not match the list of valid " + - "BlockEventTypes therefore defaulting to eventTypeAll. Valid eventTypes are: " + - "[%s]", - eventType, BlockEventType.getPrimaryEventTypes() )); + sender.sendMessage( + String.format("&7Notice: The supplied eventType does not match the list of valid " + + "BlockEventTypes therefore defaulting to eventTypeAll. Valid eventTypes are: " + + "[%s]", + eventType, BlockEventType.getPrimaryEventTypes() )); } if ( row > m.getBlockEvents().size() ) { - sender.sendMessage( - String.format("&7Please provide a valid row number no greater than &b%d&7. " + - "Was row=[&b%d&7]", - m.getBlockEvents().size(), (row == null ? "null" : row) )); - return; + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was row=[&b%d&7]", + m.getBlockEvents().size(), (row == null ? "null" : row) )); + return; } MineBlockEvent blockEvent = m.getBlockEvents().get( row - 1 ); @@ -4496,7 +4164,7 @@ public void blockEventEventType(CommandSender sender, eType != BlockEventType.TEXplosion && eType != BlockEventType.PEExplosive ) { - blockEvent.setTriggered( null ); + blockEvent.setTriggered( null ); } pMines.getMineManager().saveMine( m ); @@ -4507,9 +4175,9 @@ public void blockEventEventType(CommandSender sender, eType.name(), m.getTag(), eTypeOld.name(), blockEvent.getCommand() ); if ( eType == BlockEventType.TEXplosion ) { - sender.sendMessage( "&7Notice: &3Since the event type is for TokenEnchant's eventTEXplosion, " + - "then you may set the value of &7triggered&7 with the command " + - "&7/mines blockEvent triggered help&3." ); + sender.sendMessage( "&7Notice: &3Since the event type is for TokenEnchant's eventTEXplosion, " + + "then you may set the value of &7triggered&7 with the command " + + "&7/mines blockEvent triggered help&3." ); } // Redisplay the event list: @@ -4544,7 +4212,6 @@ public void blockEventTriggered(CommandSender sender, setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); @@ -4567,18 +4234,17 @@ public void blockEventTriggered(CommandSender sender, // try to "suggest" reading this command: // mines blockEvent triggered [row] [triggered] - FancyMessage msgAddBlock = new FancyMessage( String.format( - "&7%s [row] [triggered]", - commandRoot ) ) - .suggest( commandRoot + " [row] [triggered]" ) - .tooltip("Change the triggered source for the blockEvent - Click to change"); - - RowComponent rowFancy = new RowComponent(); - rowFancy.addFancy( msgAddBlock ); - display.addComponent( rowFancy ); + FancyMessage msgAddBlock = new FancyMessage( String.format( + "&7%s [row] [triggered]", + commandRoot ) ) + .suggest( commandRoot + " [row] [triggered]" ) + .tooltip("Change the triggered source for the blockEvent - Click to change"); + + RowComponent rowFancy = new RowComponent(); + rowFancy.addFancy( msgAddBlock ); + display.addComponent( rowFancy ); - display.send(sender); return; @@ -4603,11 +4269,12 @@ public void blockEventTriggered(CommandSender sender, triggered != null && !"none".equalsIgnoreCase( triggered ) ) { - sender.sendMessage( "&7Notice: triggered is only valid with " + - "PrisonExplosion, TEXplosion, or PEExplosive. " + - "Defaulting to 'none'." ); - triggered = null; + sender.sendMessage( "&7Notice: triggered is only valid with " + + "PrisonExplosion, TEXplosion, or PEExplosive. " + + "Defaulting to 'none'." ); + triggered = null; } + if ( triggered != null && "none".equalsIgnoreCase( triggered ) ) { triggered = null; } @@ -4659,7 +4326,6 @@ public void blockEventJobMode(CommandSender sender, setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); @@ -4682,48 +4348,40 @@ public void blockEventJobMode(CommandSender sender, // try to "suggest" reading this command: // mines blockEvent taskMode [row] [taskMode] - FancyMessage msgAddBlock = new FancyMessage( String.format( - "&7%s [row] [taskMode]", - commandRoot ) ) - .suggest( commandRoot + " [row] [taskMode]" ) - .tooltip("Change the taskMode for the blockEvent - Click to change"); - - RowComponent rowFancy = new RowComponent(); - rowFancy.addFancy( msgAddBlock ); - display.addComponent( rowFancy ); + FancyMessage msgAddBlock = new FancyMessage( String.format( + "&7%s [row] [taskMode]", + commandRoot ) ) + .suggest( commandRoot + " [row] [taskMode]" ) + .tooltip("Change the taskMode for the blockEvent - Click to change"); + + RowComponent rowFancy = new RowComponent(); + rowFancy.addFancy( msgAddBlock ); + display.addComponent( rowFancy ); display.send(sender); - return; + return; } TaskMode taskMode = TaskMode.fromString( mode ); if ( mode == null || !taskMode.name().equalsIgnoreCase( mode ) ) { - sender.sendMessage( - String.format("&7Task mode is defaulting to %s. " + - "[inline, inlinePlayer, sync, syncPlayer] mode=[&b%s&7]", - taskMode.name(), mode )); - return; + sender.sendMessage( + String.format("&7Task mode is defaulting to %s. " + + "[inline, inlinePlayer, sync, syncPlayer] mode=[&b%s&7]", + taskMode.name(), mode )); + return; } -// if ( mode == null || !"sync".equalsIgnoreCase( mode ) && !"inline".equalsIgnoreCase( mode ) ) { -// sender.sendMessage( -// String.format("&7Please provide a valid mode for running the commands. " + -// "[inline, sync] mode=[&b%s&7]", -// mode )); -// return; -// } - if ( row > m.getBlockEvents().size() ) { - sender.sendMessage( - String.format("&7Please provide a valid row number no greater than &b%d&7. " + - "Was row=[&b%d&7]", - m.getBlockEvents().size(), (row == null ? "null" : row) )); - return; + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was row=[&b%d&7]", + m.getBlockEvents().size(), (row == null ? "null" : row) )); + return; } MineBlockEvent blockEvent = m.getBlockEvents().get( row - 1 ); @@ -4761,11 +4419,6 @@ public void blockEventBlockAdd(CommandSender sender, "this command will display a list of all current blockEvents for " + "this mine.") Integer rowBlockEvent, - // search is no longer needed nor is the wildcard join for blockName: -// @Arg(name = "search", description = "Optional keyword 'search' to search " + -// "based upon value of blockName. [search, none, ]", -// def = "") String search, -// @Wildcard(join=true) @Arg(name = "rowBlockName", description = "Row number of the block to add, or " + "if ommitted, then it will show a list of all of the blocks that " + "are available within the selected mine.", @@ -4779,7 +4432,6 @@ public void blockEventBlockAdd(CommandSender sender, setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); @@ -4800,28 +4452,28 @@ public void blockEventBlockAdd(CommandSender sender, // try to "suggest" reading this command: // mines blockEvent block add [row] [search} [block] - FancyMessage msgAddBlock = new FancyMessage( String.format( - "&7%s [rowBlockEvent] [rowBlockName]", - commandRoot ) ) - .suggest( commandRoot + " [rowBlockEvent] [rowBlockName]" ) - .tooltip("Add block to blockEvent - Click to Add"); - - RowComponent rowFancy = new RowComponent(); - rowFancy.addFancy( msgAddBlock ); - display.addComponent( rowFancy ); + FancyMessage msgAddBlock = new FancyMessage( String.format( + "&7%s [rowBlockEvent] [rowBlockName]", + commandRoot ) ) + .suggest( commandRoot + " [rowBlockEvent] [rowBlockName]" ) + .tooltip("Add block to blockEvent - Click to Add"); + + RowComponent rowFancy = new RowComponent(); + rowFancy.addFancy( msgAddBlock ); + display.addComponent( rowFancy ); display.send( sender ); - return; + return; } if ( rowBlockEvent > m.getBlockEvents().size() ) { - sender.sendMessage( - String.format("&7Please provide a valid row number no greater than &b%d&7. " + - "Was rowBlockEvent=[&b%d&7]", - m.getBlockEvents().size(), (rowBlockEvent == null ? "null" : rowBlockEvent) )); - return; + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was rowBlockEvent=[&b%d&7]", + m.getBlockEvents().size(), (rowBlockEvent == null ? "null" : rowBlockEvent) )); + return; } @@ -4830,74 +4482,70 @@ public void blockEventBlockAdd(CommandSender sender, if ( blockEvent != null ) { - if ( rowBlockName == null || rowBlockName == 0 || - rowBlockName > m.getPrisonBlocks().size() ) { - - String commandBlockEvent = String.format( "" + - "%s %d ", commandRoot, rowBlockEvent ); - - ChatDisplay display = new ChatDisplay("Add blocks to a BlockEvent for " + m.getTag() ); - display.addText("&8Select a block from this mine by using the block's row number:"); - display.addText("&8 " + commandBlockEvent + " [rowBlockName]"); - - DecimalFormat dFmt = Prison.get().getDecimalFormat("0.00000"); - - // Display a list of blocks for the mine: - int blockRow = 0; - - for ( PrisonBlock block : m.getPrisonBlocks() ) - { - - RowComponent rowB = new RowComponent(); - - rowB.addTextComponent( " &3Row: &d%d ", ++blockRow ); - - String message = String.format( "&7%s %s", - block.getBlockName(), dFmt.format( block.getChance() ) ); - - String command = String.format( "%s %d", commandBlockEvent, blockRow ); - - FancyMessage msgAddBlock = new FancyMessage( message ) - .suggest( command ) - .tooltip("Add selected block to blockEvent - Click to Add"); - - rowB.addFancy( msgAddBlock ); - - display.addComponent( rowB ); - } - - - display.send( sender ); - return; - } - - - // Old block model is not supported with blockEvent block filers: - PrisonBlock block = m.getPrisonBlocks().get( rowBlockName - 1 ); - - if ( block != null ) { - - blockEvent.addPrisonBlock( block ); - - pMines.getMineManager().saveMine( m ); - - sender.sendMessage( "Block has been added to BlockEvent" ); - - return; - } - -// PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); -// PrisonBlock block = prisonBlockTypes.getBlockTypesByName( blockName ); - + if ( rowBlockName == null || rowBlockName == 0 || + rowBlockName > m.getPrisonBlocks().size() ) { + + String commandBlockEvent = String.format( "" + + "%s %d ", commandRoot, rowBlockEvent ); + + ChatDisplay display = new ChatDisplay("Add blocks to a BlockEvent for " + m.getTag() ); + display.addText("&8Select a block from this mine by using the block's row number:"); + display.addText("&8 " + commandBlockEvent + " [rowBlockName]"); + + DecimalFormat dFmt = Prison.get().getDecimalFormat("0.00000"); + + // Display a list of blocks for the mine: + int blockRow = 0; + + for ( PrisonBlock block : m.getPrisonBlocks() ) + { + + RowComponent rowB = new RowComponent(); + + rowB.addTextComponent( " &3Row: &d%d ", ++blockRow ); + + String message = String.format( "&7%s %s", + block.getBlockName(), dFmt.format( block.getChance() ) ); + + String command = String.format( "%s %d", commandBlockEvent, blockRow ); + + FancyMessage msgAddBlock = new FancyMessage( message ) + .suggest( command ) + .tooltip("Add selected block to blockEvent - Click to Add"); + + rowB.addFancy( msgAddBlock ); + + display.addComponent( rowB ); + } + + + display.send( sender ); + return; + } + + + // Old block model is not supported with blockEvent block filers: + PrisonBlock block = m.getPrisonBlocks().get( rowBlockName - 1 ); + + if ( block != null ) { + + blockEvent.addPrisonBlock( block ); + + pMines.getMineManager().saveMine( m ); + + sender.sendMessage( "Block has been added to BlockEvent" ); + + return; + } + + } else { - sender.sendMessage( "BlockEvent was not found" ); - // BlockEvent not found. Recheck the blockEven row number. + sender.sendMessage( "BlockEvent was not found" ); + // BlockEvent not found. Recheck the blockEven row number. } - // Redisplay the event list: - // blockEventList( sender, mineName ); sender.sendMessage( "BlockEvent was not completed correctly" ); } @@ -4918,12 +4566,6 @@ public void blockEventBlockRemove(CommandSender sender, "add the block filter to. If not provided, or value of 0, then " + "this command will display a list of all current blockEvents for " + "this mine.") Integer rowBlockEvent, - - // search is no longer needed nor is the wildcard join for blockName: -// @Arg(name = "search", description = "Optional keyword 'search' to search " + -// "based upon value of blockName. [search, none, ]", -// def = "") String search, -// @Wildcard(join=true) @Arg(name = "rowBlockName", description = "Name of block to add, or " + "if ommitted, then it will show a list of all of the blocks that " + "are available within the selected mine.", @@ -4938,7 +4580,6 @@ public void blockEventBlockRemove(CommandSender sender, PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); @@ -4961,28 +4602,28 @@ public void blockEventBlockRemove(CommandSender sender, // try to "suggest" reading this command: // mines blockEvent block add [row] [search} [block] - FancyMessage msgRemoveBlock = new FancyMessage( String.format( - "&7%s [rowBlockEvent] [rowBlockName]", - commandRoot ) ) - .suggest( commandRoot + " [rowBlockEvent] [rowBlockName]" ) - .tooltip("Remove a block from a blockEvent - Click to Remove"); - - RowComponent rowFancy = new RowComponent(); - rowFancy.addFancy( msgRemoveBlock ); - display.addComponent( rowFancy ); + FancyMessage msgRemoveBlock = new FancyMessage( String.format( + "&7%s [rowBlockEvent] [rowBlockName]", + commandRoot ) ) + .suggest( commandRoot + " [rowBlockEvent] [rowBlockName]" ) + .tooltip("Remove a block from a blockEvent - Click to Remove"); + + RowComponent rowFancy = new RowComponent(); + rowFancy.addFancy( msgRemoveBlock ); + display.addComponent( rowFancy ); display.send( sender ); - return; + return; } if ( rowBlockEvent > m.getBlockEvents().size() ) { - sender.sendMessage( - String.format("&7Please provide a valid row number no greater than &b%d&7. " + - "Was rowBlockEvent=[&b%d&7]", - m.getBlockEvents().size(), (rowBlockEvent == null ? "null" : rowBlockEvent) )); - return; + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was rowBlockEvent=[&b%d&7]", + m.getBlockEvents().size(), (rowBlockEvent == null ? "null" : rowBlockEvent) )); + return; } @@ -4992,115 +4633,70 @@ public void blockEventBlockRemove(CommandSender sender, if ( blockEvent != null ) { - if ( rowBlockName == null || rowBlockName == 0 || - rowBlockName > m.getBlockEvents().size() ) { - - String commandBlockEvent = String.format( "" + - "%s %d ", commandRoot, rowBlockEvent ); - - ChatDisplay display = new ChatDisplay("Remove a block from a BlockEvent for " + m.getTag() ); - display.addText("&8Select a block filter from this mine by using the block's row number:"); - display.addText("&8 " + commandBlockEvent + " [rowBlockName]"); - -// DecimalFormat dFmt = Prison.get().getDecimalFormat("0.00000"); - - // Display a list of blocks for the mine: - int blockRow = 0; - - - for ( PrisonBlock block : blockEvent.getPrisonBlocks() ) - { - - RowComponent rowB = new RowComponent(); - - rowB.addTextComponent( " &3Row: &d%d ", ++blockRow ); - - String message = String.format( "&7%s", - block.getBlockName() ); -// String message = String.format( "&7%s %s", -// block.getBlockName(), dFmt.format( block.getChance() ) ); - - String command = String.format( "%s %d", commandBlockEvent, blockRow ); - - FancyMessage msgAddBlock = new FancyMessage( message ) - .suggest( command ) - .tooltip("Remove a selected block from a blockEvent - Click to Remove"); - - rowB.addFancy( msgAddBlock ); - - display.addComponent( rowB ); - } - - display.send( sender ); - return; - } - - - if ( blockEvent.removePrisonBlock( rowBlockName ) ) { - - pMines.getMineManager().saveMine( m ); - - sender.sendMessage( "Block has been removed from the BlockEvent" ); - - return; - } + if ( rowBlockName == null || rowBlockName == 0 || + rowBlockName > m.getBlockEvents().size() ) { + + String commandBlockEvent = String.format( "" + + "%s %d ", commandRoot, rowBlockEvent ); + + ChatDisplay display = new ChatDisplay("Remove a block from a BlockEvent for " + m.getTag() ); + display.addText("&8Select a block filter from this mine by using the block's row number:"); + display.addText("&8 " + commandBlockEvent + " [rowBlockName]"); + + + // Display a list of blocks for the mine: + int blockRow = 0; + + + for ( PrisonBlock block : blockEvent.getPrisonBlocks() ) + { + + RowComponent rowB = new RowComponent(); + + rowB.addTextComponent( " &3Row: &d%d ", ++blockRow ); + + String message = String.format( "&7%s", + block.getBlockName() ); + + String command = String.format( "%s %d", commandBlockEvent, blockRow ); + + FancyMessage msgAddBlock = new FancyMessage( message ) + .suggest( command ) + .tooltip("Remove a selected block from a blockEvent - Click to Remove"); + + rowB.addFancy( msgAddBlock ); + + display.addComponent( rowB ); + } + + display.send( sender ); + return; + } + + + if ( blockEvent.removePrisonBlock( rowBlockName ) ) { + + pMines.getMineManager().saveMine( m ); + + sender.sendMessage( "Block has been removed from the BlockEvent" ); + + return; + } -// PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); -// PrisonBlock block = prisonBlockTypes.getBlockTypesByName( blockName ); - } else { - sender.sendMessage( "BlockEvent was not found" ); - // BlockEvent not found. Recheck the blockEven row number. - - return; + sender.sendMessage( "BlockEvent was not found" ); + // BlockEvent not found. Recheck the blockEven row number. + + return; } - - // Redisplay the event list: - // blockEventList( sender, mineName ); - sender.sendMessage( "BlockEvent was not completed correctly" ); } -// private String extractSearchValue( String page, String blockName ) { -// String results = blockName; -// if ( blockName.toLowerCase().startsWith( page.toLowerCase() ) ) { -// results = blockName.substring( page.length() ).trim(); -// } -// -// return results; -// } - -// private String extractPage( String blockName ) { -// String page = "1"; -// -// if ( blockName != null && blockName.toLowerCase().startsWith( "all " ) ) { -// page = "all"; -// } -// else if ( blockName!= null && blockName.contains( " " ) ) { -// -// try { -// String pageStr = blockName.substring( 0, blockName.indexOf( " " ) ); -// -// int pg = Integer.parseInt( pageStr ); -// -// page = Integer.toString( pg ); -// } -// catch ( NumberFormatException e ) { -// } -// } -// -// return page; -// } - - - - - @Command(identifier = "mines command list", description = "Lists the commands for a mine.", @@ -5108,10 +4704,6 @@ public void blockEventBlockRemove(CommandSender sender, public void commandList(CommandSender sender, @Arg(name = "mineName") String mineName) { -// if ( 1 < 2 ) { -// sender.sendMessage( "&cThis command is disabled&7. It will be enabled in the near future." ); -// return; -// } if (!performCheckMineExists(sender, mineName)) { return; @@ -5121,7 +4713,6 @@ public void commandList(CommandSender sender, setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); if (m.getResetCommands() == null || m.getResetCommands().size() == 0) { @@ -5135,40 +4726,40 @@ public void commandList(CommandSender sender, display.send(sender); } -private ChatDisplay minesCommandList( Mine m ) -{ - ChatDisplay display = new ChatDisplay("ResetCommand for " + m.getName()); - display.addText("&8Click a command to remove it."); - BulletedListComponent.BulletedListBuilder builder = - new BulletedListComponent.BulletedListBuilder(); - - int rowNumber = 1; - for (String command : m.getResetCommands()) { - - - RowComponent row = new RowComponent(); - - row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); - - FancyMessage msg = new FancyMessage( "&a'&7" + command + "&a'" ); - row.addFancy( msg ); - - FancyMessage msgRemove = new FancyMessage( " &4Remove&3" ) - .suggest("/mines command remove " + m.getName() + " " + rowNumber ) - .tooltip("Click to Remove this Mine Command"); - row.addFancy( msgRemove ); - - builder.add( row ); - + private ChatDisplay minesCommandList( Mine m ) + { + ChatDisplay display = new ChatDisplay("Mine Reset Commands for Mine " + m.getTag()); + display.addText("&8Click a command to remove it."); + BulletedListComponent.BulletedListBuilder builder = + new BulletedListComponent.BulletedListBuilder(); + + int rowNumber = 1; + for (String command : m.getResetCommands()) { + + + RowComponent row = new RowComponent(); + + row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); + + FancyMessage msg = new FancyMessage( "&a'&7" + command + "&a'" ); + row.addFancy( msg ); + + FancyMessage msgRemove = new FancyMessage( " &4Remove&3" ) + .suggest("/mines command remove " + m.getName() + " " + rowNumber ) + .tooltip("Click to Remove this Mine Command"); + row.addFancy( msgRemove ); + + builder.add( row ); + + } + + display.addComponent(builder.build()); + display.addComponent(new FancyMessageComponent( + new FancyMessage("&7[&a+&7] Add").suggest("/mines command add " + m.getName() + " /") + .tooltip("&7Add a new command."))); + return display; } - - display.addComponent(builder.build()); - display.addComponent(new FancyMessageComponent( - new FancyMessage("&7[&a+&7] Add").suggest("/mines command add " + m.getName() + " /") - .tooltip("&7Add a new command."))); - return display; -} - + @Command(identifier = "mines command remove", description = "Removes a command from a mine.", onlyPlayers = false, permissions = "mines.set") @@ -5180,11 +4771,11 @@ public void commandRemove(CommandSender sender, if ( row == null || row <= 0 ) { - sender.sendMessage( - String.format("&7Please provide a valid row number greater than zero. " + - "Was row=[&b%d&7]", - (row == null ? "null" : row) )); - return; + sender.sendMessage( + String.format("&7Please provide a valid row number greater than zero. " + + "Was row=[&b%d&7]", + (row == null ? "null" : row) )); + return; } if (!performCheckMineExists(sender, mineName)) { @@ -5194,14 +4785,8 @@ public void commandRemove(CommandSender sender, setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); -// if ( !m.isEnabled() ) { -// sender.sendMessage( "&cMine is disabled&7. Use &a/mines info &7for possible cause." ); -// return; -// } - if (m.getResetCommands() == null || m.getResetCommands().size() == 0) { Output.get().sendInfo(sender, "The mine '%s' contains no commands.", m.getTag()); return; @@ -5209,15 +4794,15 @@ public void commandRemove(CommandSender sender, if (m.getResetCommands() == null) { - m.setResetCommands( new ArrayList<>() ); + m.setResetCommands( new ArrayList<>() ); } if ( row > m.getResetCommands().size() ) { - sender.sendMessage( - String.format("&7Please provide a valid row number no greater than &b%d&7. " + - "Was row=[&b%d&7]", - m.getResetCommands().size(), (row == null ? "null" : row) )); - return; + sender.sendMessage( + String.format("&7Please provide a valid row number no greater than &b%d&7. " + + "Was row=[&b%d&7]", + m.getResetCommands().size(), (row == null ? "null" : row) )); + return; } @@ -5248,22 +4833,22 @@ public void commandAdd(CommandSender sender, if ( mineName != null && "placeholders".equalsIgnoreCase( mineName ) ) { - String placeholders = - - PrisonCommandTaskData.CustomPlaceholders.listPlaceholders( - PrisonCommandTaskData.CommandEnvironment.all_commands ) + " " + - - PrisonCommandTaskData.CustomPlaceholders.listPlaceholders( - PrisonCommandTaskData.CommandEnvironment.mine_commands ); - - String message = String.format( "Valid Placeholders that can be used with mine commands: [%s]", - placeholders ); - - sender.sendMessage( message ); - return; + String placeholders = + + PrisonCommandTaskData.BlockEventCustomPlaceholders.listPlaceholders( + PrisonCommandTaskData.CommandEnvironment.all_commands ) + " " + + + PrisonCommandTaskData.BlockEventCustomPlaceholders.listPlaceholders( + PrisonCommandTaskData.CommandEnvironment.mine_commands ); + + String message = String.format( "Valid Placeholders that can be used with mine commands: [%s]", + placeholders ); + + sender.sendMessage( message ); + return; } - if (command.startsWith("/")) { + if (command.startsWith("/")) { command = command.replaceFirst("/", ""); } @@ -5272,22 +4857,21 @@ public void commandAdd(CommandSender sender, } if ( state == null || !state.equalsIgnoreCase( "before" ) && !state.equalsIgnoreCase( "after" )) { - sender.sendMessage( - String.format("&7Please provide a valid state: &bbefore&7 or &bafter&7. Was state=[&b%s&7]", - state )); - return; + sender.sendMessage( + String.format("&7Please provide a valid state: &bbefore&7 or &bafter&7. Was state=[&b%s&7]", + state )); + return; } setLastMineReferenced(mineName); PrisonMines pMines = PrisonMines.getInstance(); -// MineManager mMan = pMines.getMineManager(); Mine m = pMines.getMine(mineName); if ( command == null || command.trim().length() == 0 ) { - sender.sendMessage( - String.format( "&7Please provide a valid command: command=[%s]", command) ); - return; + sender.sendMessage( + String.format( "&7Please provide a valid command: command=[%s]", command) ); + return; } String newComand = state + ": " + command; @@ -5301,4 +4885,571 @@ public void commandAdd(CommandSender sender, } + + @Command(identifier = "mines worldguard region mineInfo", + description = "WorldGuard Regions: shows a mine region info.", + onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsMineInfo(CommandSender sender, + @Arg(name = "mineName", description = "mine name") String mineName, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console. " + ) @Wildcard String options) { + + String cmd = "mineInfo"; + + String wgSetting = "prison-mines.world-guard.mine-region-commands.info"; + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + + } + + @Command(identifier = "mines worldguard region mineDefine", + description = "WorldGuard Regions: define a mine region based upon the mine's size.", + onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsMineDefine(CommandSender sender, + @Arg(name = "mineName", description = "mine name") String mineName, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console. " + ) @Wildcard String options) { + + String cmd = "mineDefine"; + + String wgSetting = "prison-mines.world-guard.mine-region-commands.define"; + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + } + + @Command(identifier = "mines worldguard region mineRedefine", + description = "WorldGuard Regions: define a mine region based upon the mine's size.", + onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsMineRedfine(CommandSender sender, + @Arg(name = "mineName", description = "mine name") String mineName, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console. " + ) @Wildcard String options) { + + String cmd = "mineRedefine"; + + String wgSetting = "prison-mines.world-guard.mine-region-commands.redefine"; + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + } + + + @Command(identifier = "mines worldguard region mineSelect", + description = "WorldGuard Regions: select a mine region", + onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsMineSelect(CommandSender sender, + @Arg(name = "mineName", description = "mine name") String mineName, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console. " + ) @Wildcard String options) { + + String cmd = "mineSelect"; + + String wgSetting = "prison-mines.world-guard.mine-region-commands.select"; + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + } + + + @Command(identifier = "mines worldguard region globalInfo", + description = "WorldGuard Regions: info on the global region '__global__'.", + onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsGlobalInfo(CommandSender sender, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console." + ) @Wildcard String options) { + + String cmd = "globalInfo"; + + String wgSetting = "prison-mines.world-guard.global-region-commands.info"; + + String mineName = "*global*"; + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + } + + + @Command(identifier = "mines worldguard region globalDefine", + description = "WorldGuard Regions: define the global region '__global__' based " + + "upon the config settings within config.yml..", + onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsGlobalDefine(CommandSender sender, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console. " + ) @Wildcard String options) { + + String cmd = "globalDefine"; + + String wgSetting = "prison-mines.world-guard.global-region-commands.define"; + + String mineName = "*global*"; + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + } + + @Command(identifier = "mines worldguard region globalMobSpawningDeny", + description = "WorldGuard Regions: prevent mob spawning using global region '__global__' based " + + "upon the config settings within config.yml..", + onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsGlobalMobSpawningDeny(CommandSender sender, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console. " + ) @Wildcard String options) { + + String cmd = "globalMobSpawningDeny"; + + String wgSetting = "prison-mines.world-guard.global-region-commands.deny-mob-spawning"; + + String mineName = "*global*"; + + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + } + + +// @Command(identifier = "mines worldguard region mineAreaInfo", +// description = "WorldGuard Regions: info on the mine area's region. " +// + "&6NOTE: mine areas have not been added to prison yet, so this will do nothing.", +// onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsMineAreaInfo(CommandSender sender, + @Arg(name = "mineName", description = "mine name") String mineName, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console. " + ) @Wildcard String options) { + + String cmd = "mineAreaInfo"; + + String wgSetting = "prison-mines.world-guard.mine-area-region-commands.info"; + + sender.sendMessage( "&6Notice: mine areas have not been added to prison yet. This will do nothing."); + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + } + +// @Command(identifier = "mines worldguard region mineAreaDefine", +// description = "WorldGuard Regions: define the mine area's region. " +// + "&6NOTE: mine areas have not been added to prison yet, so this will do nothing.", +// onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsMineAreaDefine(CommandSender sender, + @Arg(name = "mineName", description = "mine name") String mineName, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console. " + ) @Wildcard String options) { + + String cmd = "mineAreaDefine"; + + String wgSetting = "prison-mines.world-guard.mine-area-region-commands.define"; + + sender.sendMessage( "&6Notice: mine areas have not been added to prison yet. This will do nothing."); + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + } + +// @Command(identifier = "mines worldguard region mineAreaRedefine", +// description = "WorldGuard Regions: redefine the mine area's region. " +// + "&6NOTE: mine areas have not been added to prison yet, so this will do nothing.", +// onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsMineAreaRedefine(CommandSender sender, + @Arg(name = "mineName", description = "mine name") String mineName, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console. " + ) @Wildcard String options) { + + String cmd = "mineAreaRedefine"; + + String wgSetting = "prison-mines.world-guard.mine-area-region-commands.redefine"; + + sender.sendMessage( "&6Notice: mine areas have not been added to prison yet. This will do nothing."); + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + } + + +// @Command(identifier = "mines worldguard region mineAreaSelect", +// description = "WorldGuard Regions: select the mine area's region. " +// + "&6NOTE: mine areas have not been added to prison yet, so this will do nothing.", +// onlyPlayers = false, permissions = "mines.set") + public void commandWorldGuardRegionsMineAreaSelect(CommandSender sender, + @Arg(name = "mineName", description = "mine name") String mineName, + @Arg(name = "playerName", def = "view", + description = "An online player who can run the " + + "world guard region commands. Optional. If no player is " + + "specified and ran from console, it will only list the " + + "commands and will not try to run them.") String playerName, + @Arg(name = "options", def = "view", + description = "Options: default 'view' [view, run, world-name]. The option 'view' will generate the " + + "list of commands and display them in the console. The 'run' will submit them " + + "to be ran as the player, who must be online. They will be " + + "teleported to the mine's spawn point to ensure they are in the correct " + + "world. If running from console, you must supply the world name, or these " + + "commands cannot be ran from the console. " + ) @Wildcard String options) { + + String cmd = "mineAreaSelect"; + + String wgSetting = "prison-mines.world-guard.mine-area-region-commands.select"; + + sender.sendMessage( "&6Notice: mine areas have not been added to prison yet. This will do nothing."); + + worldGuardRegions( sender, wgSetting, mineName, playerName, options, cmd ); + } + + +// public void worldGuardRegions( CommandSender sender, String wbSetting, +// String mineName, String playerName, String options, +// String command ) { +// +// worldGuardRegions(sender, wbSetting, mineName, playerName, options, command, null); +// } + + public void worldGuardRegions( CommandSender sender, String wbSetting, + String mineName, String playerName, String options, + String command ) { + + PrisonMines pMines = PrisonMines.getInstance(); + + Mine mine = "*global*".equalsIgnoreCase(mineName) ? null : pMines.getMine( mineName ); + Player player = null; + boolean run = false; + String world = null; + + if ( mine != null ) { + world = mine.getWorldName(); + } + else if ( mine == null && !"*global*".equalsIgnoreCase(mineName) ) { + sender.sendMessage( "A valid mine name is required. Try again.");; + return; + } + + // First check to make sure the playerName does not contain the world parameter, + // but only if world was not set from the mine name. + if ( world == null && playerName != null ) { + Optional wOpt = Prison.get().getPlatform().getWorld( playerName ); + if ( wOpt.isPresent() ) { + // Player name is a world name, so use it: + world = playerName; + playerName = ""; + } + } + if ( world == null ) { + // If a world name is supplied, then it should be what's left after you remove any possible + // values for 'view' or 'run'. + String worldName = options.replace("view", "").replace("run", "").trim(); + + if ( worldName != null && worldName.length() > 0 ) { + Optional wOpt = Prison.get().getPlatform().getWorld( worldName ); + if ( wOpt.isPresent() ) { + // Player name is a world name, so use it: + world = worldName; + + // Do not change options... it's not used anymore: + } + } + } + + // Check to see if run has been specified: + if ( playerName.equalsIgnoreCase("run") ) { + run = true; + playerName = null; + } + else if ( playerName.equalsIgnoreCase("view") ) { + run = false; + playerName = null; + } + else if ( options != null ) { + String[] opts = options.split( " " ); + String newOpt = ""; + + for (String opt : opts) { + if ( opt.equalsIgnoreCase( "run" ) ) { + run = true; + } + else if ( opt.equalsIgnoreCase( "view" ) ) { + run = false; + } + else if ( world == null ) { + Optional wOpt = Prison.get().getPlatform().getWorld( opt ); + if ( wOpt.isPresent() ) { + // Set the world name: + world = opt; + } + } + else { + newOpt += opt + " "; + } + } + + options = newOpt.trim(); + } + + + + if ( sender.isPlayer() ) { + player = sender.getPlatformPlayer(); + } + else { + + // Get a Bukkit online player, which is needed to run the WorldGuard commands through: + Prison.get().getPlatform().getPlayer(playerName); + + } + + + String mode = run ? "Running" : "Viewing"; + ChatDisplay display = new ChatDisplay("WorldGuard Region Commands - " + mode); + display.addText("'/mines worldGuard regions " + command +"'"); + display.addText(""); + + if ( mine != null ) { + display.addText( "&3Mine: &7%s", mine.getTag() ); + + } + else if ( "*global*".equalsIgnoreCase(mineName) ) { + display.addText( "&3Global: &7__global__"); + } + + if ( run && player != null ) { + player.sendMessage( String.format( + "&cTeleporting you to mine &3%s &bto run WorldGuard Region " + + "commands on your behalf.", + mine.getTag()) ); + teleportPlayer(player, mine, "spawn"); + } + + String worldName = mine != null && !mine.isVirtual() ? + mine.getWorldName() : + world != null ? world : + player != null ? player.getLocation().getWorld().getName() : + "world-not-set"; + + display.addText( "&3World: &7%s", worldName ); + + display.addText(""); + + + List wbCommands = Prison.get().getPlatform().getConfigStringArray( wbSetting ); + + if ( wbCommands.size() > 0 ) { + + List cmds = new ArrayList<>(); + + + String worldPlaceholder = worldName.equals("world-not-set") ? "" : + !sender.isPlayer() ? "-w " + worldName : + ""; + + + String regionMineName = Prison.get().getPlatform().getConfigString( + "prison-mines.world-guard.region-mine.region-mine-name", "prison_mine_{mine}"); + String regionGroupPerms = Prison.get().getPlatform().getConfigString( + "prison-mines.world-guard.region-mine.region-group-permission", "g:prison.mines.{mine}"); + + regionMineName = regionMineName.replace("{mine}", mine == null ? "(no-mine)" : mine.getName() ); + regionGroupPerms = regionGroupPerms.replace("{mine}", mine == null ? "(no-mine)" : mine.getName() ); + + String minePos1 = mine == null ? "(no-mine)" : + mine.isVirtual() ? "(virtual-mine-no-coordinates)" : + mine.getBounds().getxBlockMin() + "," + + mine.getBounds().getyBlockMin() + "," + + mine.getBounds().getzBlockMin(); + String minePos2 = mine == null ? "(no-mine)" : + mine.isVirtual() ? "(virtual-mine-no-coordinates)" : + mine.getBounds().getxBlockMax() + "," + + mine.getBounds().getyBlockMax() + "," + + mine.getBounds().getzBlockMax(); + + for (String cmd : wbCommands) { + + String msg = cmd.replace("{mine-pos1}", minePos1) + .replace("{mine-pos2}", minePos2) + .replace("{region-mine-name}", regionMineName) + .replace("{region-group-permission}", regionGroupPerms) + .replace("{world}", worldPlaceholder); + + if ( msg.startsWith( "/" ) ) { + msg = msg.substring( 1 ); + } + + cmds.add( msg ); + display.addText( "&4 %s", msg ); + + } + + display.send( sender ); + + if ( run ) { + // submit the commands in cmds: + + for (String cmd : cmds) { + + sender.sendMessage( "&3Running: &7" + cmd ); + if ( player != null ) { + + Prison.get().getPlatform().dispatchCommand(player, cmd); + } + else { + // Player was not defined, so try to run everything as console: + Prison.get().getPlatform().dispatchCommand( cmd ); + } + } + } + + } + else { + sender.sendMessage( + String.format( "Invalid settings: config.yml does not have the proper WorldGuard settings. " + + "[%s]", wbSetting ) ); + } + + } + + + @Command(identifier = "mines dump", permissions = "mines.block", onlyPlayers = false, + description = "Temp command for testing: Dumps a mine as a json object.") + public void minesDumpCommand(CommandSender sender, + @Arg(name = "mineName", description = "The name of the mine to dump") + String mineName ) { + + PrisonMines pMines = PrisonMines.getInstance(); + + Mine mine = pMines.getMine( mineName ); + + if ( mine != null ) { + + JsonFileIO jfio = new JsonFileIO(); + + + DecimalFormat dFmt = new DecimalFormat( "####" ); + + int ser = (int) (Math.random() * 9999d); + + String fName = "temp_mines_" + dFmt.format(ser) + ".json"; + + File f = new File( Prison.get().getDataFolder(), fName); + + + try { + +// String mineJson = jfio.toString(mine); + + jfio.saveJsonFile(f, mine ); + + sender.sendMessage( "Mine dumpped to: " + f.getAbsolutePath() ); + } + catch (Exception e) { + + sender.sendMessage( "Mine dump error: " + e.getMessage() ); + e.printStackTrace(); + } + + } + else { + sender.sendMessage( "A valid mine name is required. Try again.");; + return; + } + + + } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesImportCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesImportCommands.java index 1ca912e33..21756b523 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesImportCommands.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesImportCommands.java @@ -14,14 +14,14 @@ import tech.mcprison.prison.internal.block.PrisonBlockTypes; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.mines.data.Mine.MineNotificationMode; import tech.mcprison.prison.mines.data.Mine.MineType; -import tech.mcprison.prison.mines.data.MineData.MineNotificationMode; import tech.mcprison.prison.mines.features.MineLinerBuilder; import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.selection.Selection; -import tech.mcprison.prison.util.Location; import tech.mcprison.prison.util.Bounds.Edges; +import tech.mcprison.prison.util.Location; public class MinesImportCommands extends MinesBlockCommands { @@ -31,30 +31,17 @@ public MinesImportCommands( String cmdGroup ) { super( cmdGroup ); } - - public void importJetsPrisonMines( CommandSender sender, String options ) { - - boolean save = false; - boolean addLiner = false; - - String path = "JetsPrisonMines//mines//"; - - String worldForced = ""; - -// if ( options.contains( "testImport" ) ) { -// testImport = true; -// list = true; -// options = options.replace( "testImport", "" ).trim(); -// } -// -// if ( options.contains( "list" ) ) { -// testImport = false; -// list = true; -// options = options.replace( "list", "" ).trim(); -// } + + boolean save = false; + boolean addLiner = false; + + String path = "JetsPrisonMines//mines//"; + + String worldForced = ""; + if ( options.contains( "save" ) ) { save = true; @@ -158,22 +145,21 @@ else if ( save ) { mines.addAll( pMines.getMines() ); - for ( Mine mine : mines ) - { - if ( !mine.isVirtual() ) { - - for (Edges edge : Edges.values() ) { - - LinerPatterns linerPattern = LinerPatterns.fromString( - mine.getLinerData().getEdge(edge) ); - - boolean force = mine.getLinerData().getForce(edge); - boolean useTracer = false; - - new MineLinerBuilder( mine, edge, linerPattern, force, useTracer ); + for ( Mine mine : mines ) { + if ( !mine.isVirtual() ) { + + for (Edges edge : Edges.values() ) { + + LinerPatterns linerPattern = LinerPatterns.fromString( + mine.getLinerData().getEdge(edge) ); + + boolean force = mine.getLinerData().getForce(edge); + boolean useTracer = false; + + new MineLinerBuilder( mine, edge, linerPattern, force, useTracer ); } - - } + + } } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesWorldGuardCommands.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesWorldGuardCommands.java new file mode 100644 index 000000000..31413f30f --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/commands/MinesWorldGuardCommands.java @@ -0,0 +1,11 @@ +package tech.mcprison.prison.mines.commands; + +public class MinesWorldGuardCommands +extends MinesImportCommands { + + + public MinesWorldGuardCommands( String cmdGroup ) { + super( cmdGroup ); + } + +} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/BlockOld.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/BlockOld.java index 414395046..70e757b30 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/BlockOld.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/BlockOld.java @@ -18,111 +18,109 @@ package tech.mcprison.prison.mines.data; -import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; -import tech.mcprison.prison.internal.block.PrisonBlockStatusData; -import tech.mcprison.prison.util.ObsoleteBlockType; - /** * Represents a block in a mine * * @deprecated */ +//@SuppressWarnings("deprecation") public class BlockOld - extends PrisonBlockStatusData - implements Comparable { - - public static final BlockOld AIR = new BlockOld( ObsoleteBlockType.AIR ); - public static final BlockOld IGNORE = new BlockOld( ObsoleteBlockType.IGNORE ); - public static final BlockOld NULL_BLOCK = new BlockOld( ObsoleteBlockType.NULL_BLOCK ); - - /** - * The {@link BlockType} represented by this {@link BlockOld} - */ - private ObsoleteBlockType type; // = BlockType.AIR; - /** - * The chance of this block appearing in it's associated mine - */ -// private double chance; // = 100.0d; - - - protected BlockOld( ObsoleteBlockType block ) { - this( block, 0.0d, 0L ); - } - - /** - * Assigns the type and chance - */ - public BlockOld(ObsoleteBlockType block, double chance, long blockCountTotal) { - super( PrisonBlockType.minecraft, (block == null ? BlockOld.AIR.getBlockName() : block.name()), chance, blockCountTotal); - - this.type = block; -// this.chance = chance; - } - - public BlockOld(String blockType, double chance, long blockCountTotal) { - super( PrisonBlockType.minecraft, blockType, chance, blockCountTotal); - -// this.chance = chance; - - ObsoleteBlockType block = ObsoleteBlockType.fromString( blockType ); - this.type = block; - // Update blockName since mapping to BlockType may result in a different name: - setBlockName( block.name() ); - - } - - @Override - public String toString() { - return getType().name() + " " + Double.toString( getChance() ); - } - - - @Override - public boolean equals( Object block ) { - boolean results = false; - - if ( block != null && block instanceof BlockOld) { - results = getType() == ((BlockOld) block).getType(); - } - - return results; - } +// extends PrisonBlockStatusData +// implements Comparable +{ - @Override - public int compareTo( BlockOld block ) - { - int results = 0; - - if ( block == null ) { - results = 1; - } - else { - results = getBlockName().compareToIgnoreCase( block.getBlockName() ); - } - - return results; - } - - public ObsoleteBlockType getType() - { - return type; - } - public void setType( ObsoleteBlockType type ) - { - this.type = type; - } - - @Override - public boolean isAir() { - return compareTo( AIR ) == 0; - } - -// public double getChance() +// public static final BlockOld AIR = new BlockOld( ObsoleteBlockType.AIR ); +// public static final BlockOld IGNORE = new BlockOld( ObsoleteBlockType.IGNORE ); +// public static final BlockOld NULL_BLOCK = new BlockOld( ObsoleteBlockType.NULL_BLOCK ); +// +// /** +// * The {@link BlockType} represented by this {@link BlockOld} +// */ +// private ObsoleteBlockType type; // = BlockType.AIR; +// /** +// * The chance of this block appearing in it's associated mine +// */ +//// private double chance; // = 100.0d; +// +// +// protected BlockOld( ObsoleteBlockType block ) { +// this( block, 0.0d, 0L ); +// } +// +// /** +// * Assigns the type and chance +// */ +// public BlockOld(ObsoleteBlockType block, double chance, long blockCountTotal) { +// super( PrisonBlockType.minecraft, (block == null ? BlockOld.AIR.getBlockName() : block.name()), chance, blockCountTotal); +// +// this.type = block; +//// this.chance = chance; +// } +// +// public BlockOld(String blockType, double chance, long blockCountTotal) { +// super( PrisonBlockType.minecraft, blockType, chance, blockCountTotal); +// +//// this.chance = chance; +// +// ObsoleteBlockType block = ObsoleteBlockType.fromString( blockType ); +// this.type = block; +// // Update blockName since mapping to BlockType may result in a different name: +// setBlockName( block.name() ); +// +// } +// +// @Override +// public String toString() { +// return getType().name() + " " + Double.toString( getChance() ); +// } +// +// +// @Override +// public boolean equals( Object block ) { +// boolean results = false; +// +// if ( block != null && block instanceof BlockOld) { +// results = getType() == ((BlockOld) block).getType(); +// } +// +// return results; +// } +// +// @Override +// public int compareTo( BlockOld block ) +// { +// int results = 0; +// +// if ( block == null ) { +// results = 1; +// } +// else { +// results = getBlockName().compareToIgnoreCase( block.getBlockName() ); +// } +// +// return results; +// } +// +// public ObsoleteBlockType getType() // { -// return chance; +// return type; // } -// public void setChance( double chance ) +// public void setType( ObsoleteBlockType type ) // { -// this.chance = chance; +// this.type = type; +// } +// +// @Override +// public boolean isAir() { +// return compareTo( AIR ) == 0; // } +// +//// public double getChance() +//// { +//// return chance; +//// } +//// public void setChance( double chance ) +//// { +//// this.chance = chance; +//// } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java index a98462376..52d76f401 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/Mine.java @@ -25,6 +25,7 @@ import java.util.Set; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.file.FileIOData; import tech.mcprison.prison.internal.World; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockStatusData; @@ -40,7 +41,6 @@ import tech.mcprison.prison.store.Document; import tech.mcprison.prison.util.Bounds; import tech.mcprison.prison.util.Location; -import tech.mcprison.prison.util.ObsoleteBlockType; /** * @author Dylan M. Perks @@ -48,7 +48,16 @@ @SuppressWarnings( "deprecation" ) public class Mine extends MineScheduler - implements PrisonSortable, Comparable, PlaceholderStringCoverter { + implements PrisonSortable, Comparable, + PlaceholderStringCoverter, + FileIOData { + + + public static final int MINE_RESET__TIME_SEC__DEFAULT = 15 * 60; // 15 minutes + public static final int MINE_RESET__TIME_SEC__MINIMUM = 30; // 30 seconds + public static final long MINE_RESET__BROADCAST_RADIUS_BLOCKS = 150; + + public static final String MINE_NOTIFICATION_PERMISSION_PREFIX = "mines.notification."; public enum MineType { @@ -75,6 +84,39 @@ public enum MineUnitTestUsage { TRUE; } + public enum MineNotificationMode { + disabled, + disable, + within, + radius, + world, + server, + + displayOptions + ; + + public static MineNotificationMode fromString(String mode) { + return fromString(mode, radius); + } + public static MineNotificationMode fromString(String mode, MineNotificationMode defaultValue) { + MineNotificationMode results = defaultValue; + + if ( mode != null && mode.trim().length() > 0 ) { + for ( MineNotificationMode mnm : values() ) { + if ( mnm.name().equalsIgnoreCase( mode )) { + results = mnm; + } + } + } + + if ( results == disable ) { + results = disabled; + } + + return results; + } + } + /** * Creates a new, empty mine instance */ @@ -94,12 +136,9 @@ public Mine() { * @param unitTestUsage */ public Mine( MineUnitTestUsage unitTestUsage, String mineName ) { - super(); + super(); setName( mineName ); - - // Kick off the initialize: - //initialize(); } @@ -111,35 +150,35 @@ public Mine( MineUnitTestUsage unitTestUsage, String mineName ) { * @param selection */ public Mine(String name, Selection selection) { - this( name, selection, MineType.primary ); + this( name, selection, MineType.primary ); } public Mine(String name, Selection selection, MineType mineType, boolean logInfo ) { - super(); - - setName(name); - - setMineType( mineType ); - - if ( selection == null ) { - setVirtual( true ); - } - else { - - setBounds(selection.asBounds(), logInfo ); - - setWorldName( getBounds().getMin().getWorld().getName()); - - setEnabled( true ); - } - - // Kick off the initialize: - initialize(); - } - - public Mine(String name, Selection selection, MineType mineType) { - this( name, selection, mineType, true ); - + super(); + + setName(name); + + setMineType( mineType ); + + if ( selection == null ) { + setVirtual( true ); + } + else { + + setBounds(selection.asBounds(), logInfo ); + + setWorldName( getBounds().getMin().getWorld().getName()); + + setEnabled( true ); + } + + // Kick off the initialize: + initialize(); + } + + public Mine(String name, Selection selection, MineType mineType) { + this( name, selection, mineType, true ); + } /** @@ -181,7 +220,7 @@ public Mine(String name, Selection selection, MineType mineType) { * @throws MineException If the mine couldn't be loaded from the document. */ public Mine(Document document) throws MineException { - super(); + super(); loadFromDocument( document ); @@ -200,7 +239,7 @@ public Mine(Document document) throws MineException { */ @Override protected void initialize() { - super.initialize(); + super.initialize(); } @@ -254,13 +293,13 @@ private void loadFromDocument( Document document ) String accessPerm = (String) document.get("accessPermission"); setAccessPermission( (accessPerm == null || accessPerm.trim().isEmpty() ? null : accessPerm) ); - - setTpAccessByRank( document.get("tpAccessByRank") == null ? false : (boolean) document.get("tpAccessByRank") ); - setMineAccessByRank( document.get("mineAccessByRank") == null ? false : (boolean) document.get("mineAccessByRank") ); - - - setVirtual( document.get("isVirtual") == null ? false : (boolean) document.get("isVirtual") ); - + + setTpAccessByRank( document.get("tpAccessByRank") == null ? false : (boolean) document.get("tpAccessByRank") ); + setMineAccessByRank( document.get("mineAccessByRank") == null ? false : (boolean) document.get("mineAccessByRank") ); + + + setVirtual( document.get("isVirtual") == null ? false : (boolean) document.get("isVirtual") ); + Double sortOrder = (Double) document.get( "sortOrder" ); setSortOrder( sortOrder == null ? 0 : sortOrder.intValue() ); @@ -350,90 +389,88 @@ private void loadFromDocument( Document document ) Set validateBlockNames = new HashSet<>(); getBlocks().clear(); - List docBlocks = (List) document.get("blocks"); - for (String docBlock : docBlocks) { - - // If the file is manually edited and a comma is added to the end of the block list, - // then docBlock could be null. Skip processing if null. - if ( docBlock != null ) { - - String[] split = docBlock.split("-"); - String blockTypeName = split[0]; -// double chance = split.length > 1 ? Double.parseDouble(split[1]) : 0; -// long blockCount = split.length > 2 ? Long.parseLong(split[2]) : 0; -// int constraintMin = split.length > 3 ? Integer.parseInt(split[3]) : 0; -// int constraintMax = split.length > 4 ? Integer.parseInt(split[4]) : 0; - - if ( blockTypeName != null && !validateBlockNames.contains( blockTypeName )) { - // Use the BlockType.name() load the block type: - ObsoleteBlockType blockType = ObsoleteBlockType.getBlock(blockTypeName); - if ( blockType != null ) { - - /** - *

    The following is code to correct the use of items being used as a - * block in a mine, which will cause a failure in trying to place an - * item as a block. - *

    - * - *

    This is intended for the old block model and is temp code to ensure - * that there are less errors the end user will experience. - *

    - */ - String errorMessage = "Warning! An invalid block type of %s was " + - "detect when loading blocks for " + - "mine %s. %s is not a valid block type. Using " + - "%s instead. If this is incorrect please fix manually."; - - if ( blockType == ObsoleteBlockType.REDSTONE ) { - ObsoleteBlockType itemType = blockType; - blockType = ObsoleteBlockType.REDSTONE_ORE; - - Output.get().logError( - String.format( errorMessage, itemType.name(), getName(), - "Redstone dust", blockType.name()) ); - - dirty = true; - } - else if ( blockType == ObsoleteBlockType.NETHER_BRICK ) { - ObsoleteBlockType itemType = blockType; - blockType = ObsoleteBlockType.DOUBLE_NETHER_BRICK_SLAB; - - Output.get().logError( - String.format( errorMessage, itemType.name(), getName(), - "Individual nether brick", blockType.name()) ); - - dirty = true; - } - - BlockOld block = new BlockOld(blockType); - - block.parseFromSaveFileFormatStats( docBlock ); - - totalBlockCount += block.getBlockCountTotal(); - -// BlockOld block = new BlockOld(blockType, chance, blockCount); -// block.setConstraintMin( constraintMin ); -// block.setConstraintMax( constraintMax ); - - getBlocks().add(block); - } - else { - String message = String.format( "Failure in loading block type from %s mine's " + - "save file. Block type %s has no mapping.", getName(), - blockTypeName ); - Output.get().logError( message ); - } - - validateBlockNames.add( blockTypeName ); - } - else if (validateBlockNames.contains( blockTypeName ) ) { - // Detected and fixed a duplication so mark as dirty so fixed block list is saved: - dirty = true; - inconsistancy = true; - } - } - - } + + // Obsolete block model: +// List docBlocks = (List) document.get("blocks"); +// for (String docBlock : docBlocks) { +// +// // If the file is manually edited and a comma is added to the end of the block list, +// // then docBlock could be null. Skip processing if null. +// if ( docBlock != null ) { +// +// String[] split = docBlock.split("-"); +// String blockTypeName = split[0]; +//// double chance = split.length > 1 ? Double.parseDouble(split[1]) : 0; +//// long blockCount = split.length > 2 ? Long.parseLong(split[2]) : 0; +//// int constraintMin = split.length > 3 ? Integer.parseInt(split[3]) : 0; +//// int constraintMax = split.length > 4 ? Integer.parseInt(split[4]) : 0; +// +// if ( blockTypeName != null && !validateBlockNames.contains( blockTypeName )) { +// // Use the BlockType.name() load the block type: +// ObsoleteBlockType blockType = ObsoleteBlockType.getBlock(blockTypeName); +// if ( blockType != null ) { +// +// /** +// *

    The following is code to correct the use of items being used as a +// * block in a mine, which will cause a failure in trying to place an +// * item as a block. +// *

    +// * +// *

    This is intended for the old block model and is temp code to ensure +// * that there are less errors the end user will experience. +// *

    +// */ +// String errorMessage = "Warning! An invalid block type of %s was " + +// "detect when loading blocks for " + +// "mine %s. %s is not a valid block type. Using " + +// "%s instead. If this is incorrect please fix manually."; +// +// if ( blockType == ObsoleteBlockType.REDSTONE ) { +// ObsoleteBlockType itemType = blockType; +// blockType = ObsoleteBlockType.REDSTONE_ORE; +// +// Output.get().logError( +// String.format( errorMessage, itemType.name(), getName(), +// "Redstone dust", blockType.name()) ); +// +// dirty = true; +// } +// else if ( blockType == ObsoleteBlockType.NETHER_BRICK ) { +// ObsoleteBlockType itemType = blockType; +// blockType = ObsoleteBlockType.DOUBLE_NETHER_BRICK_SLAB; +// +// Output.get().logError( +// String.format( errorMessage, itemType.name(), getName(), +// "Individual nether brick", blockType.name()) ); +// +// dirty = true; +// } +// +// BlockOld block = new BlockOld(blockType); +// +// block.parseFromSaveFileFormatStats( docBlock ); +// +// totalBlockCount += block.getBlockCountTotal(); +// +// getBlocks().add(block); +// } +// else { +// String message = String.format( "Failure in loading block type from %s mine's " + +// "save file. Block type %s has no mapping.", getName(), +// blockTypeName ); +// Output.get().logError( message ); +// } +// +// validateBlockNames.add( blockTypeName ); +// } +// else if (validateBlockNames.contains( blockTypeName ) ) { +// // Detected and fixed a duplication so mark as dirty so fixed block list is saved: +// dirty = true; +// inconsistancy = true; +// } +// } +// +// } // Reset validation checks: @@ -500,46 +537,6 @@ else if ( validateBlockNames.contains( prisonBlock.getBlockName() ) ) { } - -// String[] split = docBlock.split("-"); -// String blockTypeName = split[0]; -// double chance = split.length > 1 ? Double.parseDouble(split[1]) : 0; -// long blockCount = split.length > 2 ? Long.parseLong(split[2]) : 0; -// int constraintMin = split.length > 3 ? Integer.parseInt(split[3]) : 0; -// int constraintMax = split.length > 4 ? Integer.parseInt(split[4]) : 0; -// int constraintExcludeTopLayers = split.length > 5 ? Integer.parseInt(split[5]) : 0; -// int constraintExcludeBottomLayers = split.length > 6 ? Integer.parseInt(split[6]) : 0; -// -// if ( blockTypeName != null ) { -// // The new way to get the PrisonBlocks: -// // The blocks return are cloned so they have their own instance: -// PrisonBlock prisonBlock = Prison.get().getPlatform().getPrisonBlock( blockTypeName ); -// -// if ( prisonBlock != null && !validateBlockNames.contains( blockTypeName )) { -// prisonBlock.setChance( chance ); -// prisonBlock.setBlockCountTotal( blockCount ); -// prisonBlock.setConstraintMin( constraintMin ); -// prisonBlock.setConstraintMax( constraintMax ); -// prisonBlock.setConstraintExcludeTopLayers( constraintExcludeTopLayers ); -// prisonBlock.setConstraintExcludeBottomLayers( constraintExcludeBottomLayers ); -// -// -// if ( prisonBlock.isLegacyBlock() ) { -// dirty = true; -// } -// addPrisonBlock( prisonBlock ); -// -// validateBlockNames.add( blockTypeName ); -// } -// else if (validateBlockNames.contains( blockTypeName ) ) { -// // Detected and fixed a duplication so mark as dirty so fixed block list is saved: -// dirty = true; -// inconsistancy = true; -// } -// -// } - - } } @@ -556,64 +553,61 @@ else if ( validateBlockNames.contains( prisonBlock.getBlockName() ) ) { // Using the Obsolete old block model for conversion to the new block model // NOTE: This is the ONLY place were we are allowed to use the old block model! ;) - if ( // isUseNewBlockModel() && - getPrisonBlocks().size() == 0 && getBlocks().size() > 0 ) { - // Need to perform the initial conversion: - - for ( BlockOld blockOld : getBlocks() ) { - PrisonBlock prisonBlock = Prison.get().getPlatform().getPrisonBlock( blockOld.getType().name() ); - - if ( prisonBlock == null ) { - for ( String altName : blockOld.getType().getXMaterialAltNames() ) { - - prisonBlock = Prison.get().getPlatform().getPrisonBlock( altName ); - if ( prisonBlock != null ) { - break; - } - } - } - - if ( prisonBlock != null ) { - - // This transfers all the stats over so none are lost. - prisonBlock.transferStats( blockOld ); - - addPrisonBlock( prisonBlock ); - - dirty = true; - } - - } - Output.get().logInfo( "Notice: Mine: " + getName() + ": Existing prison block model has " + - "been converted to the new block model and will be saved." ); - } +// if ( // isUseNewBlockModel() && +// getPrisonBlocks().size() == 0 && getBlocks().size() > 0 ) { +// // Need to perform the initial conversion: +// +// for ( BlockOld blockOld : getBlocks() ) { +// PrisonBlock prisonBlock = Prison.get().getPlatform().getPrisonBlock( blockOld.getType().name() ); +// +// if ( prisonBlock == null ) { +// for ( String altName : blockOld.getType().getXMaterialAltNames() ) { +// +// prisonBlock = Prison.get().getPlatform().getPrisonBlock( altName ); +// if ( prisonBlock != null ) { +// break; +// } +// } +// } +// +// if ( prisonBlock != null ) { +// +// // This transfers all the stats over so none are lost. +// prisonBlock.transferStats( blockOld ); +// +// addPrisonBlock( prisonBlock ); +// +// dirty = true; +// } +// +// } +// +// Output.get().logInfo( "Notice: Mine: " + getName() + ": Existing prison block model has " + +// "been converted to the new block model and will be saved." ); +// } List commands = (List) document.get("commands"); setResetCommands( commands == null ? new ArrayList<>() : commands ); -// Boolean usePagingOnReset = (Boolean) document.get( "usePagingOnReset" ); -// setUsePagingOnReset( usePagingOnReset == null ? false : usePagingOnReset.booleanValue() ); - - List mineBlockEvents = (List) document.get("mineBlockEvents"); if ( mineBlockEvents != null ) { - for ( String blockEvent : mineBlockEvents ) { - if ( blockEvent != null ) { - - MineBlockEvent bEvent = MineBlockEvent.fromSaveString( blockEvent, this.getName() ); - - if ( bEvent != null ) { - - getBlockEvents().add( bEvent ); - } - else { - Output.get().logInfo( "Notice: Mine: " + getName() + ": Error trying to parse a blockEvent. " - + "BlockEvent is lost: raw BlockEvent= [" + blockEvent + "]" ); - } - } - } + for ( String blockEvent : mineBlockEvents ) { + if ( blockEvent != null ) { + + MineBlockEvent bEvent = MineBlockEvent.fromSaveString( blockEvent, this.getName() ); + + if ( bEvent != null ) { + + getBlockEvents().add( bEvent ); + } + else { + Output.get().logInfo( "Notice: Mine: " + getName() + ": Error trying to parse a blockEvent. " + + "BlockEvent is lost: raw BlockEvent= [" + blockEvent + "]" ); + } + } + } } @@ -626,26 +620,26 @@ else if ( validateBlockNames.contains( prisonBlock.getBlockName() ) ) { if ( dirty ) { - // Resave the mine data since an update to the mine format was detected and - // needs to be saved. Otherwise the bad data will always need to be converted - // every time the mine is loaded which may lead to other issues. - - // This is enabled since the original is not modified. - - // If dirty, then make a backup since these are automatic changes: - PrisonMines.getInstance().getMineManager().backupMine( this ); - - PrisonMines.getInstance().getMineManager().saveMine( this ); - - if ( inconsistancy ) { - - Output.get().logInfo( "Notice: Mine: " + getName() + ": During the loading of this mine an " + - "inconsistancy was detected and was fixed then saved." ); - } - else { - Output.get().logInfo( "Notice: Mine: " + getName() + ": Updated mine data was successfully saved." ); - - } + // Resave the mine data since an update to the mine format was detected and + // needs to be saved. Otherwise the bad data will always need to be converted + // every time the mine is loaded which may lead to other issues. + + // This is enabled since the original is not modified. + + // If dirty, then make a backup since these are automatic changes: + PrisonMines.getInstance().getMineManager().backupMine( this ); + + PrisonMines.getInstance().getMineManager().saveMine( this ); + + if ( inconsistancy ) { + + Output.get().logInfo( "Notice: Mine: " + getName() + ": During the loading of this mine an " + + "inconsistancy was detected and was fixed then saved." ); + } + else { + Output.get().logInfo( "Notice: Mine: " + getName() + ": Updated mine data was successfully saved." ); + + } } } @@ -656,11 +650,12 @@ public Document toDocument() { // If world name is not set, try to get it from the bounds: String worldName = getWorldName(); if ( (worldName == null || worldName.trim().length() == 0 || - "Virtually-Undefined".equalsIgnoreCase( worldName )) && - getBounds() != null && getBounds().getMin() != null && - getBounds().getMin().getWorld() != null ) { - worldName = getBounds().getMin().getWorld().getName(); - setWorldName( worldName ); + "Virtually-Undefined".equalsIgnoreCase( worldName )) && + getBounds() != null && getBounds().getMin() != null && + getBounds().getMin().getWorld() != null ) { + + worldName = getBounds().getMin().getWorld().getName(); + setWorldName( worldName ); } ret.put("world", worldName ); ret.put("name", getName()); @@ -718,33 +713,33 @@ public Document toDocument() { // This is the ONLY SECOND place where we can use the old block model! // We want to "preserve" the old blocks that may have been setup up in the mines // originally. In a future release, these may be purged. - List blockStrings = new ArrayList<>(); - for (BlockOld block : getBlocks()) { - if ( !validateBlockNames.contains( block.getType().name() )) { - - blockStrings.add( block.toSaveFileFormat() ); - -// // Use the BlockType.name() to save the block type to the file: -// blockStrings.add(block.getType().name() + "-" + block.getChance()); -// blockStrings.add(block.getType().getId() + "-" + block.getChance()); - validateBlockNames.add( block.getType().name() ); - } - } - - ret.put("blocks", blockStrings); +// List blockStrings = new ArrayList<>(); +// for (BlockOld block : getBlocks()) { +// if ( !validateBlockNames.contains( block.getType().name() )) { +// +// blockStrings.add( block.toSaveFileFormat() ); +// +// // // Use the BlockType.name() to save the block type to the file: +// // blockStrings.add(block.getType().name() + "-" + block.getChance()); +// // blockStrings.add(block.getType().getId() + "-" + block.getChance()); +// validateBlockNames.add( block.getType().name() ); +// } +// } + +// ret.put("blocks", blockStrings); // reset validation for next block list: validateBlockNames.clear(); List prisonBlockStrings = new ArrayList<>(); for (PrisonBlock pBlock : getPrisonBlocks() ) { - if ( !validateBlockNames.contains( pBlock.getBlockName()) ) { - - prisonBlockStrings.add( pBlock.toSaveFileFormat() ); - -// prisonBlockStrings.add(pBlock.getBlockNameFormal() + "-" + pBlock.getChance()); - validateBlockNames.add( pBlock.getBlockNameFormal() ); - } + if ( !validateBlockNames.contains( pBlock.getBlockName()) ) { + + prisonBlockStrings.add( pBlock.toSaveFileFormat() ); + + // prisonBlockStrings.add(pBlock.getBlockNameFormal() + "-" + pBlock.getChance()); + validateBlockNames.add( pBlock.getBlockNameFormal() ); + } } ret.put("prisonBlocks", prisonBlockStrings); @@ -752,9 +747,6 @@ public Document toDocument() { ret.put("commands", getResetCommands()); -// ret.put( "usePagingOnReset", isUsePagingOnReset() ); - - if ( getRank() != null ) { String rank = getRank().getModuleElementType() + "," + getRank().getName() + "," + getRank().getId() + "," + getRank().getTag(); @@ -779,7 +771,7 @@ public Document toDocument() { @Override public String toString() { - return getName() + " " + getTotalBlocksMined(); + return getName() + " " + getTotalBlocksMined(); } /** @@ -796,40 +788,36 @@ public String toString() { * @return */ private Location getLocation(Document doc, World world, String x, String y, String z) { - Location results = null; - -// if ( world != null ) { -// -// -// } - Object xD = doc.get(x); - Object yD = doc.get(y); - Object zD = doc.get(z); - - if ( xD != null && yD != null && zD != null ) { - - results = new Location(world, (double) xD, (double) yD, (double) zD ); - } - - return results; + Location results = null; + + Object xD = doc.get(x); + Object yD = doc.get(y); + Object zD = doc.get(z); + + if ( xD != null && yD != null && zD != null ) { + + results = new Location(world, (double) xD, (double) yD, (double) zD ); + } + + return results; } private Location getLocation(Document doc, World world, String x, String y, String z, String pitch, String yaw) { - Location loc = getLocation(doc, world, x, y, z); - - Object pitchD = doc.get(pitch); - Object yawD = doc.get(yaw); - - if ( pitchD != null ) { - - loc.setPitch( ((Double) pitchD ).floatValue() ); - } - - if ( yawD != null ) { - - loc.setYaw( ((Double) yawD ).floatValue() ); - } - return loc; + Location loc = getLocation(doc, world, x, y, z); + + Object pitchD = doc.get(pitch); + Object yawD = doc.get(yaw); + + if ( pitchD != null ) { + + loc.setPitch( ((Double) pitchD ).floatValue() ); + } + + if ( yawD != null ) { + + loc.setYaw( ((Double) yawD ).floatValue() ); + } + return loc; } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java index e8f3f9f2f..f244662ba 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineData.java @@ -14,6 +14,7 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; import tech.mcprison.prison.internal.block.PrisonBlockStatusData; +import tech.mcprison.prison.mines.data.Mine.MineNotificationMode; import tech.mcprison.prison.mines.data.Mine.MineType; import tech.mcprison.prison.mines.features.MineBlockEvent; import tech.mcprison.prison.mines.features.MineLinerData; @@ -25,24 +26,20 @@ public abstract class MineData implements ModuleElement { - - public static final int MINE_RESET__TIME_SEC__DEFAULT = 15 * 60; // 15 minutes - public static final int MINE_RESET__TIME_SEC__MINIMUM = 30; // 30 seconds - public static final long MINE_RESET__BROADCAST_RADIUS_BLOCKS = 150; - - public static final String MINE_NOTIFICATION_PERMISSION_PREFIX = "mines.notification."; + + private int dataVersion = 1; private transient final ModuleElementType elementType; private String name; private String tag; - private boolean enabled = false; + private transient boolean enabled = false; private boolean virtual = false; // Controls if a mine is able to be used during a mine reset: - private MineStateMutex mineStateMutex; + private transient MineStateMutex mineStateMutex; private MineType mineType; @@ -73,10 +70,10 @@ public abstract class MineData private long notificationRadius; private boolean useNotificationPermission = false; - private long targetResetTime; - private int resetCount = 0; + private transient long targetResetTime; + private transient int resetCount = 0; - private long lastResetTimeLong = 0; + private transient long lastResetTimeLong = 0; /** * These blocks are obsolete, and are no longer used in prison, but they @@ -87,7 +84,7 @@ public abstract class MineData * supporting magic values with the older bukkit versions. */ @SuppressWarnings( "deprecation" ) - private List blocks; + private transient List blocks; /** * This list of PrisonBlocks represents the new Prison block model. Its @@ -107,7 +104,7 @@ public abstract class MineData private transient Set prisonBlockTypes; - private TreeMap blockStats; + private transient TreeMap blockStats; /** *

    If any of the mine's blocks are effected by gravity, then this field @@ -134,13 +131,12 @@ public abstract class MineData private boolean skipResetEnabled = false; private double skipResetPercent; private int skipResetBypassLimit; - private transient int skipResetBypassCount; + private int skipResetBypassCount; private List resetCommands; -// private boolean usePagingOnReset = false; - private ModuleElement rank; + private transient ModuleElement rank; /** * When loading mines, ranks will not have been loaded yet, so must * save the rankString to be paired to the Ranks later. @@ -155,43 +151,14 @@ public abstract class MineData private boolean mineSweeperEnabled; - private int mineSweeperCount; - private long mineSweeperTotalMs; - private long mineSweeperBlocksChanged; + private transient int mineSweeperCount; + private transient long mineSweeperTotalMs; + private transient long mineSweeperBlocksChanged; private transient boolean isDeleted = false; - public enum MineNotificationMode { - disabled, - disable, - within, - radius, - - displayOptions - ; - - public static MineNotificationMode fromString(String mode) { - return fromString(mode, radius); - } - public static MineNotificationMode fromString(String mode, MineNotificationMode defaultValue) { - MineNotificationMode results = defaultValue; - - if ( mode != null && mode.trim().length() > 0 ) { - for ( MineNotificationMode mnm : values() ) { - if ( mnm.name().equalsIgnoreCase( mode )) { - results = mnm; - } - } - } - - if ( results == disable ) { - results = disabled; - } - - return results; - } - } + public MineData() { @@ -221,9 +188,9 @@ public MineData() { */ this.sortOrder = 0; - this.resetTime = MINE_RESET__TIME_SEC__DEFAULT; + this.resetTime = Mine.MINE_RESET__TIME_SEC__DEFAULT; this.notificationMode = MineNotificationMode.radius; - this.notificationRadius = MINE_RESET__BROADCAST_RADIUS_BLOCKS; + this.notificationRadius = Mine.MINE_RESET__BROADCAST_RADIUS_BLOCKS; this.useNotificationPermission = false; this.targetResetTime = 0; @@ -240,7 +207,6 @@ public MineData() { this.resetCommands = new ArrayList<>(); -// this.usePagingOnReset = false; this.rank = null; this.rankString = null; @@ -267,6 +233,34 @@ protected void initialize() { } + /** + *

    This function should be called after loading a mine from + * storage, and this function should reconnect all dynamic objects + * that could not be stored with the core Mine data. + *

    + * + *

    Note: getWorld() is actually a helper to get a world object out of + * getBounds() and setWorld() sets the world on both getBounds() and getSpawn(). + *

    + * + *

    Examples: World objects. There may be other objects that need to be reconnected. + *

    + */ + public void reconnectObjects() { + + if ( !isVirtual() ) { + + if ( getBounds() != null ) { + getBounds().reconnectObjects(); + } + + if ( getSpawn() != null ) { + getSpawn().reconnectObects(); + } + + } + + } public boolean isEnabled() { @@ -309,17 +303,17 @@ public String getName() { } public String getTag() { - return ( tag == null || tag.trim().isEmpty() ? getName() : tag ); + return ( tag == null || tag.trim().isEmpty() ? getName() : tag ); } public void setTag( String tag ) { - this.tag = tag; + this.tag = tag; } public int getSortOrder() { - return sortOrder; + return sortOrder; } public void setSortOrder( int sortOrder ) { - this.sortOrder = sortOrder; + this.sortOrder = sortOrder; } @@ -329,10 +323,10 @@ public void setSortOrder( int sortOrder ) { * set. An id is forced by Ranks and Ladders. */ public int getId() { - return -1; + return -1; } public void setId( int idIsIgnored ) { - // ignore + // ignore } /** @@ -374,7 +368,6 @@ public void setWorldName( String worldName ) { */ public Optional getWorld() { return Optional.ofNullable( isVirtual() ? null : getBounds().getMin().getWorld() ); -// return Prison.get().getPlatform().getWorld(worldName); } /** @@ -399,7 +392,7 @@ public void setWorld( World world ) { } } - setEnabled( world != null ); + setEnabled( world != null ); } public Bounds getBounds() { @@ -407,7 +400,7 @@ public Bounds getBounds() { } public void setBounds(Bounds bounds ) { - setBounds( bounds, true ); + setBounds( bounds, true ); } /** @@ -432,51 +425,51 @@ public void setBounds(Bounds bounds ) { * @param bounds the new boundaries */ public void setBounds(Bounds bounds, boolean logInfo ) { - this.bounds = bounds; - - // if Bounds is null, then clear out the world fields and set mine to virtual and disable the mine: - if ( bounds == null ) { - - setSpawn( null ); - - setWorld( null ); - setWorldName( null ); - setVirtual( true ); - setEnabled( false ); - } - - else if ( isVirtual() || !getWorld().isPresent() || - getWorldName() == null || getWorldName().trim().length() == 0 || - getWorldName().equalsIgnoreCase( "Virtually-Undefined" ) ) { - - World world = bounds.getMin().getWorld(); - - if ( world != null ) { - - setWorld( world ); - setWorldName( world.getName() ); - setVirtual( false ); - setEnabled( true ); - - if ( logInfo ) { - Output.get().logInfo( "&7Mine " + getTag() + "&7: world has been set and is now enabled." ); - } - - } - else { - setEnabled( false ); - Output.get().logWarn( - String.format( "&cCould not activate mine &7%s &cbecause the " + - "world object cannot be aquired. Bounds failed be set correctly " + - "and this mine is &ddisabled&c.", getName()) ); - } - } - - // The world name MUST NEVER be changed. If world is null then it will screw - // up the original location of when the mine was created. World name is set - // in the document loader under Mine.loadFromDocument as the first field - // that is set when restoring from the file. - //this.worldName = bounds.getMin().getWorld().getName(); + this.bounds = bounds; + + // if Bounds is null, then clear out the world fields and set mine to virtual and disable the mine: + if ( bounds == null ) { + + setSpawn( null ); + + setWorld( null ); + setWorldName( null ); + setVirtual( true ); + setEnabled( false ); + } + + else if ( isVirtual() || !getWorld().isPresent() || + getWorldName() == null || getWorldName().trim().length() == 0 || + getWorldName().equalsIgnoreCase( "Virtually-Undefined" ) ) { + + World world = bounds.getMin().getWorld(); + + if ( world != null ) { + + setWorld( world ); + setWorldName( world.getName() ); + setVirtual( false ); + setEnabled( true ); + + if ( logInfo ) { + Output.get().logInfo( "&7Mine " + getTag() + "&7: world has been set and is now enabled." ); + } + + } + else { + setEnabled( false ); + Output.get().logWarn( + String.format( "&cCould not activate mine &7%s &cbecause the " + + "world object cannot be aquired. Bounds failed be set correctly " + + "and this mine is &ddisabled&c.", getName()) ); + } + } + + // The world name MUST NEVER be changed. If world is null then it will screw + // up the original location of when the mine was created. World name is set + // in the document loader under Mine.loadFromDocument as the first field + // that is set when restoring from the file. + //this.worldName = bounds.getMin().getWorld().getName(); } @@ -535,157 +528,34 @@ public boolean removePrisonBlock( PrisonBlock prisonBlock ) { return results; } - // Obsolete... the old block model: -// /** -// * This is only used in an obsolete conversion utility. -// * -// * Adding the newer PrisonBlocks for compatibility. -// * -// * Sets the blocks for this mine -// * -// * @param blockMap the new blockmap with the {@link BlockType} as the key, and the chance of the -// * block appearing as the value. -// */ -// public void setBlocks(HashMap blockMap) { -// this.blocks.clear(); -// this.prisonBlocks.clear(); -// -// for (Map.Entry entry : blockMap.entrySet()) { -// blocks.add(new BlockOld(entry.getKey(), entry.getValue(), 0)); -// -// PrisonBlock prisonBlock = Prison.get().getPlatform().getPrisonBlock( entry.getKey().name() ); -// if ( prisonBlock != null ) { -// prisonBlock.setChance( entry.getValue() ); -// prisonBlocks.add( prisonBlock ); -// } -// } -// } public PrisonBlock getPrisonBlock(String blockName ) { - PrisonBlock results = null; - - if ( blockName != null && !blockName.trim().isEmpty() ) { - for ( PrisonBlock b : getPrisonBlocks() ) { - if ( b.getBlockName().equalsIgnoreCase( blockName ) ) { - results = b; - break; - } - } - } - - return results; + PrisonBlock results = null; + + if ( blockName != null && !blockName.trim().isEmpty() ) { + for ( PrisonBlock b : getPrisonBlocks() ) { + if ( b.getBlockName().equalsIgnoreCase( blockName ) ) { + results = b; + break; + } + } + } + + return results; } -// public BlockOld getBlockOld(String blockName ) { -// BlockOld results = null; -// -// if ( blockName != null && !blockName.trim().isEmpty() ) { -// for ( BlockOld b : getBlocks() ) { -// if ( b.getBlockName().equalsIgnoreCase( blockName ) ) { -// results = b; -// break; -// } -// } -// } -// -// return results; -// } public boolean hasBlock( String blockName ) { - boolean results = false; - - if ( blockName != null && !blockName.trim().isEmpty() ) { - - results = getPrisonBlock( blockName ) != null; - } + boolean results = false; + + if ( blockName != null && !blockName.trim().isEmpty() ) { + + results = getPrisonBlock( blockName ) != null; + } return results; } -// public boolean incrementBlockMiningCount( Block block ) { -// boolean results = false; -// -// String blockName = block.getPrisonBlock().getBlockName().toLowerCase(); -// -// // Need to always get the target block so it can be marked as counted: -// MineTargetPrisonBlock targetPrisonBlock = getTargetPrisonBlock( block ); -// -// if ( targetPrisonBlock != null && targetPrisonBlock.isAirBroke() ) { -// // If this targetPrisonBlock was originally air or already counted -// // then skip so it is not double counted: -// results = false; -// } -// else if ( targetPrisonBlock != null ){ -// -// // If the block is AIR get the original block name: -// if ( block.getPrisonBlock().isAir() ) { -// -// String targetBlockName = targetPrisonBlock.getPrisonBlock().getBlockName(); -// blockName = targetBlockName; -// } -// -//// Output.get().logInfo( "#### MineData.incrementBlockCount: " + -//// "oBlock= AIR tBlock= %s target= [%s]", blockName, -//// (targetPrisonBlock == null ? "null" : targetPrisonBlock.toString())); -// -// // Set the targetPrisonBlock's airBroke to true to indicate it is being -// // counted during this transaction so it won't be counted again: -// targetPrisonBlock.setAirBroke( true ); -// -// results = incrementBlockMiningCount( blockName ); -// } -// -// return results; -// } - -// public boolean incrementBlockMiningCount( BlockOld block ) { -// String blockName = block.getType().name().toLowerCase(); -// return incrementBlockMiningCount( blockName ); -// } - - - - // MineTargetPrisonBlock getTargetPrisonBlock( Block block ) - -// /** -// *

    This function is not as obvious it appears. Basically when this function -// * should be called, it may be too late to get the correct block value before -// * it is lost (set to AIR). So it is critical that getTargetPrisonBlockName( Block block ) -// * is called first before the original block is processed (broke or auto picked up). -// *

    -// * -// *

    The end result of calling getTargetPrisonBlockName( Block block ) first is that -// * the block name will have already been resolved to the correct original block name. -// * There is also a higher chance that the block name extracted then, may never -// * be AIR to begin with. -// *

    -// * -// *

    Keep in mind, that if the original block was AIR before being processed for -// * a natural break, or auto pickup, then it may not have been properly mined since -// * AIR cannot be mined. That said, if another process intercepted prison's -// * event handlers, then the targetBlocks will not exist until the mine is reset -// * for the first time when the server starts up. So server startups will -// * have higher risk of not being able to resolve the correct block type to -// * report. -// *

    -// * -// * @param blockName -// * @return -// */ -// private boolean incrementBlockMiningCount( String targetBlockName ) { -// boolean results = false; -// -// incrementBlockBreakCount(); -// incrementTotalBlocksMined(); -// -// PrisonBlockStatusData sBlock = getBlockStats( targetBlockName ); -// if ( sBlock != null ) { -// -// sBlock.incrementMiningBlockCount(); -// } -// -// return results; -// } /** *

    This is actually the more correct way to count a block that has been mined @@ -703,112 +573,100 @@ public boolean hasBlock( String blockName ) { * @param targetPrisonBlock */ public boolean incrementBlockMiningCount( MineTargetPrisonBlock targetPrisonBlock ) { - boolean results = false; - - // Only count the block as being broke if it was not originally air and - // and it has not been broke before. - - // NOTE: setAirBroke() and setMined() will be set to true if the mine reset - // places an air block. That will prevent the air from being processed. - if ( targetPrisonBlock != null && !targetPrisonBlock.isCounted() ) { - - targetPrisonBlock.setAirBroke( true ); - targetPrisonBlock.setCounted( true ); - - // The field isMined() is used to "reserve" a block to indicate that it is in - // the stages of being processed, since much later in the processing will the - // block be set to setAirBreak() or even setCounted(). This prevents - // high-speed or concurrent operations from multiple players from trying to - // process the same block. So set it to true here, if it has not already - // been set. - if ( !targetPrisonBlock.isMined() ) { - - targetPrisonBlock.setMined( true ); - } - - incrementBlockBreakCount(); - incrementTotalBlocksMined(); - - if ( targetPrisonBlock.getPrisonBlock() != null ) { - - targetPrisonBlock.getPrisonBlock().incrementMiningBlockCount(); - } - - results = true; - } - - return results; + boolean results = false; + + // Only count the block as being broke if it was not originally air and + // and it has not been broke before. + + // NOTE: setAirBroke() and setMined() will be set to true if the mine reset + // places an air block. That will prevent the air from being processed. + if ( targetPrisonBlock != null && !targetPrisonBlock.isCounted() ) { + + targetPrisonBlock.setAirBroke( true ); + targetPrisonBlock.setCounted( true ); + + // The field isMined() is used to "reserve" a block to indicate that it is in + // the stages of being processed, since much later in the processing will the + // block be set to setAirBreak() or even setCounted(). This prevents + // high-speed or concurrent operations from multiple players from trying to + // process the same block. So set it to true here, if it has not already + // been set. + if ( !targetPrisonBlock.isMined() ) { + + targetPrisonBlock.setMined( true ); + } + + incrementBlockBreakCount(); + incrementTotalBlocksMined(); + + if ( targetPrisonBlock.getPrisonBlock() != null ) { + + targetPrisonBlock.getPrisonBlock().incrementMiningBlockCount(); + } + + results = true; + } + + return results; } -// public void incrementBlockMiningCount( Block block ) { -// -// MineTargetPrisonBlock targetBlock = getTargetPrisonBlock( block ); -// incrementBlockMiningCount( targetBlock ); -// -// } - abstract public MineTargetPrisonBlock getTargetPrisonBlock( PrisonBlock block ); -// abstract public String getTargetPrisonBlockName( Block block ); abstract public boolean checkZeroBlockReset(); public boolean hasUnsavedBlockCounts() { - return getUnsavedBlockCount() > 0; + return getUnsavedBlockCount() > 0; } public long getUnsavedBlockCount() { - long results = 0; - - for ( PrisonBlockStatusData blockStats : getBlockStats().values() ) { - results += blockStats.getBlockCountUnsaved(); - } - - return results; + long results = 0; + + for ( PrisonBlockStatusData blockStats : getBlockStats().values() ) { + results += blockStats.getBlockCountUnsaved(); + } + + return results; } public void resetUnsavedBlockCounts() { - for ( PrisonBlockStatusData blockStats : getBlockStats().values() ) { - // Since the mine was just saved reset the unsaved value : - blockStats.setBlockCountUnsaved( 0 ); - - // Reset the block count for the reset event since the mine will be regenerated: - blockStats.setBlockPlacedCount( 0 ); - } + for ( PrisonBlockStatusData blockStats : getBlockStats().values() ) { + // Since the mine was just saved reset the unsaved value : + blockStats.setBlockCountUnsaved( 0 ); + + // Reset the block count for the reset event since the mine will be regenerated: + blockStats.setBlockPlacedCount( 0 ); + } } public void resetResetBlockCounts() { - for ( PrisonBlockStatusData block : getBlocks() ) { - - // Reset the block count for the reset event since the mine will be regenerated: - block.setBlockPlacedCount( 0 ); - block.setRangeBlockCountLow( -1 ); - block.setRangeBlockCountHigh( -1 ); - block.setRangeBlockCountLowLimit( -1 ); - block.setRangeBlockCountHighLimit( -1 ); -// block.setIncludeInLayerCalculations( true ); - } +// for ( PrisonBlockStatusData block : getBlocks() ) { +// +// // Reset the block count for the reset event since the mine will be regenerated: +// block.setBlockPlacedCount( 0 ); +// block.setRangeBlockCountLow( -1 ); +// block.setRangeBlockCountHigh( -1 ); +// block.setRangeBlockCountLowLimit( -1 ); +// block.setRangeBlockCountHighLimit( -1 ); +// // block.setIncludeInLayerCalculations( true ); +// } + + for ( PrisonBlockStatusData block : getPrisonBlocks() ) { + + // Reset the block count for the reset event since the mine will be regenerated: + block.setBlockPlacedCount( 0 ); + block.setRangeBlockCountLow( -1 ); + block.setRangeBlockCountHigh( -1 ); + block.setRangeBlockCountLowLimit( -1 ); + block.setRangeBlockCountHighLimit( -1 ); + // block.setIncludeInLayerCalculations( true ); + } - for ( PrisonBlockStatusData block : getPrisonBlocks() ) { - - // Reset the block count for the reset event since the mine will be regenerated: - block.setBlockPlacedCount( 0 ); - block.setRangeBlockCountLow( -1 ); - block.setRangeBlockCountHigh( -1 ); - block.setRangeBlockCountLowLimit( -1 ); - block.setRangeBlockCountHighLimit( -1 ); -// block.setIncludeInLayerCalculations( true ); - } - -// for ( PrisonBlockStatusData blockStats : getBlockStats().values() ) { -// // Reset the block count for the reset event since the mine will be regenerated: -// blockStats.setResetBlockCount( 0 ); -// } } /** @@ -819,118 +677,102 @@ public void resetResetBlockCounts() { * @param statsBlock */ public PrisonBlockStatusData incrementResetBlockCount( PrisonBlockStatusData statsBlock ) { - - PrisonBlockStatusData sBlock = null; - - if ( statsBlock != null ) { - sBlock = getBlockStats( statsBlock ); - - if ( sBlock != null ) { - - sBlock.incrementResetBlockCount(); - } - } - - return sBlock; + + PrisonBlockStatusData sBlock = null; + + if ( statsBlock != null ) { + sBlock = getBlockStats( statsBlock ); + + if ( sBlock != null ) { + + sBlock.incrementResetBlockCount(); + } + } + + return sBlock; } public PrisonBlockStatusData getBlockStats( PrisonBlockStatusData statsBlock ) { - return getBlockStats( statsBlock.getBlockName() ); + return getBlockStats( statsBlock.getBlockName() ); } public PrisonBlockStatusData getBlockStats( String blockName ) { - PrisonBlockStatusData results = null; - - if ( blockName != null && !blockName.trim().isEmpty() ) { - - if ( !getBlockStats().containsKey( blockName ) ) { - - for ( PrisonBlock block : getPrisonBlocks() ) { - if ( block.getBlockName().equalsIgnoreCase( blockName ) ) { - getBlockStats().put( block.getBlockName(), block ); - - results = block; - break; - } - } - - } - else { - - results = getBlockStats().get( blockName ); - } - } - - return results; + PrisonBlockStatusData results = null; + + if ( blockName != null && !blockName.trim().isEmpty() ) { + + if ( !getBlockStats().containsKey( blockName ) ) { + + for ( PrisonBlock block : getPrisonBlocks() ) { + if ( block.getBlockName().equalsIgnoreCase( blockName ) ) { + getBlockStats().put( block.getBlockName(), block ); + + results = block; + break; + } + } + + } + else { + + results = getBlockStats().get( blockName ); + } + } + + return results; } - public TreeMap getBlockStats() { + public TreeMap getBlockStats() { return blockStats; } public boolean isInMineExact(Location location) { - if ( isVirtual() ) { - return false; - } - return getBounds().within(location); + + return !isVirtual() && getBounds().within(location); } public boolean isInMineIncludeTopBottomOfMine(Location location) { - if ( isVirtual() ) { - return false; - } - return getBounds().withinIncludeTopBottomOfMine( location ); + if ( isVirtual() ) { + return false; + } + return getBounds().withinIncludeTopBottomOfMine( location ); } - // Obsolete... the old block model: -// public boolean isInMine(BlockType blockType) { -// //TODO Not sure if virtual should return false... they do have blocks. -//// if ( isVirtual() ) { -//// return false; -//// } -// for (BlockOld block : getBlocks()) { -// if (blockType == block.getType()) { -// return true; -// } -// } -// return false; -// } - public boolean isInMine(PrisonBlock blockType) { - //TODO Not sure if virtual should return false... they do have blocks. - if ( isVirtual() ) { - return false; - } - for (PrisonBlock block : getPrisonBlocks()) { - if (blockType.getBlockNameFormal().equalsIgnoreCase( block.getBlockNameFormal())) { - return true; - } - } - return false; + //TODO Not sure if virtual should return false... they do have blocks. + if ( isVirtual() ) { + return false; + } + for (PrisonBlock block : getPrisonBlocks()) { + if (blockType.getBlockNameFormal().equalsIgnoreCase( block.getBlockNameFormal())) { + return true; + } + } + return false; } public PrisonBlock getPrisonBlock( PrisonBlock blockType ) { - PrisonBlock results = null; - - if ( blockType != null && blockType.getBlockNameFormal() != null ) { - - for (PrisonBlock block : getPrisonBlocks()) { - if ( block.getBlockNameFormal().equalsIgnoreCase( blockType.getBlockNameFormal() )) { - results = block; - break; - } - } - } - - return results; + PrisonBlock results = null; + + if ( blockType != null && blockType.getBlockNameFormal() != null ) { + + for (PrisonBlock block : getPrisonBlocks()) { + if ( block.getBlockNameFormal().equalsIgnoreCase( blockType.getBlockNameFormal() )) { + results = block; + break; + } + } + } + + return results; } public double area() { - if ( isVirtual() ) { - return 0; - } + if ( isVirtual() ) { + return 0; + } return getBounds().getArea(); } @@ -962,18 +804,18 @@ public double area() { * @return */ public boolean hasTPAccess( Player player ) { - boolean results = false; - - String minePermission = "mines.tp." + getName().toLowerCase(); - - if ( isTpAccessByRank() && Prison.get().getPlatform().isMineAccessibleByRank( player, this ) || - player.hasPermission("mines.tp") || - !isTpAccessByRank() && player.hasPermission( minePermission ) ) { - - results = true; - } - - return results; + boolean results = false; + + String minePermission = "mines.tp." + getName().toLowerCase(); + + if ( isTpAccessByRank() && Prison.get().getPlatform().isMineAccessibleByRank( player, this ) || + player.hasPermission("mines.tp") || + !isTpAccessByRank() && player.hasPermission( minePermission ) ) { + + results = true; + } + + return results; } /** @@ -1004,25 +846,81 @@ public boolean hasTPAccess( Player player ) { * @return */ public boolean hasMiningAccess( Player player ) { - boolean results = false; - - if ( isMineAccessByRank() && - Prison.get().getPlatform().isMineAccessibleByRank( player, this ) || - !isMineAccessByRank() && - isAccessPermissionEnabled() && player.hasPermission( getAccessPermission() ) - - /// Note: the following cannot be added here since it will grant access if both are disabled - // || !isMineAccessByRank() && !isAccessPermissionEnabled() - ) { - - results = true; - } - - return results; + boolean results = false; + + StringBuilder dbug = new StringBuilder(); + boolean isDebug = Output.get().isDebug(); + + // The mine setting: + boolean isAccessByRank = isMineAccessByRank(); + + dbug.append( "&3## hasMineAccess: mineAccessByRank: [" ) + .append( getName() ).append( " " ) + .append( isAccessByRank ).append( "] " ); + /// Note: the following cannot be added here since it will grant access if both are disabled + // || !isMineAccessByRank() && !isAccessPermissionEnabled() + + if ( isAccessByRank ) { + + if ( Prison.get().getPlatform().isMineAccessibleByRank( player, this ) ) { + + dbug.append( "Success!" ); + results = true; + } + else { + String mineRank = getRank().getName(); + + if ( isDebug ) { + + dbug.append( "&cFailed! &aPlayer does not have access based upon their rank. " ) + .append( "mineRank: " ).append( mineRank ); + + + } + } + + + } + else { + + dbug.append( " accessByPerms: " ).append( isAccessPermissionEnabled() ); + + if ( isAccessPermissionEnabled() ) { + + if ( player.hasPermission( getAccessPermission() )) { + + dbug.append( "Success!" ); + results = true; + } + else { + dbug.append( "&cFailed! &aPlayer does not have access based upon the permission: [" ) + .append( getAccessPermission() == null ? "null" : getAccessPermission() ); + } + } + else { + + dbug.append( " &cFailed! &aMust have either accessByRank or accessByPerm enabled. " ); + } + + } + + if ( isDebug ) { + String setting = Prison.get().getPlatform().getConfigString( "prison-mines.access-to-prior-mines" ); + if ( setting != null ) { + dbug.append( "Config.yml: prison-mines.access-to-prior-mines: " ).append( setting.trim() ); + + } + } + + if ( isDebug ) { + Output.get().logInfo( dbug.toString() ); + } + + return results; } public boolean isAccessPermissionEnabled() { - return accessPermission != null && !accessPermission.trim().isEmpty(); + return accessPermission != null && !accessPermission.trim().isEmpty(); } public String getAccessPermission() { return accessPermission; @@ -1032,6 +930,13 @@ public void setAccessPermission( String accessPermission ) { } + public int getDataVersion() { + return dataVersion; + } + public void setDataVersion(int dataVersion) { + this.dataVersion = dataVersion; + } + public MineType getMineType() { return mineType; } @@ -1067,7 +972,7 @@ public void setMineAccessByRank( boolean mineAccessByRank ) { * world can't be found */ public Location getSpawn() { - return spawn; + return spawn; } /** @@ -1077,11 +982,11 @@ public Location getSpawn() { * @return this instance for chaining */ public void setSpawn(Location location) { - // cannot set spawn when virtual: - if ( !isVirtual() ) { - hasSpawn = (location != null); - spawn = location; - } + // cannot set spawn when virtual: + if ( !isVirtual() ) { + hasSpawn = (location != null); + spawn = location; + } } public boolean isHasSpawn() { @@ -1145,7 +1050,7 @@ public void setUseNotificationPermission( boolean useNotificationPermission ) { } public String getMineNotificationPermissionName() { - return MINE_NOTIFICATION_PERMISSION_PREFIX + getName().toLowerCase(); + return Mine.MINE_NOTIFICATION_PERMISSION_PREFIX + getName().toLowerCase(); } /** @@ -1271,13 +1176,6 @@ public void setResetCommands( List resetCommands ) { this.resetCommands = resetCommands; } -// public boolean isUsePagingOnReset() { -// return usePagingOnReset; -// } -// public void setUsePagingOnReset( boolean usePagingOnReset ) { -// this.usePagingOnReset = usePagingOnReset; -// } - public ModuleElement getRank() { return rank; } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLevelBlockListData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLevelBlockListData.java index 6ffe17b7b..4e8490dd6 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLevelBlockListData.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineLevelBlockListData.java @@ -219,9 +219,6 @@ public PrisonBlock randomlySelectPrisonBlock() for ( PrisonBlock block : selectedBlocks ) { - // NOTE: do not have use this field anymore: -// block.isIncludeInLayerCalculations(); - // If chance falls on this block, then select it as long as it has not // exceed the max count for this block if the max constraint is enabled. // If the block's constraint max is reached, then isIncludedInLayerCalculation will @@ -247,8 +244,6 @@ public PrisonBlock randomlySelectPrisonBlock() selected.getConstraintMax() > 0 && (selected.getBlockPlacedCount() + 1) >= selected.getConstraintMax() ) { -// selected.setIncludeInLayerCalculations( false ); - selectedBlocks.remove(selected); selectedChance -= selected.getChance(); 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 e7dda5f87..1ef1e9525 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 @@ -91,53 +91,47 @@ public abstract class MineReset public static final long MINE_RESET__PAGE_TIMEOUT_CHECK__BLOCK_COUNT = 250; - public static final long MINE_RESET__AIR_COUNT_BASE_DELAY = 30000L; // 30 seconds + // NOTE: Longer delay on air counts will not prevent the "server is running behind" messages. + public static final long MINE_RESET__AIR_COUNT_BASE_DELAY_TICKS = 10 * 20L; // 10 seconds + public static final long MINE_RESET__AIR_COUNT_SUBMIT_GAP_TICKS = 10; // 10 ticks == 0.5 second - private List mineTargetPrisonBlocks = null; - private TreeMap mineTargetPrisonBlocksMap = null; + private transient List mineTargetPrisonBlocks = null; + private transient TreeMap mineTargetPrisonBlocksMap = null; - private MineJob currentJob; + private transient MineJob currentJob; - private int resetPage = 0; - private int resetPosition = 0; + private transient int resetPage = 0; + private transient int resetPosition = 0; - private long resetPageMaxPageElapsedTimeMs = -1; - private long resetPagePageSubmitDelayTicks = -1; - private long resetPageTimeoutCheckBlockCount = -1; + private transient long resetPageMaxPageElapsedTimeMs = -1; + private transient long resetPagePageSubmitDelayTicks = -1; + private transient long resetPageTimeoutCheckBlockCount = -1; - private int airCountOriginal = 0; - private int airCount = 0; - private long airCountTimestamp = 0L; - private long airCountElapsedTimeMs = 0L; + private transient int airCountOriginal = 0; + private transient int airCount = 0; + private transient long airCountTimestamp = 0L; + private transient long airCountElapsedTimeMs = 0L; - private long statsResetTimeMS = 0; - private long statsBlockGenTimeMS = 0; - private long statsBlockUpdateTimeMS = 0; - private long statsBlockUpdateTimeNanos = 0; + private transient long statsResetTimeMS = 0; + private transient long statsBlockGenTimeMS = 0; + private transient long statsBlockUpdateTimeMS = 0; + private transient long statsBlockUpdateTimeNanos = 0; - // Note: The time it takes to teleport players and broadcast is so trivial - // that they are being disabled to reduce the clutter and memory load. -// private long statsTeleport1TimeMS = 0; -// private long statsTeleport2TimeMS = 0; -// private long statsMessageBroadcastTimeMS = 0; - private int statsResetPages = 0; - private long statsResetPageBlocks = 0; - private long statsResetPageMs = 0; + private transient int statsResetPages = 0; + private transient long statsResetPageBlocks = 0; + private transient long statsResetPageMs = 0; - private List statsMineSweeperTaskMs; - private boolean mineSweeperSubmitted = false; + private transient List statsMineSweeperTaskMs; + private transient boolean mineSweeperSubmitted = false; public MineReset() { super(); -// this.mineTargetPrisonBlocks = new ArrayList<>(); -// this.mineTargetPrisonBlocksMap = new TreeMap<>(); - this.statsMineSweeperTaskMs = new ArrayList<>(); this.currentJob = null; @@ -157,270 +151,94 @@ public MineReset() { */ @Override protected void initialize() { - super.initialize(); - - if ( !isVirtual() ) { - - // Once the mine has been loaded, MUST get a count of all air blocks. - refreshBlockBreakCountUponStartup( 0 ); - } + super.initialize(); + + if ( !isVirtual() ) { + + // Once the mine has been loaded, MUST get a count of all air blocks. + refreshBlockBreakCountUponStartup( 0 ); + } } -// /** -// *

    Optimized the mine reset to focus on itself. Also set the Y plane to refresh at the top and work its -// * way down. That way if the play is teleported to the top, it will appear like the whole mine has reset -// * instantly and they will not see the delay from the bottom of the mine working up to the top. This will -// * also reduce the likelihood of the player falling back in to the mine if there is no spawn set. -// *

    -// * -// *

    The ONLY code that could be asynchronous ran is the random generation of the blocks. The other -// * lines of code is using bukkit and/or spigot api calls which MUST be ran synchronously. -// *

    -// */ -// protected void resetSynchonously() { -// -// if ( isDeleted() ) { -// // if the mine is deleted, just return without doing anything. This will -// // cancel the job. -// return; -// } -// -// long start = System.currentTimeMillis(); -// -// // The all-important event -// MineResetEvent event = new MineResetEvent(this, resetType); -// Prison.get().getEventBus().post(event); -// if (!event.isCanceled()) { -// resetSynchonouslyInternal(); -// } -// -// long stop = System.currentTimeMillis(); -// setStatsResetTimeMS( stop - start ); -// -// // Tie to the command stats mode so it logs it if stats are enabled: -// if ( PrisonMines.getInstance().getMineManager().isMineStats() ) { -// DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); -// Output.get().logInfo("&cMine reset: &7" + getTag() + -// "&c Blocks: &7" + dFmt.format( getBounds().getTotalBlockCount() ) + -// statsMessage() ); -// } -// -// } - -// /** -// *

    This function now follows the general behavior as the async reset in that it now -// * uses a target block listing to help ensure the constraints are honored when -// * generating the blocks. -// *

    -// * -// */ -// private void resetSynchonouslyInternal() { -// try { -// -// if ( isVirtual() || isDeleted() ) { -// // Mine is virtual and cannot be reset. Just skip this with no error messages. -// // If the mine is deleted, just return without doing anything. -// return; -// } -// -// if ( !isEnabled() ) { -// Output.get().logError( -// String.format( "MineReset: Reset failure: Mine is not enabled. " + -// "Ensure world exists. mine= %s ", -// getName() )); -// return; -// } -// -// -// teleportAllPlayersOut(); -//// setStatsTeleport1TimeMS( -//// teleportAllPlayersOut( getBounds().getyBlockMax() ) ); -// -// -// // Reset stats: -// resetStats(); -// -// -// generateBlockListAsync(); -// -// -// if ( !getCurrentJob().getResetActions().contains( MineResetActions.NO_COMMANDS )) { -// -// // Before reset commands: -// if ( getResetCommands() != null && getResetCommands().size() > 0 ) { -// -// List cmdTasks = new ArrayList<>(); -// -// int row = 0; -// for (String command : getResetCommands() ) { -// row++; -//// String formatted = cmd.replace("{player}", prisonPlayer.getName()) -//// .replace("{player_uid}", player.uid.toString()); -// if ( command.startsWith( "before: " )) { -// String cmd = command.replace( "before: ", "" ); -// -// String debugInfo = "MineReset sync: " + getName() + " Before:"; -// PrisonCommandTaskData cmdTask = new PrisonCommandTaskData( -// debugInfo, cmd, row ); -// -// cmdTasks.add( cmdTask ); -//// PrisonCommandTasks.submitTasks( cmdTask ); -// //PrisonAPI.dispatchCommand(cmd); -// } -// } -// -// PrisonCommandTasks.submitTasks( cmdTasks ); -// } -// } -// -// -// MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal ); -// resetTask.submitTaskAsync(); -//// resetAsynchonouslyUpdate( false ); -// -// -// -// // If a player falls back in to the mine before it is fully done being reset, -// // such as could happen if there is lag or a lot going on within the server, -// // this will TP anyone out who would otherwise suffocate. I hope! lol -// teleportAllPlayersOut(); -//// setStatsTeleport2TimeMS( -//// teleportAllPlayersOut( getBounds().getyBlockMax() ) ); -// -// -// incrementResetCount(); -// -// if ( !getCurrentJob().getResetActions().contains( MineResetActions.NO_COMMANDS )) { -// -// // After reset commands: -// if ( getResetCommands() != null && getResetCommands().size() > 0 ) { -// -// List cmdTasks = new ArrayList<>(); -// -// int row = 0; -// for (String command : getResetCommands() ) { -// row++; -//// String formatted = cmd.replace("{player}", prisonPlayer.getName()) -//// .replace("{player_uid}", player.uid.toString()); -// if ( command.startsWith( "after: " )) { -// String cmd = command.replace( "after: ", "" ); -// -// String debugInfo = "MineReset sync: " + getName() + " After:"; -// PrisonCommandTaskData cmdTask = new PrisonCommandTaskData( -// debugInfo, cmd, row ); -// -// cmdTasks.add( cmdTask ); -// } -// } -// -// PrisonCommandTasks.submitTasks( cmdTasks ); -// } -// } -// -// -// // Broadcast message to all players within a certain radius of this mine: -// broadcastResetMessageToAllPlayersWithRadius(); -//// broadcastResetMessageToAllPlayersWithRadius( MINE_RESET__BROADCAST_RADIUS_BLOCKS ); -// -// -// submitTeleportGlassBlockRemoval(); -// -// -// // If part of a chained_resets, then kick off the next reset: -// if ( getCurrentJob().getResetActions().contains( MineResetActions.CHAINED_RESETS )) { -// -// PrisonMines pMines = PrisonMines.getInstance(); -// pMines.resetAllMinesNext(); -// } -// -// -// } catch (Exception e) { -// Output.get().logError("&cFailed to reset mine " + getName(), e); -// } -// } - public String statsMessage() { - StringBuilder sb = new StringBuilder(); - DecimalFormat dFmt = Prison.get().getDecimalFormatDouble(); - DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); - - sb.append( "&3 ResetTime: &7" ); - sb.append( dFmt.format(getStatsResetTimeMS() / 1000.0d )).append( " s " ); - - sb.append( "&3 BlockGenTime: &7" ); - sb.append( dFmt.format(getStatsBlockGenTimeMS() / 1000.0d )).append( " s " ); - - - sb.append( "&3 BlockUpdateTime: &7" ); - sb.append( dFmt.format(getStatsBlockUpdateTimeMS() / 1000.0d )).append( " s " ); - sb.append( dFmt.format(getStatsBlockUpdateTimeNanos() / 1000000.0d )).append( " ms(nanos) " ); - - - sb.append( "&3 ResetPages: &7" ); - sb.append( iFmt.format(getStatsResetPages() )); - - double avgBlocks = getStatsResetPages() == 0 ? 0 : - getStatsResetPageBlocks() / getStatsResetPages(); - double avgMs = getStatsResetPages() == 0 ? 0 : - getStatsResetPageMs() / getStatsResetPages(); - - sb.append( "&3 avgBlocksPerPage: &7" ); - sb.append( dFmt.format(avgBlocks)); - - sb.append( "&3 avgMsPerPage: &7" ); - sb.append( dFmt.format(avgMs)); - - sb.append( statsMessageMineSweeper() ); - -// sb.append( " TPS: " ) -// .append( Prison.get().getPrisonTPS().getAverageTPSFormatted() ); - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + DecimalFormat dFmt = Prison.get().getDecimalFormatDouble(); + DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); + + sb.append( "&3 ResetTime: &7" ); + sb.append( dFmt.format(getStatsResetTimeMS() / 1000.0d )).append( " s " ); + + sb.append( "&3 BlockGenTime: &7" ); + sb.append( dFmt.format(getStatsBlockGenTimeMS() / 1000.0d )).append( " s " ); + + + sb.append( "&3 BlockUpdateTime: &7" ); + sb.append( dFmt.format(getStatsBlockUpdateTimeMS() / 1000.0d )).append( " s " ); + sb.append( dFmt.format(getStatsBlockUpdateTimeNanos() / 1000000.0d )).append( " ms(nanos) " ); + + + sb.append( "&3 ResetPages: &7" ); + sb.append( iFmt.format(getStatsResetPages() )); + + double avgBlocks = getStatsResetPages() == 0 ? 0 : + getStatsResetPageBlocks() / getStatsResetPages(); + double avgMs = getStatsResetPages() == 0 ? 0 : + getStatsResetPageMs() / getStatsResetPages(); + + sb.append( "&3 avgBlocksPerPage: &7" ); + sb.append( dFmt.format(avgBlocks)); + + sb.append( "&3 avgMsPerPage: &7" ); + sb.append( dFmt.format(avgMs)); + + sb.append( statsMessageMineSweeper() ); + + // sb.append( " TPS: " ) + // .append( Prison.get().getPrisonTPS().getAverageTPSFormatted() ); + + return sb.toString(); } public String statsMessageMineSweeper() { - StringBuilder sb = new StringBuilder(); - - if ( getStatsMineSweeperTaskMs().size() > 0 ) { - sb.append( " &3 MineSweeper ms: " ); - - for ( Long sweepMs : getStatsMineSweeperTaskMs() ) { - sb.append( sweepMs ).append( " " ); - } - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + if ( getStatsMineSweeperTaskMs().size() > 0 ) { + sb.append( " &3 MineSweeper ms: " ); + + for ( Long sweepMs : getStatsMineSweeperTaskMs() ) { + sb.append( sweepMs ).append( " " ); + } + } + + return sb.toString(); } private void resetStats() { - setResetPage( 0 ); - - setBlockBreakCount( 0 ); - - // The reset position is critical in ensuring that all blocks within the mine are reset - // and that when a reset process pages (allows another process to run) then it will be - // used to pick up where it left off. - setResetPosition( 0 ); - - setSkipResetBypassCount( 0 ); - - // NOTE: DO NOT reset blockBreakCount here! Players can break many blocks between - // here and when the mine actually starts to reset. - - setAirCountOriginal( 9 ); - setAirCount( 0 ); - - setStatsResetTimeMS( 0 ); - setStatsBlockGenTimeMS( 0 ); - setStatsBlockUpdateTimeMS( 0 ); - setStatsBlockUpdateTimeNanos( 0 ); -// setStatsTeleport1TimeMS( 0 ); -// setStatsTeleport2TimeMS( 0 ); -// setStatsMessageBroadcastTimeMS( 0 ); - - setStatsResetPages( 0 ); - setStatsResetPageBlocks( 0 ); + setResetPage( 0 ); + + setBlockBreakCount( 0 ); + + // The reset position is critical in ensuring that all blocks within the mine are reset + // and that when a reset process pages (allows another process to run) then it will be + // used to pick up where it left off. + setResetPosition( 0 ); + + setSkipResetBypassCount( 0 ); + + // NOTE: DO NOT reset blockBreakCount here! Players can break many blocks between + // here and when the mine actually starts to reset. + + setAirCountOriginal( 9 ); + setAirCount( 0 ); + + setStatsResetTimeMS( 0 ); + setStatsBlockGenTimeMS( 0 ); + setStatsBlockUpdateTimeMS( 0 ); + setStatsBlockUpdateTimeNanos( 0 ); + + setStatsResetPages( 0 ); + setStatsResetPageBlocks( 0 ); setStatsResetPageMs( 0 ); @@ -462,12 +280,8 @@ public void saveIfUnsavedBlockCounts() { * * @param callbackAsync */ -// public abstract int submitAsyncTask( PrisonRunnable callbackAsync ); - public abstract int submitAsyncTask( PrisonRunnable callbackAsync, long delay ); -// public abstract int submitSyncTask( PrisonRunnable callbackSync ); - public abstract int submitSyncTask( PrisonRunnable callbackSync, long delay ); @@ -530,10 +344,11 @@ public int getPlayerCount() { */ public void generateBlockListAsync() { - if ( isVirtual() || isDeleted() ) { - // ignore and generate no error messages: - return; - } + if ( isVirtual() || isDeleted() ) { + // ignore and generate no error messages: + return; + } + if ( !isEnabled() ) { Output.get().logError( String.format( "MineReset: Block count failure: Mine is not enabled. " + @@ -541,8 +356,8 @@ public void generateBlockListAsync() { getName() )); return; } - - long start = System.currentTimeMillis(); + + long start = System.currentTimeMillis(); // Reset stats: resetStats(); @@ -557,9 +372,6 @@ public void generateBlockListAsync() { resetResetBlockCounts(); -// // setup the monitoring of the blocks that have constraints: -// List constrainedBlocks = null; - Optional worldOptional = getWorld(); World world = worldOptional.get(); @@ -610,10 +422,6 @@ public void generateBlockListAsync() { targetLocation.setEdge( isEdge ); targetLocation.setCorner( isCorner ); -// MineTargetBlock mtb = null; - - // track the constraints: (obsolete) - //trackConstraints( currentLevel, constrainedBlocks ); PrisonBlock prisonBlock = mineLevelBlockList.randomlySelectPrisonBlock(); @@ -621,17 +429,15 @@ public void generateBlockListAsync() { prisonBlock = PrisonBlock.AIR.clone(); } -// PrisonBlock prisonBlock = randomlySelectPrisonBlock( random, currentLevel ); // Increment the mine's block count. This block is one of the control blocks: incrementResetBlockCount( prisonBlock ); // TODO AIR block fix - allow AIR to be part of the regular block list? addMineTargetPrisonBlock( prisonBlock, targetLocation ); -// mtb = new MineTargetPrisonBlock( prisonBlock, x, y, z); - if ( prisonBlock.equals( PrisonBlock.AIR ) ) { -// mAirBlocks[i++] = true; + if ( prisonBlock.isAir() ) { + airCount++; } @@ -652,7 +458,6 @@ public void generateBlockListAsync() { if ( Output.get().isDebug() && Output.get().isSelectiveTarget( DebugTarget.blockConstraints ) ) { DecimalFormat dFmt = Prison.get().getDecimalFormatDouble(); - //DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); for ( PrisonBlockStatusData b : getPrisonBlocks() ) { @@ -690,517 +495,155 @@ public void generateBlockListAsync() { } -// private void trackConstraints( int currentLevel, List constrainedBlocks ) -// { -// -// // If the constrainedBlocks list has not be configured, set it up with the -// // blocks that have constraints: -// if ( constrainedBlocks == null ) { -// -// constrainedBlocks = new ArrayList<>(); -// -// for (PrisonBlock block : getPrisonBlocks()) { -// if ( block.getConstraintExcludeTopLayers() > 0 || -// block.getConstraintExcludeBottomLayers() > 0 ) { -// -// constrainedBlocks.add( block ); -// } -// } -// } -// -// -// // If there are any constrained blocks, then need to record -// for ( PrisonBlockStatusData block : constrainedBlocks ) { -// -// // If exclude top layers is enabled, then only try to set the -// // rangeBlockCountLowLimit once since we need the lowest possible -// // value. The inital value for getRangeBlockCountLowLimit is -1. -// if ( block.getConstraintExcludeTopLayers() > 0 && -// block.getRangeBlockCountLowLimit() <= 0 && -// currentLevel > block.getConstraintExcludeTopLayers() ) { -// -// int targetBlockPosition = getMineTargetPrisonBlocks().size(); -// block.setRangeBlockCountLowLimit( targetBlockPosition ); -// } -// -// // If exclude bottom layer is enabled, then we need to track every number -// // until the currentLevel exceeds the getConstraintExcludeBottomLayers value. -// // If exclude top layers, then do not record for the bottom layers until -// // the top layers is cleared. -// if ( (block.getConstraintExcludeTopLayers() > 0 && -// currentLevel > block.getConstraintExcludeTopLayers() || -// block.getConstraintExcludeTopLayers() == 0) && -// -// block.getConstraintExcludeBottomLayers() > 0 && -// block.getConstraintExcludeBottomLayers() < currentLevel -// ) { -// -// int targetBlockPosition = getMineTargetPrisonBlocks().size(); -// block.setRangeBlockCountHighLimit( targetBlockPosition ); -// -// } -// } -// -// } - -// /** -// * -// *

    Update 2021-08-25 : This function should only be called once now. The main -// * work on performing the actual resets is now performed within the task -// * MinePagedResetAsyncTask. This is now to be ran asynchronously. -// *

    -// * -// *

    Yeah I know, it has async in the name of the function, but it still can only -// * be ran synchronously. The async part implies this is the reset "part" for the -// * async workflow. -// *

    -// * -// *

    Before this part is ran, the generateBlockListAsync() function must be ran -// * to regenerate the new block list. -// *

    -// * -// */ -// protected void resetAsynchonously() { -// boolean canceled = false; -// -//// Output.get().logInfo( "MineRest.resetAsynchonously() " + getName() ); -// -// if ( isVirtual() ) { -// canceled = true; -// } -// -// if ( !canceled && getResetPage() == 0 ) { -// generateBlockListAsync(); -// -// canceled = resetAsynchonouslyInitiate( MineResetType.normal ); -// } -// -// if ( !canceled ) { -// -//// // First time through... reset the block break count and run the before reset commands: -//// if ( getResetPosition() == 0 ) { -//// -//// // Reset the block break count before resetting the blocks: -//// // Set it to the original air count, if subtracted from total block count -//// // in the mine, then the result will be blocks remaining. -//// setBlockBreakCount( getAirCountOriginal() ); -//// -//// -//// if ( !getCurrentJob().getResetActions().contains( MineResetActions.NO_COMMANDS )) { -//// -//// // Before reset commands: -//// if ( getResetCommands() != null && getResetCommands().size() > 0 ) { -//// -//// for (String command : getResetCommands() ) { -////// String formatted = cmd.replace("{player}", prisonPlayer.getName()) -////// .replace("{player_uid}", player.uid.toString()); -//// if ( command.startsWith( "before: " )) { -//// String cmd = command.replace( "before: ", "" ); -//// -//// PrisonCommandTask cmdTask = new PrisonCommandTask( "MineReset: Before:" ); -//// cmdTask.submitCommandTask( cmd ); -//// -//// // PrisonAPI.dispatchCommand(cmd); -//// } -//// } -//// } -//// } -//// -//// } -// -// asynchronouslyResetSetup(); -// -// MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal ); -// resetTask.submitTaskAsync(); -// -// asynchronouslyResetFinalize( null ); -// -// -//// resetAsynchonouslyUpdate( true ); -// -//// if ( getResetPosition() == getMineTargetPrisonBlocks().size() ) { -//// // Done resetting the mine... wrap up: -//// -//// -//// // If a player falls back in to the mine before it is fully done being reset, -//// // such as could happen if there is lag or a lot going on within the server, -//// // this will TP anyone out who would otherwise suffocate. I hope! lol -//// teleportAllPlayersOut(); -////// setStatsTeleport2TimeMS( -////// teleportAllPlayersOut( getBounds().getyBlockMax() ) ); -//// -//// // Reset the paging for the next reset: -//// setResetPage( 0 ); -//// -//// incrementResetCount(); -//// -//// if ( !getCurrentJob().getResetActions().contains( MineResetActions.NO_COMMANDS )) { -//// -//// // After reset commands: -//// if ( getResetCommands() != null && getResetCommands().size() > 0 ) { -//// -//// for (String command : getResetCommands() ) { -////// String formatted = cmd.replace("{player}", prisonPlayer.getName()) -////// .replace("{player_uid}", player.uid.toString()); -//// if ( command.startsWith( "after: " )) { -//// String cmd = command.replace( "after: ", "" ); -//// -//// PrisonCommandTask cmdTask = new PrisonCommandTask( "MineReset: After:" ); -//// cmdTask.submitCommandTask( cmd ); -//// -//// // PrisonAPI.dispatchCommand(cmd); -//// } -//// } -//// } -//// } -//// -//// -//// // Broadcast message to all players within a certain radius of this mine: -//// broadcastResetMessageToAllPlayersWithRadius(); -////// broadcastResetMessageToAllPlayersWithRadius( MINE_RESET__BROADCAST_RADIUS_BLOCKS ); -//// -//// -//// submitTeleportGlassBlockRemoval(); -//// -//// -//// // Tie to the command stats mode so it logs it if stats are enabled: -//// if ( PrisonMines.getInstance().getMineManager().isMineStats() || -//// getCurrentJob().getResetActions().contains( MineResetActions.DETAILS ) ) { -//// DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); -//// Output.get().logInfo("&cMine reset: &7" + getTag() + -//// "&c Blocks: &7" + dFmt.format( getBounds().getTotalBlockCount() ) + -//// statsMessage() ); -//// } -//// -//// // If part of a chained_resets, then kick off the next reset: -//// if ( getCurrentJob().getResetActions().contains( MineResetActions.CHAINED_RESETS )) { -//// -//// PrisonMines pMines = PrisonMines.getInstance(); -//// pMines.resetAllMinesNext(); -//// } -//// -//// -//// } -// -//// NOTE: Only run this ONCE now... MinePagedResetAsyncTask handles the paging now -//// else { -//// -//// // Need to continue to reset the mine. Resubmit it to run again. -//// MineResetAsyncResubmitTask mrAsyncRT = new MineResetAsyncResubmitTask( this, null, -//// getCurrentJob().getResetActions() ); -//// -//// // Must run synchronously!! -//// submitSyncTask( mrAsyncRT ); -//// } -// } -// -// -// } - public List getTargetBlockStatsPerLevel() { - List layers = new ArrayList<>(); - - - // Scan all blocks to see if they are the same or now air - // Use isCheckAir() and isCheckSamme(); - scanAllBlocksForUpdates(); - - -// int blocksPerLayer = getBounds().getBlockCountPerLayer(); - //int totalLayers = getBounds().getTotalLayers(); - - // BlockName = BlockLetter -// TreeMap translator = new TreeMap<>(); -// TreeMap map = new TreeMap<>(); -// TreeMap mapMine = new TreeMap<>(); - - // Add AIR to make sure it is there: - PrisonBlock air = PrisonBlock.AIR.clone(); - boolean hasAir = getPrisonBlock( air.getBlockName() ) != null; - - if ( !hasAir ) { - getPrisonBlocks().add( air ); - getBlockStats( air ); - } - - int j = 0; - TreeSet keys = new TreeSet<>( getBlockStats().keySet() ); - for (String key : keys) { + List layers = new ArrayList<>(); + + + // Scan all blocks to see if they are the same or now air + // Use isCheckAir() and isCheckSamme(); + scanAllBlocksForUpdates(); + + + // Add AIR to make sure it is there: + PrisonBlock air = PrisonBlock.AIR.clone(); + boolean hasAir = getPrisonBlock( air.getBlockName() ) != null; + + if ( !hasAir ) { + getPrisonBlocks().add( air ); + getBlockStats( air ); + } + + int j = 0; + TreeSet keys = new TreeSet<>( getBlockStats().keySet() ); + for (String key : keys) { PrisonBlockStatusData blk = getBlockStats().get( key ); blk.setAltValues( j++ ); } - - -// String codesStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789@#&*"; -// List codes = Arrays.asList( codesStr.split("|")); -// String colors = "12345789abcde"; - - - // Always add the air block: -// translator.put( PrisonBlock.AIR.getBlockName(), "" ); - - - -// // Build translations: -// char blk = 'A'; -//// double chance = 0; -//// boolean hasAir = false; -// -// // First add all the blocks with an empty String as the value: -// for (PrisonBlock b : getPrisonBlocks() ) { -//// chance += b.getChance(); -// translator.put( b.getBlockName(), "" ); -//// if ( b.isAir() ) { -//// hasAir = true; -//// } -// } -//// if ( !hasAir && chance < 100.0d ) { -//// translator.put( PrisonBlock.AIR.getBlockName(), "" ); -//// } -// -// // Now that they are in order, assign the alphabetical names: -// Set tkeys = translator.keySet(); -// for (String tKey : tkeys) { -// translator.put( tKey, Character.toString( blk ) ); -// -// if ( blk == 'Z' ) { -// blk = 'a'; -// } -// else if ( blk == 'z' ) { -// blk = '1'; -// } -// else { -// blk++; -// } -// } - -// String airName = PrisonBlock.AIR.getBlockName(); -// String keyAir = translator.get(airName); -// -// map.put( keyAir, 0 ); -// mapMine.put( keyAir, 0 ); - - int layer = 0; - int blockCount = 0; - - for ( int i = 0; i < getMineTargetPrisonBlocks().size(); i++ ) { - - MineTargetPrisonBlock tBlock = getMineTargetPrisonBlocks().get(i); - int y = getMineTargetPrisonBlocks().get(i).getLocation().getBlockY(); - blockCount++; - - - { - PrisonBlockStatusData statsBlock = null; - - // the getPrisonblock() should not return a null value: - PrisonBlockStatusData sBlock = tBlock.getPrisonBlock(); - - if ( sBlock == null ) { - sBlock = PrisonBlock.AIR.clone(); - } - - String blockName = sBlock.getBlockName(); - statsBlock = getBlockStats().get( blockName ); - - if ( statsBlock == null ) { - statsBlock = getBlockStats().get( air ); - } - - - statsBlock.setAltCountVirtual( statsBlock.getAltCountVirtual() + 1); - if ( tBlock.isCheckSame() ) { - statsBlock.setAltCountPhysical( statsBlock.getAltCountPhysical() + 1); - } - else if ( tBlock.isCheckAir() ) { - - PrisonBlockStatusData airStats = getBlockStats( air ); - airStats.setAltCountPhysical( airStats.getAltCountPhysical() + 1); - - } - - } - - -// int level = (int) ((i / (double) blocksPerLayer) + 1); - -// getBlockStats(keyAir); -// tBlock.getPrisonBlock(); -// -// String keyPrime = tBlock == null || tBlock.getPrisonBlock() == null ? -// airName : -// tBlock.getPrisonBlock().getBlockName(); -// -// String key = translator.get(keyPrime); -// -// if ( !map.containsKey(key) ) { -// map.put( key, 1 ); -// } -// else { -// map.put( key, 1 + map.get(key) ); -// } -// -// if ( !mapMine.containsKey(key) ) { -// mapMine.put( key, 0 ); -// } -//// if ( !mapMine.containsKey(keyAir) ) { -//// mapMine.put( keyAir, 0 ); -//// } -// -// if ( tBlock.isCheckSame() ) { -// mapMine.put( key, 1 + mapMine.get(key) ); -// } -// else if ( tBlock.isCheckAir() ) { -// mapMine.put( keyAir, 1 + mapMine.get(keyAir) ); -// -// } + + int layer = 0; + int blockCount = 0; + + for ( int i = 0; i < getMineTargetPrisonBlocks().size(); i++ ) { + + MineTargetPrisonBlock tBlock = getMineTargetPrisonBlocks().get(i); + int y = getMineTargetPrisonBlocks().get(i).getLocation().getBlockY(); + blockCount++; + + + { + PrisonBlockStatusData statsBlock = null; + + // the getPrisonblock() should not return a null value: + PrisonBlockStatusData sBlock = tBlock.getPrisonBlock(); + + if ( sBlock == null ) { + sBlock = PrisonBlock.AIR.clone(); + } + + String blockName = sBlock.getBlockName(); + statsBlock = getBlockStats().get( blockName ); + + + // TODO Not sure if air.getBlockName() is correct! It was just 'air' which was wrong. + // Did not have time to review this code to see if blockName is correct. + if ( statsBlock == null ) { + statsBlock = getBlockStats().get( air.getBlockName() ); + } + + + statsBlock.setAltCountVirtual( statsBlock.getAltCountVirtual() + 1); + if ( tBlock.isCheckSame() ) { + statsBlock.setAltCountPhysical( statsBlock.getAltCountPhysical() + 1); + } + else if ( tBlock.isCheckAir() ) { + + PrisonBlockStatusData airStats = getBlockStats( air ); + airStats.setAltCountPhysical( airStats.getAltCountPhysical() + 1); + + } + + } - if ( (i + 1) >= getMineTargetPrisonBlocks().size() || - getMineTargetPrisonBlocks().get(i + 1).getLocation().getBlockY() != y ) { - - StringBuilder sb = new StringBuilder(); - - sb.append( "Layer " ).append( layer++ ) - .append( " (" ).append( blockCount ).append(")") - .append( " : " ); - -// TreeSet keys = new TreeSet<>( map.keySet() ); - for ( String k : keys ) { - - PrisonBlockStatusData statsBlock = getBlockStats( k ); - - sb.append( statsBlock.getAltColorCode() ) - .append( statsBlock.getAltAlias() ) - .append( Output.get().getColorCodeInfo() ) - .append( ":" ) - .append( statsBlock.getAltCountVirtual() ); - - if ( statsBlock.getAltCountVirtual() != statsBlock.getAltCountPhysical() ) { - sb.append( ":" ) - .append( statsBlock.getAltCountPhysical() ); - } - - sb.append( " " ); - - statsBlock.resetAltValues(); - -// for ( Entry eSet : translator.entrySet()) { -// if ( eSet.getValue().equalsIgnoreCase(k) ) { -// -// String blockName = eSet.getKey(); -// sb.append( blockName ).append( ":" ).append( map.get(k) ).append( " " ); -// -// break; -// } -// } - -// int c = k.charAt(0) % colors.length(); -// -// String color = "&" + String.valueOf(colors.charAt(c)); -// -// int count = map.get(k); -// int countMine = mapMine.get(k); -// -// sb -// .append( color ).append( k ).append( Output.get().getColorCodeDebug() ) -// .append( ":" ).append( count ); -// -// if ( count != countMine ) { -// sb -// .append( ":" ).append( countMine ); -// } -// -// sb.append( " " ); - } - - layers.add( sb.toString() ); - - blockCount = 0; - - -// map.clear(); -// mapMine.clear(); -// -// map.put( keyAir, 0 ); -// mapMine.put( keyAir, 0 ); - } -// // if last block of the layer: -// if ( (int) (((i + 1) / (double) blocksPerLayer) + 1) > level ) { -// StringBuilder sb = new StringBuilder(); -// -// sb.append( "Layer " ).append( layer++ ).append( " : " ); -// -// TreeSet keys = new TreeSet<>( map.keySet() ); -// for ( String k : keys ) { -//// for ( Entry eSet : translator.entrySet()) { -//// if ( eSet.getValue().equalsIgnoreCase(k) ) { -//// -//// String blockName = eSet.getKey(); -//// sb.append( blockName ).append( ":" ).append( map.get(k) ).append( " " ); -//// -//// break; -//// } -//// } -// sb.append( k ).append( ":" ).append( map.get(k) ).append( " " ); -// } -// -// layers.add( sb.toString() ); -// -// map.clear(); -// } - } - - - { - // print the legend: - StringBuilder sb = new StringBuilder(); - - sb.append( "Legend: " ); + if ( (i + 1) >= getMineTargetPrisonBlocks().size() || + getMineTargetPrisonBlocks().get(i + 1).getLocation().getBlockY() != y ) { + + StringBuilder sb = new StringBuilder(); + + sb.append( "Layer " ).append( layer++ ) + .append( " (" ).append( blockCount ).append(")") + .append( " : " ); + + for ( String k : keys ) { + + PrisonBlockStatusData statsBlock = getBlockStats( k ); + + sb.append( statsBlock.getAltColorCode() ) + .append( statsBlock.getAltAlias() ) + .append( Output.get().getColorCodeInfo() ) + .append( ":" ) + .append( statsBlock.getAltCountVirtual() ); + + if ( statsBlock.getAltCountVirtual() != statsBlock.getAltCountPhysical() ) { + sb.append( ":" ) + .append( statsBlock.getAltCountPhysical() ); + } + + sb.append( " " ); + + statsBlock.resetAltValues(); + + } + + layers.add( sb.toString() ); + + blockCount = 0; + } - for ( String k : keys ) { - - PrisonBlockStatusData statsBlock = getBlockStats( k ); - - sb.append( statsBlock.getAltColorCode() ) - .append( statsBlock.getAltAlias() ) - .append( Output.get().getColorCodeInfo() ) - .append( "=" ) - .append( statsBlock.getBlockName() ) - .append( " " ); - - } - -// for ( Entry eSet : translator.entrySet()) { -// String blockName = eSet.getKey(); -// -// String value = eSet.getValue(); -// -// int c = value.charAt(0) % colors.length(); -// String color = "&" + String.valueOf(colors.charAt(c)); -// -// sb -// .append( color ).append( eSet.getValue() ).append( Output.get().getColorCodeDebug() ) -// .append( ":" ).append( blockName ).append( " " ); -// } + } + + + // Print the legend: + { + // print the legend: + StringBuilder sb = new StringBuilder(); + + sb.append( "Legend: " ); + + for ( String k : keys ) { + + PrisonBlockStatusData statsBlock = getBlockStats( k ); + + sb.append( statsBlock.getAltColorCode() ) + .append( statsBlock.getAltAlias() ) + .append( Output.get().getColorCodeInfo() ) + .append( "=" ) + .append( statsBlock.getBlockName() ) + .append( " " ); + + + } - layers.add( sb.toString() ); - } - - if ( !hasAir ) { - removePrisonBlock( air ); - getBlockStats().remove( air.getBlockName() ); - } - - - return layers; + layers.add( sb.toString() ); + + } + + + // If there is no air in the layers, then remove it from the stats: + if ( !hasAir ) { + removePrisonBlock( air ); + getBlockStats().remove( air.getBlockName() ); + } + + + return layers; } @@ -1222,8 +665,7 @@ public void asynchronouslyResetSetup() { int row = 0; for (String command : getResetCommands() ) { row++; -// String formatted = cmd.replace("{player}", prisonPlayer.getName()) -// .replace("{player_uid}", player.uid.toString()); + if ( command.startsWith( "before: " )) { String cmd = command.replace( "before: ", "" ); @@ -1232,8 +674,6 @@ public void asynchronouslyResetSetup() { debugInfo, cmd, row ); cmdTasks.add( cmdTask ); -// PrisonCommandTasks.submitTasks( cmdTask ); - // PrisonAPI.dispatchCommand(cmd); } } @@ -1248,15 +688,12 @@ public void asynchronouslyResetFinalize( List jobResetActions // this will TP anyone out who would otherwise suffocate. I hope! lol - if ( Prison.get().getPlatform().getConfigBooleanTrue( "prison-mines.tp-to-spawn-on-mine-resets" ) ) { - MineTeleportTask teleportTask = new MineTeleportTask( (Mine) this ); - teleportTask.submitTaskSync(); - } + if ( Prison.get().getPlatform().getConfigBooleanTrue( "prison-mines.tp-to-spawn-on-mine-resets" ) ) { + MineTeleportTask teleportTask = new MineTeleportTask( (Mine) this ); + teleportTask.submitTaskSync(); + } -// teleportAllPlayersOut(); -// setStatsTeleport2TimeMS( -// teleportAllPlayersOut( getBounds().getyBlockMax() ) ); // Reset the paging for the next reset: setResetPage( 0 ); @@ -1281,8 +718,7 @@ public void asynchronouslyResetFinalize( List jobResetActions int row = 0; for (String command : getResetCommands() ) { row++; -// String formatted = cmd.replace("{player}", prisonPlayer.getName()) -// .replace("{player_uid}", player.uid.toString()); + if ( command.startsWith( "after: " )) { String cmd = command.replace( "after: ", "" ); @@ -1301,7 +737,6 @@ public void asynchronouslyResetFinalize( List jobResetActions // Broadcast message to all players within a certain radius of this mine: broadcastResetMessageToAllPlayersWithRadius(); -// broadcastResetMessageToAllPlayersWithRadius( MINE_RESET__BROADCAST_RADIUS_BLOCKS ); submitTeleportGlassBlockRemoval(); @@ -1309,16 +744,17 @@ public void asynchronouslyResetFinalize( List jobResetActions // Tie to the command stats mode so it logs it if stats are enabled: if ( PrisonMines.getInstance().getMineManager().isMineStats() || - getCurrentJob().getResetActions().contains( MineResetActions.DETAILS ) ) { - DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - Output.get().logInfo("&cMine reset: &7" + getTag() + - "&c Blocks: &7" + dFmt.format( getBounds().getTotalBlockCount() ) + - statsMessage() ); + getCurrentJob().getResetActions().contains( MineResetActions.DETAILS ) ) { + + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + Output.get().logInfo("&cMine reset: &7" + getTag() + + "&c Blocks: &7" + dFmt.format( getBounds().getTotalBlockCount() ) + + statsMessage() ); } // If part of a chained_resets, then kick off the next reset: if ( jobResetActions != null && jobResetActions.contains( MineResetActions.CHAINED_RESETS ) || - getCurrentJob().getResetActions().contains( MineResetActions.CHAINED_RESETS )) { + getCurrentJob().getResetActions().contains( MineResetActions.CHAINED_RESETS )) { PrisonMines pMines = PrisonMines.getInstance(); pMines.resetAllMinesNext(); @@ -1326,164 +762,43 @@ public void asynchronouslyResetFinalize( List jobResetActions } - public boolean resetAsynchonouslyInitiate( MineResetType resetType ) { - boolean canceled = false; - - if ( isVirtual()) { - canceled = true; - } - else - if ( !isEnabled() ) { - Output.get().logError( - String.format( "MineReset: resetAsynchonouslyInitiate failure: Mine is not enabled. " + - "Ensure world exists. mine= %s ", - getName() )); - canceled = true; - } - else { -// long start = System.currentTimeMillis(); + public boolean resetAsynchonouslyInitiate( MineResetType resetType ) { + boolean canceled = false; - // The all-important event - MineResetEvent event = new MineResetEvent(this, resetType); - Prison.get().getEventBus().post(event); - - canceled = event.isCanceled(); - if (!canceled) { + if ( isVirtual()) { + canceled = true; + } + else + if ( !isEnabled() ) { + Output.get().logError( + String.format( "MineReset: resetAsynchonouslyInitiate failure: Mine is not enabled. " + + "Ensure world exists. mine= %s ", + getName() )); + canceled = true; + } + else { + + // The all-important event + MineResetEvent event = new MineResetEvent(this, resetType); + Prison.get().getEventBus().post(event); + + canceled = event.isCanceled(); + if (!canceled) { + + + if ( Prison.get().getPlatform().getConfigBooleanTrue( "prison-mines.tp-to-spawn-on-mine-resets" ) ) { + MineTeleportTask teleportTask = new MineTeleportTask( (Mine) this ); + teleportTask.submitTaskSync(); + } + + } - - if ( Prison.get().getPlatform().getConfigBooleanTrue( "prison-mines.tp-to-spawn-on-mine-resets" ) ) { - MineTeleportTask teleportTask = new MineTeleportTask( (Mine) this ); - teleportTask.submitTaskSync(); - } - -// try { -// teleportAllPlayersOut(); -//// setStatsTeleport1TimeMS( -//// teleportAllPlayersOut( getBounds().getyBlockMax() ) ); -// -// } catch (Exception e) { -// Output.get().logError("&cMineReset: Failed to TP players out of mine. mine= " + -// getName(), e); -// canceled = true; -// } } - -// long stop = System.currentTimeMillis(); -// setStatsResetTimeMS( stop - start ); - } - - return canceled; + + return canceled; } -// /** -// *

    This is the synchronous part of the job that actually updates the blocks. -// * It will only replace what it can within the given allocated milliseconds, -// * then it will terminate and allow this process to re-run, picking up where it -// * left off. -// *

    -// * -// *

    Paging is what this is doing. Running, and doing what it can within it's -// * limited amount of time, then yielding to any other task, then resuming later. -// * This is a way of running a massive synchronous task, without hogging all the -// * resources and killing the TPS. -// *

    -// * -// *

    NOTE: The values for MINE_RESET__PAGE_TIMEOUT_CHECK__BLOCK_COUNT and for -// * MINE_RESET__MAX_PAGE_ELASPSED_TIME_MS are set to arbitrary values and may not -// * be the correct values. They may be too large and may have to be adjusted to -// * smaller values to better tune the process. -// *

    -// * -// */ -// private void resetAsynchonouslyUpdate( boolean paged ) { -// if ( isVirtual() ) { -// // ignore: -// } -// else -// if ( !isEnabled() ) { -// Output.get().logError( -// String.format( "MineReset: resetAsynchonouslyUpdate failure: Mine is not enabled. " + -// "Ensure world exists. mine= %s ", -// getName() )); -// } -// else { -// World world = getBounds().getCenter().getWorld(); -// -// -// long start = System.currentTimeMillis(); -// -//// boolean isFillMode = PrisonMines.getInstance().getConfig().fillMode; -// -// int blocksPlaced = 0; -// long elapsed = 0; -// -// int i = getResetPosition(); -// for ( ; i < getMineTargetPrisonBlocks().size(); i++ ) -// { -// MineTargetPrisonBlock target = getMineTargetPrisonBlocks().get(i); -// -// Location targetBlock = new Location(world, -// target.getBlockKey().getX(), target.getBlockKey().getY(), -// target.getBlockKey().getZ()); -// -//// if (!isFillMode || isFillMode && targetBlock.getBlockAt().isEmpty()) { -//// } -// if ( isUseNewBlockModel() ) { -// -// targetBlock.getBlockAt().setPrisonBlock( (PrisonBlock) target.getPrisonBlock() ); -// } -// else { -// -// targetBlock.getBlockAt().setType( ((BlockOld) target.getPrisonBlock()).getType() ); -// } -// -// /** -// * If paged is enabled... -// * -// * About every 250 blocks, or so, check to see if the current wall time -// * spent is greater than -// * the threshold. If it is greater, then end the update and let it resubmit. -// * It does not matter how many blocks were actually updated during this "page", -// * but what it is more important is the actual elapsed time. This is to allow other -// * processes to get processing time and to eliminate possible lagging. -// */ -// if ( paged && i % getResetPageTimeoutCheckBlockCount() == 0 ) { -// elapsed = System.currentTimeMillis() - start; -// if ( elapsed > getResetPageMaxPageElapsedTimeMs() ) { -// -// break; -// } -// } -// } -// -// blocksPlaced = i - getResetPosition(); -// -// if ( PrisonMines.getInstance().getMineManager().isMineStats() ) { -// -// // Only print these details if stats is enabled: -// Output.get().logInfo( "MineReset.resetAsynchonouslyUpdate() :" + -// " page " + getResetPage() + -// " blocks = " + blocksPlaced + " elapsed = " + elapsed + -// " ms TPS: " + Prison.get().getPrisonTPS().getAverageTPSFormatted() ); -// } -// -// setResetPosition( i ); -// -// setResetPage( getResetPage() + 1 ); -// -// long time = System.currentTimeMillis() - start; -// setStatsBlockUpdateTimeMS( time + getStatsBlockUpdateTimeMS() ); -// setStatsResetTimeMS( time + getStatsResetTimeMS() ); -// -// -// setStatsResetPages( getStatsResetPages() + 1 ); -// setStatsResetPageBlocks( getStatsResetPageBlocks() + blocksPlaced ); -// setStatsResetPageMs( getStatsResetPageMs() + time ); -// } -// -// } - /** @@ -1496,23 +811,9 @@ public boolean resetAsynchonouslyInitiate( MineResetType resetType ) { */ public void refreshBlockBreakCountUponStartup( long delay) { - // if the mine is being used in a unit test, then it will not have a value for - // bounds and therefore do not run the task. - if ( getBounds() != null ) { - - OnStartupRefreshBlockBreakCountSyncTask.submit( this, delay ); - -// OnStartupRefreshBlockBreakCountAsyncTask cabAsyncTask = new OnStartupRefreshBlockBreakCountAsyncTask(this); -// -// // Must run synchronously!! -// submitSyncTask( cabAsyncTask ); -// //submitAsyncTask( cabAsyncTask ); - } + // not used } -// protected void resetAirCountStartupAsyncTask() { -// refreshAirCountAsyncTask( false ); -// } /** *

    This function performs the air count and should be ran as an async task. @@ -1531,47 +832,47 @@ protected boolean refreshAirCountSyncTaskCheckBeforeSubmit() { boolean results = false; - if ( isVirtual() ) { - // ignore: - } - else - if ( !isEnabled() ) { - Output.get().logError( - String.format( "MineReset: refreshAirCountAsyncTask failure: Mine is not enabled. " + - "Ensure world exists. mine= %s ", - getName() )); - } - else if ( getPrisonBlocks().size() == 1 && - getPrisonBlocks().get( 0 ).equals( PrisonBlock.IGNORE ) ) { - - // This mine is set to ignore all blocks when trying to do a reset, - // so for now ignore the types and just set air count to zero. - // Basically, this mine, if using natural spawned landscape, may contain blocks that are - // not registered and tracked within prison, and hence will report incorrect errors. - setAirCount( 0 ); - } - else { - Optional worldOptional = getWorld(); - World world = worldOptional.get(); - - if ( world == null ) { + if ( isVirtual() ) { + // ignore: + } + else + if ( !isEnabled() ) { Output.get().logError( - String.format( "MineReset: refreshAirCountAsyncTask failure: The world is invalid and " + - "cannot be located. mine= %s worldName=%s ", - getName(), getWorldName() )); - - + String.format( "MineReset: refreshAirCountAsyncTask failure: Mine is not enabled. " + + "Ensure world exists. mine= %s ", + getName() )); + } + else if ( getPrisonBlocks().size() == 1 && + getPrisonBlocks().get( 0 ).equals( PrisonBlock.IGNORE ) ) { + + // This mine is set to ignore all blocks when trying to do a reset, + // so for now ignore the types and just set air count to zero. + // Basically, this mine, if using natural spawned landscape, may contain blocks that are + // not registered and tracked within prison, and hence will report incorrect errors. + setAirCount( 0 ); } else { + Optional worldOptional = getWorld(); + World world = worldOptional.get(); - // This means we can actually go ahead and perform the air-counts and so the - // actual job can be submitted: - return true; + if ( world == null ) { + Output.get().logError( + String.format( "MineReset: refreshAirCountAsyncTask failure: The world is invalid and " + + "cannot be located. mine= %s worldName=%s ", + getName(), getWorldName() )); + + + } + else { + + // This means we can actually go ahead and perform the air-counts and so the + // actual job can be submitted: + return true; + } + } - - } - - return results; + + return results; } @@ -1586,25 +887,15 @@ else if ( getPrisonBlocks().size() == 1 && public List refreshAirCountSyncTaskBuildLocations() { List locations = new ArrayList<>(); -// long start = System.currentTimeMillis(); Optional worldOptional = getWorld(); World world = worldOptional.get(); - - { -// boolean containsCustomBlocks = getPrisonBlockTypes().contains( PrisonBlockType.CustomItems ); - + { // Reset the target block lists: clearMineTargetPrisonBlocks(); - -// int airCount = 0; -// int errorCount = 0; - - - int yMin = getBounds().getyBlockMin(); int yMax = getBounds().getyBlockMax(); @@ -1615,9 +906,6 @@ public List refreshAirCountSyncTaskBuildLocations() { int zMax = getBounds().getzBlockMax(); - -// StringBuilder sb = new StringBuilder(); - for (int y = yMax; y >= yMin; y--) { for (int x = xMin; x <= xMax; x++) { for (int z = zMin; z <= zMax; z++) { @@ -1637,74 +925,13 @@ public List refreshAirCountSyncTaskBuildLocations() { locations.add( targetLocation ); - - -// try { -// -// Block tBlock = targetBlock.getBlockAt( containsCustomBlocks ); -// -// -// -// -// PrisonBlock pBlock = tBlock.getPrisonBlock(); -// -// if ( pBlock != null ) { -// -// // Increment the mine's block count. This block is one of the control blocks: -// addMineTargetPrisonBlock( incrementResetBlockCount( pBlock ), targetBlock ); -// -// } -// -// if ( pBlock == null || pBlock.isAir() ) { -// airCount++; -// } -// } -// catch ( Exception e ) { -// // Updates to the "world" should never be ran async. Upon review of the above -// // that gets the location and block, causes the chunk to load, if it is not loaded, -// // and if there is an entity in that loaded chunk it will throw an exception: -// // java.lang.IllegalStateException: Asynchronous entity world add! -// // If there are no entities, it will be fine, but they could cause issues with async -// // access of unloaded chunks. -// String coords = String.format( "%d.%d.%d ", x, y, z ); -// if ( errorCount ++ == 0 ) { -// String message = String.format( -// "MineReset.refreshAirCountAsyncTask: Error counting air blocks: " + -// "Mine=%s coords=%s Error: %s ", getName(), coords, e.getMessage() ); -// if ( e.getMessage() != null && e.getMessage().contains( "Asynchronous entity world add" )) { -// Output.get().logWarn( message, e ); -// } else { -// Output.get().logWarn( message, e ); -// } -// -// } -// else if ( errorCount <= 20 ) { -// sb.append( coords ); -// } -// } } } } -// if ( errorCount > 0 ) { -// String message = String.format( -// "MineReset.refreshAirCountAsyncTask: Error counting air blocks: Mine=%s: " + -// "errorCount=%d blocks%s : %s", getName(), errorCount, -// (errorCount > 20 ? "(first 20)" : ""), -// sb.toString() ); -// Output.get().logWarn( message ); -// } -// -// -// setAirCount( airCount ); - -// long stop = System.currentTimeMillis(); -// long elapsed = stop - start; -// setAirCountElapsedTimeMs( elapsed ); -// setAirCountTimestamp( stop ); } - return locations; + return locations; } @@ -1712,7 +939,6 @@ public void refreshAirCountSyncTaskSetLocation( Location targetLocation, OnStartupRefreshBlockBreakCountSyncTask stats ) { try { -// Location targetBlock = new Location(world, x, y, z); boolean containsCustomBlocks = getPrisonBlockTypes().contains( PrisonBlockType.CustomItems ) || @@ -1739,6 +965,8 @@ public void refreshAirCountSyncTaskSetLocation( Location targetLocation, } } catch ( Exception e ) { + String msg = e.getMessage(); + stats.incrementErrorCount(); // Updates to the "world" should never be ran async. Upon review of the above @@ -1747,19 +975,34 @@ public void refreshAirCountSyncTaskSetLocation( Location targetLocation, // java.lang.IllegalStateException: Asynchronous entity world add! // If there are no entities, it will be fine, but they could cause issues with async // access of unloaded chunks. - String coords = String.format( "%d.%d.%d ", - targetLocation.getBlockX(), targetLocation.getBlockY(), targetLocation.getBlockZ() ); + + String coords = targetLocation.toBlockCoordinates(); + + if ( stats.getExceptionError() == null ) { + + stats.setExceptionError( msg ); + + StackTraceElement[] stackTrace = e.getStackTrace(); + + // print only the first 6 lines of the stack trace: + for (int i = 0; i < stackTrace.length && i <= 9; i++) { + StackTraceElement stEle = stackTrace[i]; + Output.get().logWarn( "*#* " + stEle.toString()); + } + } if ( stats.getErrorCount() == 0 ) { + // Error count is 0, so setup the messages: String message = String.format( "MineReset.refreshAirCountAsyncTask: Error counting air blocks: " + - "Mine=%s coords=%s Error: %s ", getName(), coords, e.getMessage() ); + "Mine=%s coords=%s Error: [%s] ", getName(), coords, msg ); - if ( e.getMessage() != null && e.getMessage().contains( "Asynchronous entity world add" )) { - Output.get().logWarn( message, e ); - } else { + if ( msg != null && msg.contains( "Asynchronous entity world add" )) { Output.get().logWarn( message, e ); - } + } +// else { +// Output.get().logWarn( message, e ); +// } } else if ( stats.getErrorCount() <= 10 ) { @@ -1784,11 +1027,10 @@ private void scanAllBlocksForUpdates() { i++; -; targetBlock.setCheckAir( false ); + targetBlock.setCheckAir( false ); targetBlock.setCheckSame( false ); try { -// Location targetBlock = new Location(world, x, y, z); boolean containsCustomBlocks = getPrisonBlockTypes().contains( PrisonBlockType.CustomItems ) || @@ -1824,8 +1066,6 @@ else if ( pBlock.getBlockName().equalsIgnoreCase( targetBlockName) ) { } - - } catch ( Exception e ) { @@ -1987,9 +1227,6 @@ public double getPercentRemainingBlockCount() { int totalCount = getBounds().getTotalBlockCount(); int remainingCount = getRemainingBlockCount(); double percentRemaining = (totalCount == 0d ? 0d : (remainingCount * 100d) / (double) totalCount); -// double remainingBlocksP = (totalCount - getAirCount()) * 100d; -// double originalCount = totalCount - getAirCountOriginal(); -// double percentRemaining = (originalCount == 0d ? 0d : remainingBlocksP / originalCount); return percentRemaining; } @@ -2032,134 +1269,8 @@ else if ( getPercentRemainingBlockCount() > getSkipResetPercent() ) { MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal ); resetTask.submitTaskAsync(); -// resetAsynchonously(); } -// public void refreshMineAsyncResubmitTask() { -// -// // Mine reset here: -// resetAsynchonously(); -// } - - - -// private PrisonBlock randomlySelectPrisonBlock( Random random, int currentLevel ) { -// -// int targetBlockPosition = getMineTargetPrisonBlocks().size(); -// -// PrisonBlock prisonBlock = Prison.get().getPlatform().getPrisonBlock( "AIR" ); -// -// -// // this fallbackBlock field will provide a valid block that can be used when all other -// // blocks have failed to be matched due to constraints not aligning with the random chance. -// // As a result of failing to find a block, would result in an AIR block being used instead. -// PrisonBlock fallbackBlock = null; -// -// -// // If a chosen block was skipped, try to find another block, but try no more than 10 times -// // to prevent a possible endless loop. Side effects of failing to find a block in 10 attempts -// // would be an air block. -// boolean success = false; -// int attempts = 0; -// while ( !success && attempts++ < 10 ) { -// double chance = random.nextDouble() * 100.0d; -// -// for (PrisonBlock block : getPrisonBlocks()) { -// boolean isBlockEnabled = block.isBlockConstraintsEnbled( currentLevel, targetBlockPosition ); -// -// if ( fallbackBlock == null && isBlockEnabled && !block.isAir() ) { -// fallbackBlock = block; -// } -// -// if ( chance <= block.getChance() && isBlockEnabled ) { -// -// // If this block is chosen and it was not skipped, then use this block and exit. -// // Otherwise the chance will be recalculated and tried again to find a valid block, -// // since the odds have been thrown off... -// prisonBlock = block; -// -// // stop trying to locate a block so success will terminate the search: -// success = true; -// -// break; -// } else { -// chance -= block.getChance(); -// } -// } -// -// if ( !success && fallbackBlock != null ) { -// prisonBlock = fallbackBlock; -// success = true; -// } -// } -// return prisonBlock; -// } - - // Obsolete... the old block model: -// private BlockOld randomlySelectBlock( Random random, int currentLevel ) { -// -// int targetBlockPosition = getMineTargetPrisonBlocks().size(); -// -// BlockOld results = BlockOld.AIR; -// -// -// // this fallbackBlock field will provide a valid block that can be used when all other -// // blocks have failed to be matched due to constraints not aligning with the random chance. -// // As a result of failing to find a block, would result in an AIR block being used instead. -// BlockOld fallbackBlock = null; -// -// -// -// // If a chosen block was skipped, try to find another block, but try no more than 10 times -// // to prevent a possible endless loop. Side effects of failing to find a block in 10 attempts -// // would be an air block. -// boolean success = false; -// int attempts = 0; -// while ( !success && attempts++ < 10 ) { -// double chance = random.nextDouble() * 100.0d; -// -// for (BlockOld block : getBlocks()) { -// boolean isBlockEnabled = block.isBlockConstraintsEnbled( currentLevel, targetBlockPosition ); -// -// if ( fallbackBlock == null && isBlockEnabled && !block.isAir() ) { -// fallbackBlock = block; -// } -// -// if ( chance <= block.getChance() && isBlockEnabled ) { -// -// // If this block is chosen and it was not skipped, then use this block and exit. -// // Otherwise the chance will be recalculated and tried again to find a valid block, -// // since the odds have been thrown off... -// results = block; -// -// // stop trying to locate a block so success will terminate the search: -// success = true; -// -// break; -// } else { -// chance -= block.getChance(); -// } -// } -// } -// -// if ( !success && fallbackBlock != null ) { -// results = fallbackBlock; -// success = true; -// } -// -//// for (BlockOld block : getBlocks()) { -//// if (block.checkConstraints( currentLevel, targetBlockPosition ) && -//// chance <= block.getChance() && -//// (block.getConstraintMax() == 0 || block.getResetBlockCount() < block.getConstraintMax())) { -//// results = block; -//// break; -//// } else { -//// chance -= block.getChance(); -//// } -//// } -// return results; -// } - private void constraintsApplyMin() { @@ -2187,66 +1298,58 @@ private void constraintsApplyMin() { private void constraintsApplyMin( PrisonBlockStatusData block ) { - if ( block.getConstraintMin() > 0 && block.getBlockPlacedCount() < block.getConstraintMin() ) { - - int maxAttempts = (block.getConstraintMin() - block.getBlockPlacedCount()) + 3; - - for ( int i = 0; i < maxAttempts && block.getBlockPlacedCount() < block.getConstraintMin(); i++ ) { - -// int maxSize = getMineTargetPrisonBlocks().size(); - - - - // Get an unmatched block in the block's range (not the same block): - int blockPos = block.getRandomBlockPositionInRangeUnmatched( getMineTargetPrisonBlocks() ); - - -// int rangeLow = block.getRangeBlockCountLowLimit(); -// int rangeHigh = block.getRangeBlockCountHighLimit(); - - // Each block has a valid range in which it can spawn in the mine. This range - // is honored by using the rangeHigh and rangeLow values. -// int rndPos = ((int) Math.round( Math.random() * (rangeHigh - rangeLow) )) + rangeLow; - - if ( blockPos > -1 && blockPos < getMineTargetPrisonBlocks().size() ) { - - MineTargetPrisonBlock targetBlock = getMineTargetPrisonBlocks().get( blockPos ); - - if ( targetBlock != null && - targetBlock.getPrisonBlock().getConstraintMin() == 0 && - targetBlock.getPrisonBlock().getConstraintMax() == 0 && - !targetBlock.getPrisonBlock().getBlockName().equalsIgnoreCase( - block.getBlockName() ) ) { - - // decrement the block count on the block being removed: - if ( targetBlock.getPrisonBlock().isAir() ) { - - // Need to remove one from the air count fields: - setAirCountOriginal( getAirCountOriginal() - 1 ); - setAirCount( getAirCount() - 1 ); - - } - else { - targetBlock.getPrisonBlock().decrementResetBlockCount(); - } - - - // Add the new block and increment it's count: - targetBlock.setPrisonBlock( block ); - - // If the reset is placing an AiR block, then mark the block as - // setAirBroke() and setMined() to ensure they are not counted or - // processed during normal mining operations, or through - // MineSweeper checks. - if ( block.isAir() ) { - targetBlock.setAirBroke( true ); - targetBlock.setMined( true ); - } - block.incrementResetBlockCount(); - } - } - } - } + if ( block.getConstraintMin() > 0 && block.getBlockPlacedCount() < block.getConstraintMin() ) { + + int maxAttempts = (block.getConstraintMin() - block.getBlockPlacedCount()) + 3; + + for ( int i = 0; i < maxAttempts && block.getBlockPlacedCount() < block.getConstraintMin(); i++ ) { + + // Get an unmatched block in the block's range (not the same block): + int blockPos = block.getRandomBlockPositionInRangeUnmatched( getMineTargetPrisonBlocks() ); + + // Each block has a valid range in which it can spawn in the mine. This range + // is honored by using the rangeHigh and rangeLow values. + // int rndPos = ((int) Math.round( Math.random() * (rangeHigh - rangeLow) )) + rangeLow; + + if ( blockPos > -1 && blockPos < getMineTargetPrisonBlocks().size() ) { + + MineTargetPrisonBlock targetBlock = getMineTargetPrisonBlocks().get( blockPos ); + + if ( targetBlock != null && + targetBlock.getPrisonBlock().getConstraintMin() == 0 && + targetBlock.getPrisonBlock().getConstraintMax() == 0 && + !targetBlock.getPrisonBlock().getBlockName().equalsIgnoreCase( + block.getBlockName() ) ) { + + // decrement the block count on the block being removed: + if ( targetBlock.getPrisonBlock().isAir() ) { + + // Need to remove one from the air count fields: + setAirCountOriginal( getAirCountOriginal() - 1 ); + setAirCount( getAirCount() - 1 ); + + } + else { + targetBlock.getPrisonBlock().decrementResetBlockCount(); + } + + + // Add the new block and increment it's count: + targetBlock.setPrisonBlock( block ); + + // If the reset is placing an AiR block, then mark the block as + // setAirBroke() and setMined() to ensure they are not counted or + // processed during normal mining operations, or through + // MineSweeper checks. + if ( block.isAir() ) { + targetBlock.setAirBroke( true ); + targetBlock.setMined( true ); + } + block.incrementResetBlockCount(); + } + } + } + } } /** @@ -2255,8 +1358,8 @@ private void constraintsApplyMin( PrisonBlockStatusData block ) */ public void enableTracer(MineResetType resetType) { - // First clear the mine: - clearMine( resetType ); + // First clear the mine: + clearMine( resetType ); // Prison.get().getPlatform().enableMineTracer( // getWorldName(), @@ -2278,39 +1381,39 @@ public void enableTracer(MineResetType resetType) { */ public void adjustSize( Edges edge, int amount ) { - // First clear the mine: - clearMine( MineResetType.clear ); - - // if amount is zero, then just refresh the liner: - - if ( amount < 0 ) { - while ( amount++ < 0 ) { - - new MineLinerBuilder( (Mine) this, edge, LinerPatterns.repair, false ); - - Bounds newBounds = new Bounds( getBounds(), edge, -1 ); - setBounds( newBounds ); - - new MineLinerBuilder( (Mine) this, edge, LinerPatterns.repair, false ); - } - } - else if ( amount > 0 ) { - new MineLinerBuilder( (Mine) this, edge, LinerPatterns.repair, false ); - - Bounds newBounds = new Bounds( getBounds(), edge, amount ); - setBounds( newBounds ); - } - - // Rebuild the liner if it exists: - for ( Edges targtEdge : Edges.values() ) { + // First clear the mine: + clearMine( MineResetType.clear ); - if ( getLinerData().hasEdge( targtEdge ) ) { - - LinerPatterns pattern = LinerPatterns.fromString( getLinerData().getEdge( targtEdge ) ); - boolean force = getLinerData().getForce( targtEdge ); - - new MineLinerBuilder( (Mine) this, targtEdge, pattern, force ); - } + // if amount is zero, then just refresh the liner: + + if ( amount < 0 ) { + while ( amount++ < 0 ) { + + new MineLinerBuilder( (Mine) this, edge, LinerPatterns.repair, false ); + + Bounds newBounds = new Bounds( getBounds(), edge, -1 ); + setBounds( newBounds ); + + new MineLinerBuilder( (Mine) this, edge, LinerPatterns.repair, false ); + } + } + else if ( amount > 0 ) { + new MineLinerBuilder( (Mine) this, edge, LinerPatterns.repair, false ); + + Bounds newBounds = new Bounds( getBounds(), edge, amount ); + setBounds( newBounds ); + } + + // Rebuild the liner if it exists: + for ( Edges targtEdge : Edges.values() ) { + + if ( getLinerData().hasEdge( targtEdge ) ) { + + LinerPatterns pattern = LinerPatterns.fromString( getLinerData().getEdge( targtEdge ) ); + boolean force = getLinerData().getForce( targtEdge ); + + new MineLinerBuilder( (Mine) this, targtEdge, pattern, force ); + } } // Finally trace the mine: @@ -2320,15 +1423,15 @@ else if ( amount > 0 ) { public void moveMine( Edges edge, int amount ) { - MineMover moveMine = new MineMover(); - moveMine.moveMine( (Mine) this, edge, amount ); + MineMover moveMine = new MineMover(); + moveMine.moveMine( (Mine) this, edge, amount ); } public void clearMine( MineResetType resetType ) { - MineTracerBuilder tracerBuilder = new MineTracerBuilder(); - tracerBuilder.clearMine( (Mine) this, resetType ); + MineTracerBuilder tracerBuilder = new MineTracerBuilder(); + tracerBuilder.clearMine( (Mine) this, resetType ); } @@ -2354,28 +1457,19 @@ private void addMineTargetPrisonBlock( PrisonBlockStatusData block, Location tar } } -// private void addMineTargetPrisonBlock( PrisonBlockStatusData block, int x, int y, int z, boolean isEdge ) { -// -// MineTargetPrisonBlock mtpb = new MineTargetPrisonBlock( block, getWorld().get(), x, y, z, isEdge ); -// -// getMineTargetPrisonBlocks().add( mtpb ); -// getMineTargetPrisonBlocksMap().put( mtpb.getBlockKey(), mtpb ); -// } private void clearMineTargetPrisonBlocks() { + + // Instead of clearing the collections, set them to null so that way if + // other reference exist, they will be able to continue to use them + // until the release the references. + + synchronized ( getMineStateMutex() ) { + + mineTargetPrisonBlocks = null; + mineTargetPrisonBlocksMap = null; + } - // Instead of clearing the collections, set them to null so that way if - // other reference exist, they will be able to continue to use them - // until the release the references. - - synchronized ( getMineStateMutex() ) { - - mineTargetPrisonBlocks = null; - mineTargetPrisonBlocksMap = null; - } - -// getMineTargetPrisonBlocks().clear(); -// getMineTargetPrisonBlocksMap().clear(); } @@ -2410,30 +1504,6 @@ public MineTargetPrisonBlock getTargetPrisonBlock( PrisonBlock block ) { } - -// public String getTargetPrisonBlockName( Block block ) { -// String results = "AIR"; -// -// if ( block != null ) { -// PrisonBlock pBlock = block.getPrisonBlock(); -// if ( pBlock != null ) { -// -// results = pBlock.getBlockName(); -// } -// -// if ( "AIR".equalsIgnoreCase( results ) ) { -// MineTargetPrisonBlock targetBlock = getTargetPrisonBlock( block ); -// -// if ( targetBlock != null ) { -// results = targetBlock.getPrisonBlock().getBlockName(); -// } -// } -// } -// -// return results; -// } - - public int getResetPage() { @@ -2590,6 +1660,5 @@ public boolean isMineSweeperSubmitted() { public void setMineSweeperSubmitted( boolean mineSweeperSubmitted ) { this.mineSweeperSubmitted = mineSweeperSubmitted; } - } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java index 82bbc534e..35ff5fd63 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineScheduler.java @@ -21,7 +21,7 @@ import tech.mcprison.prison.mines.tasks.MinePagedResetAsyncTask; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonCommandTaskData; -import tech.mcprison.prison.tasks.PrisonCommandTaskData.CustomPlaceholders; +import tech.mcprison.prison.tasks.PrisonCommandTaskData.BlockEventCustomPlaceholders; import tech.mcprison.prison.tasks.PrisonRunnable; import tech.mcprison.prison.tasks.PrisonTaskSubmitter; import tech.mcprison.prison.tasks.PrisonCommandTasks; @@ -44,10 +44,9 @@ public abstract class MineScheduler * once a workflow cycle has been completed. *

    */ - private List jobWorkflow; - private Stack jobStack; -// private MineJob currentJob; - private Integer taskId = null; + private transient List jobWorkflow; + private transient Stack jobStack; + private transient Integer taskId = null; private transient long mineResetStartTimestamp; @@ -69,11 +68,11 @@ public MineScheduler() { */ @Override protected void initialize() { - super.initialize(); - - // need to rebuild JobWorkflow if reset time ever changes: - setJobWorkflow( initializeJobWorkflow() ); - resetJobStack(); + super.initialize(); + + // need to rebuild JobWorkflow if reset time ever changes: + setJobWorkflow( initializeJobWorkflow() ); + resetJobStack(); } public enum JobType { @@ -280,7 +279,6 @@ protected List initializeJobWorkflow( double resetTime, boolean include if ( includeMessages ) { // Need to ensure that the reset warning times are sorted in ascending order: -// ArrayList rwTimes = PrisonMines.getInstance().getConfig().resetWarningTimes; Collections.sort( resetWarningTimes ); double total = 0; @@ -352,10 +350,10 @@ public void run() return; } - boolean skip = !forced && - isSkipResetEnabled() && - getPercentRemainingBlockCount() >= getSkipResetPercent() && - getSkipResetBypassCount() < getSkipResetBypassLimit(); + boolean skip = !forced && + isSkipResetEnabled() && + getPercentRemainingBlockCount() >= getSkipResetPercent() && + getSkipResetBypassCount() < getSkipResetBypassLimit(); // Output.get().logInfo( "Mine Reset: Run: Mine= %s action= %s skip= %s forced= %s ", // this.getName(), getCurrentJob().getAction().name(), @@ -395,9 +393,8 @@ public void run() MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal, resetActions, resetScheduleType ); - resetTask.submitTaskAsync(); + resetTask.submitTaskAsync(); -// resetAsynchonously(); } else { incrementSkipResetBypassCount(); @@ -406,35 +403,11 @@ public void run() break; -// case RESET_SYNC: -// // synchronous reset. Will be phased out in the future? -// if ( !skip ) { -// -// List resetActions = getCurrentJob().getResetActions(); -// -// MinePagedResetAsyncTask resetTask = -// new MinePagedResetAsyncTask( (Mine) this, MineResetType.normal, resetActions ); -// -// resetTask.submitTaskAsync(); -// -//// resetSynchonously(); -// } else { -// incrementSkipResetBypassCount(); -// } -// -// break; default: break; } -// if ( getCurrentJob().getAction() == MineJobAction.RESET ) { -// resetSynchonously(); -// } else { -// // Send reset message: -// broadcastPendingResetMessageToAllPlayersWithRadius(getCurrentJob(), MINE_RESET_BROADCAST_RADIUS_BLOCKS ); -// } -// // this may be an issue for disabled resetTimes... may still need to be submitted? // disabled resets may not need to be submitted at all. @@ -466,9 +439,9 @@ private void checkWorld() "This is serious. &aworldName= " + getWorldName() ); } else { - World world = worldOptional.get(); - - setWorld( world ); + World world = worldOptional.get(); + + setWorld( world ); } } } @@ -555,10 +528,11 @@ private void submitNextAction(double offsetSeconds) { * @param blockCount * @param player */ - public void processBlockBreakEventCommands( PrisonBlock prisonBlock, + public int processBlockBreakEventCommands( PrisonBlock prisonBlock, MineTargetPrisonBlock targetBlock, Player player, BlockEventType eventType, String triggered ) { + int blockEventsRan = 0; // Only one block is processed here: if ( getBlockEvents().size() > 0 ) { @@ -571,52 +545,28 @@ public void processBlockBreakEventCommands( PrisonBlock prisonBlock, for ( MineBlockEvent blockEvent : getBlockEvents() ) { double chance = random.nextDouble() * 100; - processBlockEventDetails( player, prisonBlock, - targetBlock, eventType, chance, blockEvent, triggered, - cmdTasks, ++row ); + blockEventsRan += + processBlockEventDetails( player, prisonBlock, + targetBlock, eventType, chance, blockEvent, triggered, + cmdTasks, ++row ); } PrisonCommandTasks.submitTasks( player, cmdTasks ); } + + return blockEventsRan; } - -// /** -// *

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

    -// * -// * @param blockCount -// * @param player -// */ -// @Deprecated -// public void processBlockBreakEventCommands( int blockCount, Player player, -// BlockEventType eventType, String triggered ) { -// -// if ( getBlockEvents().size() > 0 ) { -// Random random = new Random(); -// -// for ( int i = 0; i < blockCount; i ++ ) { -// -// for ( MineBlockEvent blockEvent : getBlockEvents() ) { -// double chance = random.nextDouble() * 100; -// -// processBlockEventDetails( player, null, eventType, chance, blockEvent, triggered ); -// } -// -// } -// } -// } - - private void processBlockEventDetails( Player player, PrisonBlock prisonBlock, + + private int processBlockEventDetails( Player player, PrisonBlock prisonBlock, MineTargetPrisonBlock targetBlock, BlockEventType eventType, double chance, MineBlockEvent blockEvent, String triggered, List cmdTasks, int row ) { - + int blockEventsRan = 0; + boolean fireEvent = blockEvent.isFireEvent( chance, eventType, targetBlock, triggered ); @@ -629,6 +579,8 @@ private void processBlockEventDetails( Player player, PrisonBlock prisonBlock, perms == null || perms.trim().length() == 0 ) { + + blockEventsRan++; DecimalFormat dFmt = Prison.get().getDecimalFormat( "#,##0.0000" ); @@ -639,110 +591,58 @@ private void processBlockEventDetails( Player player, PrisonBlock prisonBlock, cmdTask.setTaskMode( blockEvent.getTaskMode() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockName, originalBlock.getBlockName() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.mineName, getName() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.blockName, originalBlock.getBlockName() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.mineName, getName() ); if ( targetBlock.getLocation() != null ) { Location location = targetBlock.getLocation(); - cmdTask.addCustomPlaceholder( CustomPlaceholders.locationWorld, location.getWorld().getName() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.locationX, Integer.toString( location.getBlockX() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.locationY, Integer.toString( location.getBlockY() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.locationZ, Integer.toString( location.getBlockZ() )); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.locationWorld, location.getWorld().getName() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.locationX, Integer.toString( location.getBlockX() )); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.locationY, Integer.toString( location.getBlockY() )); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.locationZ, Integer.toString( location.getBlockZ() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.coordinates, location.toCoordinates() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.worldCoordinates, location.toWorldCoordinates() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.coordinates, location.toCoordinates() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.worldCoordinates, location.toWorldCoordinates() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockCoordinates, targetBlock.getBlockCoordinates() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.blockCoordinates, targetBlock.getBlockCoordinates() ); } // cmdTask.addCustomPlaceholder( CustomPlaceholders.blockCoordinates, prisonBlock.getBlockCoordinates() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockChance, dFmt.format( originalBlock.getChance() ) ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.blockChance, dFmt.format( originalBlock.getChance() ) ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blocksPlaced, Integer.toString( originalBlock.getBlockPlacedCount() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockRemaining, Long.toString( originalBlock.getBlockCountUnsaved() )); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.blocksPlaced, Integer.toString( originalBlock.getBlockPlacedCount() )); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.blockRemaining, Long.toString( originalBlock.getBlockCountUnsaved() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blocksMinedTotal, Long.toString( originalBlock.getBlockCountSession() ) ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.blocksMinedTotal, Long.toString( originalBlock.getBlockCountSession() ) ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.mineBlocksRemaining, Integer.toString( getRemainingBlockCount() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.mineBlocksRemainingPercent, Double.toString( getPercentRemainingBlockCount() ) ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.mineBlocksTotalMined, Long.toString( getTotalBlocksMined() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.mineBlocksSize, Integer.toString( getBounds().getTotalBlockCount() )); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.mineBlocksRemaining, Integer.toString( getRemainingBlockCount() )); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.mineBlocksRemainingPercent, Double.toString( getPercentRemainingBlockCount() ) ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.mineBlocksTotalMined, Long.toString( getTotalBlocksMined() )); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.mineBlocksSize, Integer.toString( getBounds().getTotalBlockCount() )); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockIsAir, Boolean.toString( targetBlock.getPrisonBlock().isAir() )); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.blockIsAir, Boolean.toString( targetBlock.getPrisonBlock().isAir() )); if ( prisonBlock != null ) { - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockMinedName, prisonBlock.getBlockName() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockMinedNameFormal, prisonBlock.getBlockNameFormal() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.blockMinedBlockType, prisonBlock.getBlockType().name() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.blockMinedName, prisonBlock.getBlockName() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.blockMinedNameFormal, prisonBlock.getBlockNameFormal() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.blockMinedBlockType, prisonBlock.getBlockType().name() ); } - cmdTask.addCustomPlaceholder( CustomPlaceholders.eventType, eventType.name() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.eventTriggered, triggered ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.eventType, eventType.name() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.eventTriggered, triggered ); cmdTasks.add( cmdTask ); - -// cmdTask.submitCommandTask( player, blockEvent.getCommand(), blockEvent.getTaskMode() ); - -// { -// -// String formatted = blockEvent.getCommand() -// .replace( "{msg}", "prison utils msg {player} " ) -// .replace( "{broadcast}", "prison utils broadcast " ) -// .replace("{player}", player.getName()) -// .replace("{player_uid}", player.getUUID().toString()); -// -// // Split multiple commands in to a List of individual tasks: -// List tasks = new ArrayList<>( -// Arrays.asList( formatted.split( ";" ) )); -// -// -// if ( tasks.size() > 0 ) { -// -// String errorMessage = "BlockEvent: Player: " + player.getName(); -// -// boolean playerTask = blockEvent.getTaskMode() == TaskMode.inlinePlayer || -// blockEvent.getTaskMode() == TaskMode.syncPlayer; -// -// PrisonDispatchCommandTask task = -// new PrisonDispatchCommandTask( tasks, errorMessage, -// player, playerTask ); -// -// -// switch ( blockEvent.getTaskMode() ) -// { -// case inline: -// case inlinePlayer: -// // Don't submit, but run it here within this thread: -// task.run(); -// break; -// -// case sync: -// case syncPlayer: -// //case "async": // async will cause failures so run as sync: -// -// // submit task: -// @SuppressWarnings( "unused" ) -// int taskId = PrisonTaskSubmitter.runTaskLater(task, 0); -// break; -// -// default: -// break; -// } -// -// } -// -// -//// PrisonAPI.dispatchCommand(formatted); -// } } } + + return blockEventsRan; } @Override @@ -778,9 +678,6 @@ public boolean checkZeroBlockReset() { * triggered by a player. * */ -// public void manualReset() { -// manualReset( MineResetScheduleType.FORCED ); -// } public void manualReset( MineResetScheduleType resetType ) { if ( !isVirtual() ) { @@ -852,37 +749,6 @@ private void manualReset( MineResetScheduleType resetType, double delayActionSec setMineResetStartTimestamp( System.currentTimeMillis() ); -// // Lock the mine's mutex if it's still minable. Otherwise skip it since the -// // state has been incremented by one already. -// if ( getMineStateMutex().isMinable() ) { -// -// getMineStateMutex().setMineStateResetStart(); -// } -// else if ( getMineStateMutex().getMineStateSn() > 1 ) { -// -// // synchronizing on the mutex this will allow only one thread to be -// // processed at a time, which will weed out extra threads from being -// // wrongfully shutdown. Based upon this "technique" the last thread to -// // be paused by this synchronized block will be the one that will actually -// // initiate the reset. -// if ( getMineStateMutex().getMineStateSn() > 1 ) { -// -// // This may be a double submission sinc the mineStateSn should only be 1 at this -// // point. So release this lock and shutdown this duplicate submission. -// getMineStateMutex().setMineStateResetFinished(); -// -// // duplicate reset request, so exit... -// return; -// } -// -// } - - - - // cancel existing job: - if ( getTaskId() != null ) { - PrisonTaskSubmitter.cancelTask( getTaskId() ); - } // Clear jobStack and set currentJob to run the RESET with zero delay: getJobStack().clear(); diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineSweeperTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineSweeperTask.java index 8d174f640..5bff879f9 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineSweeperTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineSweeperTask.java @@ -21,8 +21,6 @@ public void run() { this.mine.submitAsyncTask( callbackAsync, 0 ); } - } - } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java index 7e64551c7..d9b0f1f81 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MineTasks.java @@ -8,6 +8,7 @@ import tech.mcprison.prison.internal.block.Block; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.mines.PrisonMines; +import tech.mcprison.prison.mines.data.Mine.MineNotificationMode; import tech.mcprison.prison.mines.data.MineScheduler.MineJob; import tech.mcprison.prison.mines.tasks.MineChangeBlockTask; import tech.mcprison.prison.output.Output; @@ -23,7 +24,6 @@ public abstract class MineTasks public MineTasks() { super(); - } @@ -40,31 +40,22 @@ public MineTasks() { */ @Override protected void initialize() { - super.initialize(); + super.initialize(); } - /** * This should be used to submit async tasks. * * @param callbackAsync */ -// @Override -// public int submitAsyncTask( PrisonRunnable callbackAsync ) { -// return submitAsyncTask( callbackAsync, 0L ); -// } @Override public int submitAsyncTask( PrisonRunnable callbackAsync, long delay ) { return Prison.get().getPlatform().getScheduler().runTaskLaterAsync( callbackAsync, getResetPagePageSubmitDelayTicks() + delay ); } -// @Override -// public int submitSyncTask( PrisonRunnable callbackSync ) { -// return submitSyncTask( callbackSync, 0L ); -// } @Override public int submitSyncTask( PrisonRunnable callbackSync, long delay ) { @@ -92,38 +83,39 @@ public int submitSyncTask( PrisonRunnable callbackSync, long delay ) { */ @Override public long teleportAllPlayersOut() { - long start = System.currentTimeMillis(); - - if ( isVirtual() ) { - return 0; - } - - World world = getBounds().getCenter().getWorld(); - - try { - if ( isEnabled() && world != null ) { - List players = (world.getPlayers() != null ? world.getPlayers() : - Prison.get().getPlatform().getOnlinePlayers()); - for (Player player : players) { - if ( getBounds().withinIncludeTopBottomOfMine(player.getLocation()) ) { - - teleportPlayerOut(player); - } - } - } - - } - catch (Exception e) { - Output.get().logError("&cMineReset: Failed to TP players out of mine. mine= " + - getName(), e); + long start = System.currentTimeMillis(); + + if ( isVirtual() ) { + return 0; + } + + World world = getBounds().getCenter().getWorld(); + + try { + if ( isEnabled() && world != null ) { + List players = (world.getPlayers() != null ? world.getPlayers() : + Prison.get().getPlatform().getOnlinePlayers()); + for (Player player : players) { + if ( getBounds().withinIncludeTopBottomOfMine(player.getLocation()) ) { + + teleportPlayerOut(player); + } + } + } + + } + catch (Exception e) { + Output.get().logError("&cMineReset: Failed to TP players out of mine. mine= " + + getName(), e); } - return System.currentTimeMillis() - start; + + return System.currentTimeMillis() - start; } @Override public void teleportPlayerOut(Player player) { - teleportPlayerOut( player, "spawn" ); + teleportPlayerOut( player, "spawn" ); } /** @@ -154,78 +146,56 @@ public void teleportPlayerOut(Player player) { */ @Override public Location teleportPlayerOut(Player player, String targetLocation) { - Location tpTargetLocation = null; - - if ( isVirtual() ) { - // ignore: - } - else - if ( !isEnabled() ) { - player.sendMessage( - String.format( "&7MineReset: Teleport failure: Mine is not enabled. " + - "Ensure world exists. mine= &3%s ", - getName() )); - } - else { -// Location altTp = alternativeTpLocation(); - tpTargetLocation = "spawn".equalsIgnoreCase( targetLocation ) && isHasSpawn() ? - getSpawn() : alternativeTpLocation(); - - // Player needs to stand on something. If block below feet is air, change it to a - // glass block: - Location targetGround = new Location( tpTargetLocation ); - targetGround.setY( tpTargetLocation.getBlockY() - 1 ); - - Block pBlock = targetGround.getBlockAt(); - if ( pBlock.isEmpty() ) { - pBlock.setPrisonBlock( PrisonBlock.GLASS );; + Location tpTargetLocation = null; + + if ( isVirtual() ) { + // ignore: + } + else + if ( !isEnabled() ) { + player.sendMessage( + String.format( "&7MineReset: Teleport failure: Mine is not enabled. " + + "Ensure world exists. mine= &3%s ", + getName() )); } - - player.teleport( tpTargetLocation ); - - - -// PrisonMines.getInstance().getMinesMessages().getLocalizable("teleported") -// .withReplacements(this.getName()).sendTo(player); - } - - return tpTargetLocation; + else { + tpTargetLocation = "spawn".equalsIgnoreCase( targetLocation ) && isHasSpawn() ? + getSpawn() : alternativeTpLocation(); + + // Player needs to stand on something. If block below feet is air, change it to a + // glass block: + Location targetGround = new Location( tpTargetLocation ); + targetGround.setY( tpTargetLocation.getBlockY() - 1 ); + + Block pBlock = targetGround.getBlockAt(); + if ( pBlock.isEmpty() ) { + pBlock.setPrisonBlock( PrisonBlock.GLASS );; + } + + player.teleport( tpTargetLocation ); + + } + + return tpTargetLocation; } @Override public void submitTeleportGlassBlockRemoval() { -// Location altTp = alternativeTpLocation(); - Location tpTargetLocation = isHasSpawn() ? getSpawn() : alternativeTpLocation(); - - Location glassBlockLocation = new Location( tpTargetLocation ); - int newY = tpTargetLocation.getBlockY() - 1; - glassBlockLocation.setY( newY ); - - - MineChangeBlockTask changeBlockTask = - new MineChangeBlockTask( glassBlockLocation, - PrisonBlock.AIR, PrisonBlock.GLASS ); - - int delayInTicks = 10; - PrisonTaskSubmitter.runTaskLater( changeBlockTask, delayInTicks ); + Location tpTargetLocation = isHasSpawn() ? getSpawn() : alternativeTpLocation(); + + Location glassBlockLocation = new Location( tpTargetLocation ); + int newY = tpTargetLocation.getBlockY() - 1; + glassBlockLocation.setY( newY ); + + + MineChangeBlockTask changeBlockTask = + new MineChangeBlockTask( glassBlockLocation, + PrisonBlock.AIR, PrisonBlock.GLASS ); + + int delayInTicks = 10; + PrisonTaskSubmitter.runTaskLater( changeBlockTask, delayInTicks ); - -// Block block = glassBlockLocation.getBlockAt(); -// if ( block != null ) { -// PrisonBlock prisonBlock = block.getPrisonBlock(); -// -// if ( prisonBlock != null && prisonBlock.equals( PrisonBlock.GLASS ) ) { -// // The glass block is under the player's feet so submit to remove it: -// -// MineChangeBlockTask changeBlockTask = -// new MineChangeBlockTask( glassBlockLocation, PrisonBlock.AIR ); -// -// int delayInTicks = 10; -// PrisonTaskSubmitter.runTaskLater( changeBlockTask, delayInTicks ); -// } -// } - } /** @@ -246,7 +216,7 @@ public Location alternativeTpLocation() { Location altTp = new Location( getBounds().getCenter() ); int y = getBounds().getyBlockMax() + 2; - altTp.setY( y ); + altTp.setY( y ); return altTp; } @@ -256,53 +226,62 @@ public Location alternativeTpLocation() @Override protected void broadcastResetMessageToAllPlayersWithRadius() { -// long start = System.currentTimeMillis(); - if ( isVirtual() || getResetTime() <= 0 ) { - // ignore: - } - else - if ( getNotificationMode() != MineNotificationMode.disabled ) { - World world = getBounds().getCenter().getWorld(); - - if ( world != null ) { - List players = (world.getPlayers() != null ? world.getPlayers() : - Prison.get().getPlatform().getOnlinePlayers()); - for (Player player : players) { - - // Check for either mode: Within the mine, or by radius from mines center: - if ( getNotificationMode() == MineNotificationMode.within && - getBounds().withinIncludeTopBottomOfMine(player.getLocation() ) || - getNotificationMode() == MineNotificationMode.radius && - getBounds().within(player.getLocation(), getNotificationRadius()) ) { - - if ( !isUseNotificationPermission() || - isUseNotificationPermission() && - player.hasPermission( getMineNotificationPermissionName() ) ) { - - - PrisonMines.getInstance().getMinesMessages() - .getLocalizable("reset_message").withReplacements( getTag() ) - .sendTo(player); - -// player.sendMessage( "The mine " + getName() + " has just reset." ); - } - } - } - - } - - } + if ( isVirtual() || getResetTime() <= 0 ) { + // ignore: + } + else + if ( getNotificationMode() != MineNotificationMode.disabled ) { + World world = getBounds().getCenter().getWorld(); + + if ( world != null ) { + + boolean useWorld = getNotificationMode() != MineNotificationMode.server && + world != null && world.getPlayers() != null; + + List players = + useWorld ? + world.getPlayers() : + Prison.get().getPlatform().getOnlinePlayers(); + + for (Player player : players) { + + // Check for either mode: Within the mine, or by radius from mines center: + if ( + getNotificationMode() == MineNotificationMode.server || + + getNotificationMode() == MineNotificationMode.world && + getBounds().getMin().getWorld().getName().equalsIgnoreCase( + player.getLocation().getWorld().getName() ) || + + getNotificationMode() == MineNotificationMode.within && + getBounds().withinIncludeTopBottomOfMine(player.getLocation() ) || + + getNotificationMode() == MineNotificationMode.radius && + getBounds().within(player.getLocation(), getNotificationRadius()) ) { + + if ( !isUseNotificationPermission() || + isUseNotificationPermission() && + player.hasPermission( getMineNotificationPermissionName() ) ) { + + + PrisonMines.getInstance().getMinesMessages() + .getLocalizable("reset_message").withReplacements( getTag() ) + .sendTo(player); + + } + } + } + + } + + } -// long stop = System.currentTimeMillis(); - -// setStatsMessageBroadcastTimeMS( stop - start ); } @Override protected void broadcastSkipResetMessageToAllPlayersWithRadius() { -// long start = System.currentTimeMillis(); if ( isVirtual() || getResetTime() <= 0 ) { // ignore: @@ -317,13 +296,28 @@ else if ( PrisonMines.getInstance().getMinesMessages() World world = getBounds().getCenter().getWorld(); if ( world != null ) { - List players = (world.getPlayers() != null ? world.getPlayers() : - Prison.get().getPlatform().getOnlinePlayers()); + + boolean useWorld = getNotificationMode() != MineNotificationMode.server && + world != null && world.getPlayers() != null; + + List players = + useWorld ? + world.getPlayers() : + Prison.get().getPlatform().getOnlinePlayers(); + for (Player player : players) { // Check for either mode: Within the mine, or by radius from mines center: - if ( getNotificationMode() == MineNotificationMode.within && + if ( + getNotificationMode() == MineNotificationMode.server || + + getNotificationMode() == MineNotificationMode.world && + getBounds().getMin().getWorld().getName().equalsIgnoreCase( + player.getLocation().getWorld().getName() ) || + + getNotificationMode() == MineNotificationMode.within && getBounds().withinIncludeTopBottomOfMine(player.getLocation() ) || + getNotificationMode() == MineNotificationMode.radius && getBounds().within(player.getLocation(), getNotificationRadius()) ) { @@ -336,7 +330,6 @@ else if ( PrisonMines.getInstance().getMinesMessages() .getLocalizable("skip_reset_message").withReplacements( getTag() ) .sendTo(player); -// player.sendMessage( "The mine " + getName() + " has just reset." ); } } } @@ -345,51 +338,61 @@ else if ( PrisonMines.getInstance().getMinesMessages() } -// long stop = System.currentTimeMillis(); - -// setStatsMessageBroadcastTimeMS( stop - start ); } @Override protected void broadcastPendingResetMessageToAllPlayersWithRadius(MineJob mineJob) { - if ( isVirtual() || getResetTime() <= 0) { - // ignore: - } - else - if ( getNotificationMode() != MineNotificationMode.disabled ) { - World world = getBounds().getCenter().getWorld(); - - if ( world != null ) { - List players = (world.getPlayers() != null ? world.getPlayers() : - Prison.get().getPlatform().getOnlinePlayers()); - for (Player player : players) { - // Check for either mode: Within the mine, or by radius from mines center: - if ( getNotificationMode() == MineNotificationMode.within && - getBounds().withinIncludeTopBottomOfMine(player.getLocation() ) || - getNotificationMode() == MineNotificationMode.radius && - getBounds().within(player.getLocation(), getNotificationRadius()) ) { - - if ( !isUseNotificationPermission() || - isUseNotificationPermission() && - player.hasPermission( getMineNotificationPermissionName() ) ) { - - PrisonMines.getInstance().getMinesMessages() - .getLocalizable("reset_warning") - .withReplacements( getTag(), - Text.getTimeUntilString(Math.round(mineJob.getResetInSec() * 1000.0d)) ) - .sendTo(player); - -// player.sendMessage( "The mine " + getName() + " will reset in " + -// Text.getTimeUntilString(mineJob.getResetInSec() * 1000) ); - } - - - } - } - - } - } + if ( isVirtual() || getResetTime() <= 0) { + // ignore: + } + else + if ( getNotificationMode() != MineNotificationMode.disabled ) { + World world = getBounds().getCenter().getWorld(); + + if ( world != null ) { + + boolean useWorld = getNotificationMode() != MineNotificationMode.server && + world != null && world.getPlayers() != null; + + List players = + useWorld ? + world.getPlayers() : + Prison.get().getPlatform().getOnlinePlayers(); + + for (Player player : players) { + // Check for either mode: Within the mine, or by radius from mines center: + if ( + getNotificationMode() == MineNotificationMode.server || + + getNotificationMode() == MineNotificationMode.world && + getBounds().getMin().getWorld().getName().equalsIgnoreCase( + player.getLocation().getWorld().getName() ) || + + getNotificationMode() == MineNotificationMode.within && + getBounds().withinIncludeTopBottomOfMine(player.getLocation() ) || + + getNotificationMode() == MineNotificationMode.radius && + getBounds().within(player.getLocation(), getNotificationRadius()) ) { + + if ( !isUseNotificationPermission() || + isUseNotificationPermission() && + player.hasPermission( getMineNotificationPermissionName() ) ) { + + PrisonMines.getInstance().getMinesMessages() + .getLocalizable("reset_warning") + .withReplacements( getTag(), + Text.getTimeUntilString(Math.round(mineJob.getResetInSec() * 1000.0d)) ) + .sendTo(player); + + } + + + } + } + + } + } } } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MinesConfig.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MinesConfig.java index 008da7dda..59913cdd0 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MinesConfig.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/MinesConfig.java @@ -29,41 +29,18 @@ */ public class MinesConfig implements FileIOData { -// /** -// * True if randomized blocks for mines should be cached for faster resets. False otherwise -// */ -// public boolean asyncReset = true; /** * True if reset warnings an reset broadcasts should be enabled. False otherwise */ public boolean resetMessages = true; -// /** -// * True if broadcasts should only be enabled in the worlds specified in the worlds list. -// * False otherwise. -// * -// * @see MinesConfig#worlds -// */ -// public boolean multiworld = false; - -// /** -// * True if only blocks that are air should be replaced. False otherwise -// */ -// public boolean fillMode = false; /** * The duration between mine resets in seconds. */ - public int resetTime = MineData.MINE_RESET__TIME_SEC__DEFAULT; + public int resetTime = Mine.MINE_RESET__TIME_SEC__DEFAULT; -// /** -// * The worlds that reset messages should be broadcasted to. Ignored if multiworld is disabled. -// * -// * @see MinesConfig#multiworld -// */ -// public ArrayList worlds = -// new ArrayList<>(Arrays.asList(new String[]{"plots", "mines"})); /** * The time between mine reset warnings. Ignored if resetMessages is disabled. diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/OnStartupRefreshBlockBreakCountSyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/OnStartupRefreshBlockBreakCountSyncTask.java index d2a7f2964..3c5376bf8 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/data/OnStartupRefreshBlockBreakCountSyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/data/OnStartupRefreshBlockBreakCountSyncTask.java @@ -1,68 +1,218 @@ package tech.mcprison.prison.mines.data; import java.text.DecimalFormat; +import java.util.ArrayList; import java.util.List; +import java.util.TreeSet; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.tasks.PrisonRunnable; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; import tech.mcprison.prison.util.Location; public class OnStartupRefreshBlockBreakCountSyncTask implements PrisonRunnable { - + + private static OnStartupRefreshBlockBreakCountSyncTask instance; + private MineReset mine; + private int jobId = 0; private List locations = null; private int position = 0; private int pages = 0; + private int pagesStart = 0; private int airCount = 0; private long elapsedNanos = 0; + private double elapsedMsTotal = 0; + private int errorCount = 0; private StringBuilder sbErrors = new StringBuilder(); + private String exceptionError; - public OnStartupRefreshBlockBreakCountSyncTask(MineReset mine) { - this.mine = mine; + private List processedMines; + private int countCurrentMine = 0; + private int countTotalMines = 0; + + + private OnStartupRefreshBlockBreakCountSyncTask() { + super(); + + this.processedMines = new ArrayList<>(); + } + + public static OnStartupRefreshBlockBreakCountSyncTask getInstance() { + if ( instance == null ) { + synchronized ( OnStartupRefreshBlockBreakCountSyncTask.class ) { + if ( instance == null ) { + instance = new OnStartupRefreshBlockBreakCountSyncTask(); + } + } + } + return instance; } - public static void submit( MineReset mine, long delay ) { + + public void submit( long delay ) { + + setJobId( PrisonTaskSubmitter.runTaskLater( this, delay) ); + + DecimalFormat dFmt = new DecimalFormat( "#,##0.0" ); + DecimalFormat iFmt = new DecimalFormat( "#,##0" ); + + long gapTicks = MineReset.MINE_RESET__AIR_COUNT_SUBMIT_GAP_TICKS; + + String msg = String.format( + "&dStartup Block Count Task Submitted " + + "&6to run in %s seconds, with a %s tick gap between " + + "each task.", + dFmt.format(delay / 20), + iFmt.format( gapTicks ) + ); + + Output.get().logInfo( msg ); - OnStartupRefreshBlockBreakCountSyncTask syncTask = - new OnStartupRefreshBlockBreakCountSyncTask( mine ); + } + + private Mine getNextMine() { + Mine mine = null; + + + List mines = PrisonMines.getInstance().getMineManager().getMines(); + + if ( countTotalMines == 0 ) { + + countTotalMines = mines.size(); + } + + // When the server starts, all mines will have a resetCount of zero. + // So to get the "nextMine", just need to go through the list of all mines + // and grab the first one that is zero. Then set the resetCount on the + // selected mine to 1 so it will not be chosen again. And then return + // the selected mine. + for (Mine m : mines ) { + + // Check to see if we can even submit the job: + if ( !m.isVirtual() && + m.getResetCount() == 0 + && m.refreshAirCountSyncTaskCheckBeforeSubmit() ) { + + // Prevents the mine from being counted again when the next + // check is ran. + m.setResetCount( 1 ); + + countCurrentMine++; + + // Sets this mine to be processed next: + mine = m; + + // Added this mine to the processedMines list even though it has not + // been processed yet: + processedMines.add( m ); + + break; + } + } + + // If no mine has been selected, then that means all mines were + // processed, so perform the ending tasks of printing out the + // list of mines that could not be processed and the totals message. + if ( mine == null ) { + // done processing: + + TreeSet minesNotProcessed = new TreeSet<>( mines ); + minesNotProcessed.removeAll(processedMines); + + for (Mine m : minesNotProcessed) { + countCurrentMine++; - // Check to see if we can even submit the job: - if ( mine.refreshAirCountSyncTaskCheckBeforeSubmit() ) { + String msg = String.format( + "MineReset startup air-count: Mine [%3d of %3d]: %-10s " + + " Skipped: virtual: %b resetCounts: %s", + countCurrentMine, + countTotalMines, + m.getName(), + m.isVirtual(), + m.getResetCount() + + ); + + Output.get().logInfo( msg ); + + } + + String message = String.format( + "MineReset startup air-count: Completed. [%3d of %3d]: " + + "Mines not processed: %d", + countCurrentMine, + countTotalMines, + minesNotProcessed.size() ); - // The first phase generates a List of Locations which - // can be ran async... - syncTask.setJobId( mine.submitAsyncTask( syncTask, delay ) ); + Output.get().logInfo( message ); } + return mine; } private void resubmit() { - // Must run synchronously!! - setJobId( mine.submitSyncTask( this, 0 ) ); + long delay = 0; + + if ( mine == null ) { + mine = getNextMine(); + locations = null; + position = 0; + + pagesStart = pages; + + elapsedNanos = 0; + + delay = MineReset.MINE_RESET__AIR_COUNT_SUBMIT_GAP_TICKS; + } + + if ( mine != null ) { + + // Must run synchronously!! + setJobId( PrisonTaskSubmitter.runTaskLater( this, delay) ); + } } @Override public void run() { + + if ( mine == null ) { + mine = getNextMine(); + locations = null; + } + if ( locations == null ) { - long nanoStart = System.nanoTime(); - locations = this.mine.refreshAirCountSyncTaskBuildLocations(); - long nanoEnd = System.nanoTime(); - long elpased = (nanoEnd - nanoStart ); - this.elapsedNanos += elpased; + if ( mine != null ) { + + long nanoStart = System.nanoTime(); + locations = this.mine.refreshAirCountSyncTaskBuildLocations(); + long nanoEnd = System.nanoTime(); + long elpased = (nanoEnd - nanoStart ); + this.elapsedNanos += elpased; + + } - resubmit(); } - else { + + if ( mine == null ) { + // No mine is available, either they are all processed, or none exist on + // the server yet (new startup), so exit without resubmitting: + return; + } + + { + pages++; long nanoStart = System.nanoTime(); @@ -74,17 +224,17 @@ public void run() { mine.refreshAirCountSyncTaskSetLocation( targetLocation, this ); position++; - if ( (i - start) % 500 == 0 ) { + if ( i != start && (i - start) % 500 == 0 ) { long nanoEnd = System.nanoTime(); long elpased = (nanoEnd - nanoStart ); - long elapsedMs = elpased / 1000000; + long elapsedMs = elpased / 1_000_000; if ( elapsedMs > 20 ) { // Check every 500 blocks and if been running longer than 20 ms then yield to prevent lag this.elapsedNanos += elpased; - pages++; +// pages++; // Need to yield and resubmit resubmit(); @@ -96,7 +246,6 @@ public void run() { // It will only hit this point when done processing all of the locations: - pages++; mine.setAirCount( getAirCount() ); mine.setBlockBreakCount( mine.getBlockBreakCount() + getAirCount() ); @@ -106,20 +255,28 @@ public void run() { this.elapsedNanos += elpased; double elapsedMs = ((double) elapsedNanos) / 1000000d; + elapsedMsTotal += elapsedMs; mine.setAirCountElapsedTimeMs( (long) elapsedMs ); mine.setAirCountTimestamp( System.currentTimeMillis() ); - if ( Output.get().isDebug() ) { +// if ( Output.get().isDebug() ) + { + DecimalFormat dFmt = Prison.get().getDecimalFormatDouble(); DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); String message = String.format( - "MineReset startup air-count: Mine: %-6s " + - " blocks: %10s pages: %s elapsed %s ms", + "MineReset startup air-count: Mine [%3d of %3d]: %-10s " + + " blocks: %10s pages: [%3s: %3s] [%9s: %9s ms]", + countCurrentMine, + countTotalMines, mine.getName(), iFmt.format( locations.size() ), + iFmt.format( pages - pagesStart ), iFmt.format( pages ), - dFmt.format(elapsedMs) ); + dFmt.format(elapsedMs), + dFmt.format(elapsedMsTotal) + ); Output.get().logInfo( message ); @@ -128,14 +285,37 @@ public void run() { if ( getErrorCount() > 0 ) { String message = String.format( "MineReset.refreshAirCountAsyncTask: Error counting air blocks: Mine=%s: " + - "errorCount=%d blocks: %s : %s", mine.getName(), getErrorCount(), + "errorCount=%d blocks: %s : %s ExcptError: [%s]", + mine.getName(), getErrorCount(), (getErrorCount() > 20 ? "(first 20)" : ""), - getSbErrors().toString() ); + getSbErrors().toString(), + (getExceptionError() == null ? "" : getExceptionError()) + ); Output.get().logWarn( message ); + + + // Since the error has beep logged, reset it. + setExceptionError( null ); + getSbErrors().setLength( 0 ); + setErrorCount( 0 ); } + + // Finalize by setting mine and locations to null so it will reset properly the next time: + locations = null; + mine = null; + } + // Submit the next mine, which will be assigned in resubmit(): + resubmit(); + } + + public MineReset getMine() { + return mine; + } + public void setMine(MineReset mine) { + this.mine = mine; } public int getJobId() { @@ -171,4 +351,11 @@ public StringBuilder getSbErrors() { public void setSbErrors( StringBuilder sbErrors ) { this.sbErrors = sbErrors; } + + protected String getExceptionError() { + return exceptionError; + } + protected void setExceptionError(String exceptionError) { + this.exceptionError = exceptionError; + } } 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 c34a3d527..c7aeb08f3 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 @@ -33,6 +33,13 @@ public enum BlockEventType { all, blockBreak, + + /** + * The EntityExplodeEvent is a bukkit event, but other plugins, such as ExcellentEnchants + * will use it too. + */ + EntityExplodeEvent, + TEXplosion, CEXplosion, PEExplosive, // PrisonEnchant: Pulsi_'s plugin @@ -110,32 +117,6 @@ public static String getPrimaryEventTypes() { } -// public enum TaskMode { -// inline, -// inlinePlayer, -// -// sync, -// syncPlayer; -// -// public static TaskMode fromString( String taskMode ) { -// TaskMode results = inline; -// -// if ( taskMode != null ) { -// -// for ( TaskMode mode : values() ) { -// if ( mode.name().equalsIgnoreCase( taskMode ) ) { -// results = mode; -// -// break; -// } -// } -// } -// -// return results; -// } -// -// } - public MineBlockEvent( double chance, String permission, String command, TaskMode taskMode, BlockEventType eventType, String triggered ) { @@ -169,8 +150,6 @@ public String toSaveString() { } nFmt.format( getChance() ); -// DecimalFormat dFmt = Prison.get().getDecimalFormat("0.00000"); - String cmd = getCommand().replace( "|", ENCODED_PIPE ); return nFmt.format( getChance() ) + "|" + @@ -190,38 +169,6 @@ public static MineBlockEvent fromSaveString( String blockEventString, String min results = fromStringV1( blockEventString, mineName ); } -// if ( chancePermCommand != null && chancePermCommand.trim().length() > 0 ) { -// String[] cpc = chancePermCommand.split( "\\|" ); -// -// double chance = cpc.length >= 1 ? Double.parseDouble( cpc[0] ) : 0d; -// -// String permission = cpc.length >= 2 ? cpc[1] : ""; -// if ( permission == null || "none".equalsIgnoreCase( permission) ) { -// permission = ""; -// } -// -// String command = cpc.length >= 3 ? cpc[2] : ""; -// -// String mode = cpc.length >= 4 ? cpc[3] : "inline"; -// -// if ( !"sync".equalsIgnoreCase( mode ) && !"inline".equalsIgnoreCase( mode ) ) { -// mode = "sync"; -// } -//// boolean async = (asyncStr != null && -//// "true".equalsIgnoreCase( asyncStr ) ); -// -// BlockEventType eventType = cpc.length >= 5 ? BlockEventType.fromString( cpc[4] ) : -// BlockEventType.eventTypeAll; -// -// String triggered = cpc.length >= 6 && !"none".equals(cpc[5]) ? cpc[5] : null; -// -// -// if ( command != null && command.trim().length() > 0 ) { -// -// results = new MineBlockEvent( chance, permission, command, mode, eventType, triggered ); -// } -// } - return results; } @@ -247,7 +194,6 @@ private static MineBlockEvent fromStringV1( String chancePermCommand, String min chance = nDbl.doubleValue(); } -// chance = cpc.length >= 1 ? Double.parseDouble( cpc[0] ) : 0d; } catch ( ParseException | NumberFormatException e ) { Output.get().logError( "Failure parsing a mine " + mineName + @@ -397,28 +343,6 @@ else if ( getTriggered() != null && } } - -// // First check chance, since that's perhaps the quickest check: -// if ( chance <= getChance() && -// -// isValidBlock( targetBlock ) && -// -// // Make sure we have the correct eventTypes: -// (eventType == BlockEventType.TEXplosion && -// eventType == getEventType() && -// ( getTriggered() == null || -// getTriggered().equalsIgnoreCase( triggered )) || -// -// getEventType() == BlockEventType.all || -// getEventType() == eventType) ) { -// -// // The check for the player's perms will have to be done outside of this -// // function. -// -// results = true; -// } - - return results; } @@ -430,8 +354,6 @@ private boolean isValidBlock( MineTargetPrisonBlock targetBlock) { } private boolean hasBlockType( MineTargetPrisonBlock targetBlock ) { -// PrisonBlockTypes prisonBlockTypes = Prison.get().getPlatform().getPrisonBlockTypes(); -// PrisonBlock block = prisonBlockTypes.getBlockTypesByName( blockName ); return getPrisonBlocks().contains( targetBlock.getPrisonBlock() ); } @@ -501,14 +423,4 @@ public void setPrisonBlocks( Set prisonBlocks ) { this.prisonBlocks = prisonBlocks; } - - -// public boolean isInline() { -// return "inline".equalsIgnoreCase( getMode() ); -// } -// public boolean isSync() { -// return "sync".equalsIgnoreCase( getMode() ); -// } - - } 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 2e6430a58..d65a77de2 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 @@ -289,8 +289,6 @@ private void generatePattern( Edges edge ) { private void generatePattern( Edges edge, World world, int xMin, int xMax, int yMin, int yMax, int zMin, int zMax) { try { - // Output.get().logInfo( "MineRest.resetSynchonouslyInternal() " + getName() ); - // Output.get().logInfo( "### MineLinerBuilder - xMin=%d, xMax=%d, yMin=%d, yMax=%d, zMin=%d, zMax=%d ", // xMin, xMax, yMin, yMax, zMin, zMax); @@ -501,58 +499,6 @@ private boolean isLadderBlock( int curr, int min, int max ) { ( curr >= (min + mid - range) && curr <= (min + mid + range)); -// if ( getLadderType() == LadderType.normal ) { -// -// results = len <= 5; -// -// if ( len > 5 ) { -// -// -// if ( curr == (min + mid) ) { -// results = true; -// } -// else { -// results = isEven ? -// // if distance is even, then next ladder position is mid - 1 -// ( curr == min + mid + 1 ) : -// // If odd, then one above and below mid: -// ( curr == min + mid + 1 || curr == min + mid - 1); -// } -// -// } -// -// } -// else if ( getLadderType() == LadderType.wide ) { -// -// results = len <= 7; -// -// if ( len > 7 ) { -// -// -// if ( curr == (min + mid) ) { -// results = true; -// } -// else { -// results = isEven ? -// // if distance is even, then next ladder position is mid - 1 through mid + 2 -// ( curr >= (min + mid - range + 1) && curr <= (min + mid + range ) ) : -// -// // If odd, then one above and below mid: -// ( curr >= (min + mid - range) && curr <= (min + mid + range)); -// } -// -// } -// } - - -// Output.get().logInfo( "#### isLadderBlock: curr=%d min=%d max=%d " + -// " len=%d mid=%d " + -// "isEven=%s results=%s " + -// " (min+mid)=%d ", -// curr, min, max, len, mid, -// (isEven ? "true" : "false"), -// (results ? "true" : "false"), (min+mid) ); - } return results; @@ -981,33 +927,6 @@ protected void apply2Dto3DPattern( Edges edge, String[][] pattern2d ) } - -// public boolean isPatternValidForSpigotVersion() { -// boolean results = true; -// -// try { -// -// String v = Prison.get().getMinecraftVersion(); -// -// String versionStr = v.substring( v.indexOf( "(MC:" ) + 4, v.lastIndexOf( "." ) ); -// -// -// Output.get().logInfo( "#### MineLinerBuilder : " + -// getPattern() + " " + getPatternMinVersion() + " : " + -// "Prison Version: " + v + " " + versionStr ); -// -// double version = Double.parseDouble( versionStr ); -// -// if ( version < getPatternMinVersion() ) { -// -// } -// } -// catch ( NumberFormatException e ) { -// // ignore... just use all patterns -// } -// -// return results; -// } public List>> getPattern3d() { return pattern3d; 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 6f2059a17..1c9b4a49c 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 @@ -47,93 +47,17 @@ public static TracerType fromString( String type ) { public void clearMine( Mine mine, MineResetType resetType ) { - if ( mine == null ) { - Output.get().logError(" #### Null MINE? ###"); - } - - if ( mine.isVirtual() ) { - // Mine is virtual and cannot be reset. Just skip this with no error messages. - return; - } - -// MineResetType resetType = tracer ? MineResetType.tracer : MineResetType.clear; + if ( mine == null ) { + Output.get().logError(" #### Null MINE? ###"); + } + + if ( mine.isVirtual() ) { + // Mine is virtual and cannot be reset. Just skip this with no error messages. + return; + } MinePagedResetAsyncTask resetTask = new MinePagedResetAsyncTask( mine, resetType ); resetTask.submitTaskAsync(); } -// public void clearMine( Mine mine, boolean tracer ) { -// -// if ( mine == null ) { -// Output.get().logError(" #### Null MINE? ###"); -// } -// try { -// -// if ( mine.isVirtual() ) { -// // Mine is virtual and cannot be reset. Just skip this with no error messages. -// return; -// } -// -// -// // Output.get().logInfo( "MineRest.resetSynchonouslyInternal() " + getName() ); -// -// Optional worldOptional = mine.getWorld(); -// World world = worldOptional.get(); -// -// -// PrisonBlock blockAirPB = new PrisonBlock( "AIR" ); -//// BlockType blockAirBT = BlockType.AIR; -// -// PrisonBlock blockRedPB = new PrisonBlock( "PINK_STAINED_GLASS" ); -//// BlockType blockRedBT = BlockType.PINK_STAINED_GLASS; -// -//// PrisonBlock blockRedstonePB = new PrisonBlock( "REDSTONE_BLOCK" ); -//// BlockType blockRedstoneBT = BlockType.REDSTONE_BLOCK; -// -// -// -// -// -// // Reset the block break count before resetting the blocks: -//// setBlockBreakCount( 0 ); -//// Random random = new Random(); -// -// int yMin = mine.getBounds().getyBlockMin(); -// int yMax = mine.getBounds().getyBlockMax(); -// -// int xMin = mine.getBounds().getxBlockMin(); -// int xMax = mine.getBounds().getxBlockMax(); -// -// int zMin = mine.getBounds().getzBlockMin(); -// int zMax = mine.getBounds().getzBlockMax(); -// -// for (int y = yMax; y >= yMin; y--) { -//// for (int y = getBounds().getyBlockMin(); y <= getBounds().getyBlockMax(); y++) { -// for (int x = xMin; x <= xMax; x++) { -// for (int z = zMin; z <= zMax; z++) { -// Location targetBlock = new Location(world, x, y, z); -// -// boolean xEdge = x == xMin || x == xMax; -// boolean yEdge = y == yMin || y == yMax; -// boolean zEdge = z == zMin || z == zMax; -// -// boolean isEdge = xEdge && yEdge || xEdge && zEdge || -// yEdge && zEdge; -// -// -// targetBlock.getBlockAt().setPrisonBlock( -// tracer && isEdge ? blockRedPB : blockAirPB ); -// } -// } -// } -// -// -// } -// catch (Exception e) { -// Output.get().logError("&cFailed to clear mine " + mine.getName() + -// " Error: [" + e.getMessage() + "]", e); -// } -// } - - } 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 2a1513338..fa095d3a8 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 @@ -35,6 +35,8 @@ import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.data.Mine; +import tech.mcprison.prison.mines.data.MineReset; +import tech.mcprison.prison.mines.data.OnStartupRefreshBlockBreakCountSyncTask; import tech.mcprison.prison.mines.data.MineScheduler.MineResetActions; import tech.mcprison.prison.mines.data.MineScheduler.MineResetScheduleType; import tech.mcprison.prison.mines.data.PrisonSortableResults; @@ -254,29 +256,13 @@ public void loadFromDbCollection( PrisonMines pMines ) { getMines().size(), offsetTimingMs)); -// // When finished loading the mines, then if there are any worlds that -// // could not be loaded, dump the details: -// List unavailableWorlds = getUnavailableWorldsListings(); -// for ( String uWorld : unavailableWorlds ) { -// Output.get().logInfo( uWorld ); -// } + // Count the blocks for the mines that were just loaded.. n-sec delay + long submitDelay = MineReset.MINE_RESET__AIR_COUNT_BASE_DELAY_TICKS; + OnStartupRefreshBlockBreakCountSyncTask.getInstance().submit( submitDelay ); -// // Submit all the loaded mines to run: -// int offset = 0; -// for ( Mine mine : mines ) -// { -// mine.submit(offset); -// offset += 5; -// } -// Output.get().logInfo("Mines are all queued to run auto resets."); } -// public void loadMine(String mineFile) throws IOException, MineException { -// Document document = coll.get(mineFile).orElseThrow(IOException::new); -// Mine m = new Mine(document); -// add(m, false, 0); -// } /** * Adds a {@link Mine} to this {@link MineManager} instance. @@ -287,7 +273,7 @@ public void loadFromDbCollection( PrisonMines pMines ) { * @return if the add was successful */ public boolean add(Mine mine) { - return add(mine, true, 0); + return add(mine, true, 0); } /** @@ -302,17 +288,17 @@ public boolean add(Mine mine) { * @return if the add was successful */ private boolean add(Mine mine, boolean save, int offsetTimingMs ) { - boolean results = false; + boolean results = false; - // not add if it already exists, or if the mine is null or does not have a valid name: + // not add if it already exists, or if the mine is null or does not have a valid name: if ( mine != null && mine.getName() != null && mine.getName().trim().length() > 0 && !getMines().contains(mine)) { - if ( save ) { - saveMine( mine ); - } - + if ( save ) { + saveMine( mine ); + } + results = getMines().add(mine); getMinesByName().put( mine.getName().toLowerCase(), mine ); @@ -324,24 +310,24 @@ private boolean add(Mine mine, boolean save, int offsetTimingMs ) { public boolean removeMine(String mineName){ - boolean results = false; - if ( mineName != null ) { - Mine mine = getMinesByName().get( mineName.toLowerCase() ); - if ( mine != null ) { - results = removeMine(mine); - } - } - - return results; + boolean results = false; + if ( mineName != null ) { + Mine mine = getMinesByName().get( mineName.toLowerCase() ); + if ( mine != null ) { + results = removeMine(mine); + } + } + + return results; } public boolean removeMine(Mine mine) { - boolean success = false; - if ( mine != null ) { - coll.delete( mine.getName() ); - getMinesByName().remove(mine.getName().toLowerCase()); - success = getMines().remove(mine); - } + boolean success = false; + if ( mine != null ) { + coll.delete( mine.getName() ); + getMinesByName().remove(mine.getName().toLowerCase()); + success = getMines().remove(mine); + } return success; } @@ -370,7 +356,7 @@ private void loadMines( long offsetTimingMs ) { * PrisonMines} */ public void saveMine(Mine mine) { - coll.save(mine.toDocument()); + coll.save( mine.getName(), mine.toDocument(), null, "Mine" ); } public void saveMines(){ @@ -381,11 +367,11 @@ public void saveMines(){ public void saveMinesIfUnsavedBlockCounts() { - for (Mine m : getMines()){ - if ( m.hasUnsavedBlockCounts() ) { - saveMine( m ); - } - } + for (Mine m : getMines()){ + if ( m.hasUnsavedBlockCounts() ) { + saveMine( m ); + } + } } @@ -430,9 +416,7 @@ public void rename( Mine mine, String newName ) { * does not exist by the specified name. */ public Mine getMine(String mineName) { - return (mineName == null ? null : getMinesByName().get( mineName.toLowerCase() )); - - //return mines.stream().filter(mine -> mine.getName().equals(name)).findFirst(); + return (mineName == null ? null : getMinesByName().get( mineName.toLowerCase() )); } public List getMines() { @@ -440,44 +424,44 @@ public List getMines() { } public PrisonSortableResults getMines( MineSortOrder sortOrder ) { - return getMines( sortOrder, getMines() ); + return getMines( sortOrder, getMines() ); } protected PrisonSortableResults getMines( MineSortOrder sortOrder, List mines ) { - PrisonSortableResults results = new PrisonSortableResults( sortOrder ); - - - // if invalid, then that's invalid, so default to sortOrder: - if ( sortOrder == MineSortOrder.invalid ) { - sortOrder = MineSortOrder.sortOrder; - } - - - for ( Mine mine : mines ) { - if ( mine.getSortOrder() < 0 ) { - results.getExclude().add( mine ); - } - else { - results.getInclude().add( mine ); - } + PrisonSortableResults results = new PrisonSortableResults( sortOrder ); + + + // if invalid, then that's invalid, so default to sortOrder: + if ( sortOrder == MineSortOrder.invalid ) { + sortOrder = MineSortOrder.sortOrder; + } + + + for ( Mine mine : mines ) { + if ( mine.getSortOrder() < 0 ) { + results.getExclude().add( mine ); + } + else { + results.getInclude().add( mine ); + } } - - // Sort first by name, then by other means if needed: - results.getInclude().sort( (a, b) -> a.getName().compareToIgnoreCase( b.getName()) ); - results.getExclude().sort( (a, b) -> a.getName().compareToIgnoreCase( b.getName()) ); - - if ( sortOrder == MineSortOrder.sortOrder || sortOrder == MineSortOrder.xSortOrder ) { - results.getInclude().sort( (a, b) -> Integer.compare( a.getSortOrder(), b.getSortOrder()) ); - results.getExclude().sort( (a, b) -> Integer.compare( a.getSortOrder(), b.getSortOrder()) ); - } - - // for now hold off on sorting by total blocks mined. - else if ( sortOrder == MineSortOrder.active || sortOrder == MineSortOrder.xActive ) { - results.getInclude().sort( (a, b) -> Long.compare(b.getTotalBlocksMined(), a.getTotalBlocksMined()) ); - results.getExclude().sort( (a, b) -> Long.compare(b.getTotalBlocksMined(), a.getTotalBlocksMined()) ); - } - - return results; + + // Sort first by name, then by other means if needed: + results.getInclude().sort( (a, b) -> a.getName().compareToIgnoreCase( b.getName()) ); + results.getExclude().sort( (a, b) -> a.getName().compareToIgnoreCase( b.getName()) ); + + if ( sortOrder == MineSortOrder.sortOrder || sortOrder == MineSortOrder.xSortOrder ) { + results.getInclude().sort( (a, b) -> Integer.compare( a.getSortOrder(), b.getSortOrder()) ); + results.getExclude().sort( (a, b) -> Integer.compare( a.getSortOrder(), b.getSortOrder()) ); + } + + // for now hold off on sorting by total blocks mined. + else if ( sortOrder == MineSortOrder.active || sortOrder == MineSortOrder.xActive ) { + results.getInclude().sort( (a, b) -> Long.compare(b.getTotalBlocksMined(), a.getTotalBlocksMined()) ); + results.getExclude().sort( (a, b) -> Long.compare(b.getTotalBlocksMined(), a.getTotalBlocksMined()) ); + } + + return results; } @@ -667,7 +651,7 @@ public void assignAvailableWorld( String worldName ) { // List remove = new ArrayList<>(); - long delay = 0; +// long delay = 0; for ( Mine mine : unenabledMines ) { if ( !mine.isEnabled() ) { @@ -692,7 +676,7 @@ public void assignAvailableWorld( String worldName ) { } // Run the air-counts now that mine can be activated: - mine.refreshBlockBreakCountUponStartup( delay++ ); +// mine.refreshBlockBreakCountUponStartup( delay++ ); } @@ -700,6 +684,12 @@ public void assignAvailableWorld( String worldName ) { // remove.add( mine ); } + + // Count the blocks for the mines that were just loaded.. n-sec delay + long submitDelay = MineReset.MINE_RESET__AIR_COUNT_BASE_DELAY_TICKS; + OnStartupRefreshBlockBreakCountSyncTask.getInstance().submit( submitDelay ); + + // // Purge all removed mines from the unenabledMines list: // if ( remove.size() > 0 ) { // unenabledMines.removeAll( remove ); @@ -723,30 +713,30 @@ public void assignAvailableWorld( String worldName ) { } public List getUnavailableWorldsListings() { - List results = new ArrayList<>(); - - if ( getUnavailableWorlds().size() > 0 ) { - results.add( "&cUnavailable Worlds: &3Deferred loading of mines." ); - - Set worlds = getUnavailableWorlds().keySet(); - - for ( String worldName : worlds ) { - int enabledCount = 0; - - List mines = getUnavailableWorlds().get( worldName ); - for ( Mine mine : mines ) { - if ( mine.isEnabled() ) { - enabledCount++; + List results = new ArrayList<>(); + + if ( getUnavailableWorlds().size() > 0 ) { + results.add( "&cUnavailable Worlds: &3Deferred loading of mines." ); + + Set worlds = getUnavailableWorlds().keySet(); + + for ( String worldName : worlds ) { + int enabledCount = 0; + + List mines = getUnavailableWorlds().get( worldName ); + for ( Mine mine : mines ) { + if ( mine.isEnabled() ) { + enabledCount++; + } } + results.add( + String.format( "&7 world: &3%s &7(&c%s mines enabled out &7of &c%s &7mines in the world) ", + worldName, Integer.toString( enabledCount ), + Integer.toString( mines.size() ))); } - results.add( - String.format( "&7 world: &3%s &7(&c%s mines enabled out &7of &c%s &7mines in the world) ", - worldName, Integer.toString( enabledCount ), - Integer.toString( mines.size() ))); - } - } - - return results; + } + + return results; } @@ -755,15 +745,14 @@ public List getUnavailableWorldsListings() { public String getTranslateMinesPlaceholder( PlaceholderIdentifier identifier ) { -// // placeholder Attributes: -// PlaceholderManager pman = Prison.get().getPlaceholderManager(); - - Player player = identifier.getPlayer(); - - PlaceHolderKey placeHolderKey = identifier.getPlaceholderKey(); - - Mine mine = null; + Player player = identifier.getPlayer(); + + PlaceHolderKey placeHolderKey = identifier.getPlaceholderKey(); + + + Mine mine = null; + if ( placeHolderKey.getPlaceholder().hasFlag( PlaceholderFlags.MINES ) || placeHolderKey.getPlaceholder().hasFlag( PlaceholderFlags.STATSMINES ) ) { @@ -771,6 +760,8 @@ public String getTranslateMinesPlaceholder( PlaceholderIdentifier identifier ) { } else { + // If the placeholder is a MINEPLAYERS, then dynamically figure out + // what mine a player is is, which requires a location... if ( player != null && player.getLocation() != null ) { mine = PrisonMines.getInstance().findMineLocation( player ); @@ -778,11 +769,11 @@ public String getTranslateMinesPlaceholder( PlaceholderIdentifier identifier ) { } - PlaceholderAttributeBar attributeBar = identifier.getAttributeBar(); - PlaceholderAttributeNumberFormat attributeNFormat = identifier.getAttributeNFormat(); - PlaceholderAttributeText attributeText = identifier.getAttributeText(); - PlaceholderAttributeTime attributeTime = identifier.getAttributeTime(); - + PlaceholderAttributeBar attributeBar = identifier.getAttributeBar(); + PlaceholderAttributeNumberFormat attributeNFormat = identifier.getAttributeNFormat(); + PlaceholderAttributeText attributeText = identifier.getAttributeText(); + PlaceholderAttributeTime attributeTime = identifier.getAttributeTime(); + int sequence = identifier.getSequence(); @@ -1345,32 +1336,32 @@ else if ( attributeNFormat != null ) { public String getTranslatePlayerMinesPlaceHolder( UUID playerUuid, String playerName, String identifier ) { - String results = null; - - if ( playerUuid != null ) { - - List placeHolderKeys = getTranslatedPlaceHolderKeys(); - - - PlaceholderIdentifier phIdentifier = new PlaceholderIdentifier( identifier ); - phIdentifier.setPlayer(playerUuid, playerName); - - - - - for ( PlaceHolderKey placeHolderKey : placeHolderKeys ) { - - if ( phIdentifier.checkPlaceholderKey(placeHolderKey) ) { - - results = getTranslateMinesPlaceholder( phIdentifier ); - - break; - } - - } - } - - return results; + String results = null; + + if ( playerUuid != null ) { + + List placeHolderKeys = getTranslatedPlaceHolderKeys(); + + + PlaceholderIdentifier phIdentifier = new PlaceholderIdentifier( identifier ); + phIdentifier.setPlayer(playerUuid, playerName); + + + + + for ( PlaceHolderKey placeHolderKey : placeHolderKeys ) { + + if ( phIdentifier.checkPlaceholderKey(placeHolderKey) ) { + + results = getTranslateMinesPlaceholder( phIdentifier ); + + break; + } + + } + } + + return results; } @@ -1380,10 +1371,10 @@ private String getRemainingTimeBar( Mine mine, PlaceholderAttribute attribute ) PlaceholderAttributeBar attributeBar = ( attribute instanceof PlaceholderAttributeBar ? (PlaceholderAttributeBar) attribute : null ); - double timeRemaining = mine.getRemainingTimeSec(); - int time = mine.getResetTime(); - - return PlaceholderManagerUtils.getInstance(). + double timeRemaining = mine.getRemainingTimeSec(); + int time = mine.getResetTime(); + + return PlaceholderManagerUtils.getInstance(). getProgressBar( timeRemaining, ((double) time), true, attributeBar ); } @@ -1401,73 +1392,24 @@ private String getRemainingTimeBar( Mine mine, PlaceholderAttribute attribute ) */ @Override public List getTranslatedPlaceHolderKeys() { - if ( translatedPlaceHolderKeys == null ) { - translatedPlaceHolderKeys = new ArrayList<>(); - - TreeSet blockNames = new TreeSet<>(); - - List placeHolders = - PrisonPlaceHolders.getTypes( PlaceholderFlags.MINES ); - - placeHolders.addAll( PrisonPlaceHolders.getTypes( PlaceholderFlags.STATSMINES ) ); - - - for ( Mine mine : getMines() ) { - for ( PrisonPlaceHolders ph : placeHolders ) { - String key = ph.name().replace( - PlaceholderManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX, "_" + mine.getName() ). - toLowerCase(); - - PlaceHolderKey placeholder = new PlaceHolderKey(key, ph, mine.getName() ); - if ( ph.getAlias() != null ) { - String aliasName = ph.getAlias().name().replace( - PlaceholderManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX, "_" + mine.getName() ). - toLowerCase(); - placeholder.setAliasName( aliasName ); - } - translatedPlaceHolderKeys.add( placeholder ); - - // Getting too many placeholders... add back the extended prefix when looking up: - -// // Now generate a new key based upon the first key, but without the prison_ prefix: -// String key2 = key.replace( -// IntegrationManager.PRISON_PLACEHOLDER_PREFIX + "_", "" ); -// PlaceHolderKey placeholder2 = new PlaceHolderKey(key2, ph, mine.getName(), false ); -// translatedPlaceHolderKeys.add( placeholder2 ); - - // capture all of the possible blocks used within the mines: - for ( PrisonBlock block : mine.getPrisonBlocks() ) { - - String blockName = block.getBlockType() == PrisonBlockType.minecraft ? - block.getBlockName().toLowerCase() : - block.getBlockNameFormal().replace( ":", "-" ).toLowerCase(); - - if ( !blockNames.contains( blockName ) ) { - blockNames.add( blockName ); - } - } - } - } - - - // Next we need to register all the PLAYERMINES. The mines are dynamic, based upon which one - // the player is in. So this is just a simple registration. - List placeHoldersPM = - PrisonPlaceHolders.getTypes( PlaceholderFlags.MINEPLAYERS ); - - for ( PrisonPlaceHolders ph : placeHoldersPM ) { - String key = ph.name().toLowerCase(); - - // There is a special condition when a MINEPLAYERS placeholder may have a suffix of - // _minename so they need to be expanded the same as a MINES placeholder. - if ( key.endsWith( PlaceholderManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX ) ) { - - for ( Mine mine : getMines() ) { - String mineKey = ph.name().replace( + if ( translatedPlaceHolderKeys == null ) { + translatedPlaceHolderKeys = new ArrayList<>(); + + TreeSet blockNames = new TreeSet<>(); + + List placeHolders = + PrisonPlaceHolders.getTypes( PlaceholderFlags.MINES ); + + placeHolders.addAll( PrisonPlaceHolders.getTypes( PlaceholderFlags.STATSMINES ) ); + + + for ( Mine mine : getMines() ) { + for ( PrisonPlaceHolders ph : placeHolders ) { + String key = ph.name().replace( PlaceholderManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX, "_" + mine.getName() ). toLowerCase(); - PlaceHolderKey placeholder = new PlaceHolderKey(mineKey, ph, mine.getName() ); + PlaceHolderKey placeholder = new PlaceHolderKey(key, ph, mine.getName() ); if ( ph.getAlias() != null ) { String aliasName = ph.getAlias().name().replace( PlaceholderManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX, "_" + mine.getName() ). @@ -1475,73 +1417,116 @@ public List getTranslatedPlaceHolderKeys() { placeholder.setAliasName( aliasName ); } translatedPlaceHolderKeys.add( placeholder ); - } -// PlaceHolderKey placeholder = new PlaceHolderKey(key, ph ); -// if ( ph.getAlias() != null ) { -// String aliasName = ph.getAlias().name().toLowerCase(); -// placeholder.setAliasName( aliasName ); -// } -// translatedPlaceHolderKeys.add( placeholder ); - } - else { + + // Getting too many placeholders... add back the extended prefix when looking up: + + // // Now generate a new key based upon the first key, but without the prison_ prefix: + // String key2 = key.replace( + // IntegrationManager.PRISON_PLACEHOLDER_PREFIX + "_", "" ); + // PlaceHolderKey placeholder2 = new PlaceHolderKey(key2, ph, mine.getName(), false ); + // translatedPlaceHolderKeys.add( placeholder2 ); + + // capture all of the possible blocks used within the mines: + for ( PrisonBlock block : mine.getPrisonBlocks() ) { + + String blockName = block.getBlockType() == PrisonBlockType.minecraft ? + block.getBlockName().toLowerCase() : + block.getBlockNameFormal().replace( ":", "-" ).toLowerCase(); + + if ( !blockNames.contains( blockName ) ) { + blockNames.add( blockName ); + } + } + } + } + + + // Next we need to register all the PLAYERMINES. The mines are dynamic, based upon which one + // the player is in. So this is just a simple registration. + List placeHoldersPM = + PrisonPlaceHolders.getTypes( PlaceholderFlags.MINEPLAYERS ); + + for ( PrisonPlaceHolders ph : placeHoldersPM ) { + String key = ph.name().toLowerCase(); - PlaceHolderKey placeholder = new PlaceHolderKey(key, ph ); - if ( ph.getAlias() != null ) { - String aliasName = ph.getAlias().name().toLowerCase(); - placeholder.setAliasName( aliasName ); + // There is a special condition when a MINEPLAYERS placeholder may have a suffix of + // _minename so they need to be expanded the same as a MINES placeholder. + if ( key.endsWith( PlaceholderManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX ) ) { + + for ( Mine mine : getMines() ) { + String mineKey = ph.name().replace( + PlaceholderManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX, "_" + mine.getName() ). + toLowerCase(); + + PlaceHolderKey placeholder = new PlaceHolderKey(mineKey, ph, mine.getName() ); + if ( ph.getAlias() != null ) { + String aliasName = ph.getAlias().name().replace( + PlaceholderManager.PRISON_PLACEHOLDER_MINENAME_SUFFIX, "_" + mine.getName() ). + toLowerCase(); + placeholder.setAliasName( aliasName ); + } + translatedPlaceHolderKeys.add( placeholder ); + } + // PlaceHolderKey placeholder = new PlaceHolderKey(key, ph ); + // if ( ph.getAlias() != null ) { + // String aliasName = ph.getAlias().name().toLowerCase(); + // placeholder.setAliasName( aliasName ); + // } + // translatedPlaceHolderKeys.add( placeholder ); + } + else { + + PlaceHolderKey placeholder = new PlaceHolderKey(key, ph ); + if ( ph.getAlias() != null ) { + String aliasName = ph.getAlias().name().toLowerCase(); + placeholder.setAliasName( aliasName ); + } + translatedPlaceHolderKeys.add( placeholder ); } - translatedPlaceHolderKeys.add( placeholder ); } - } - - - - // Next we need to register all the PLAYERMINES. The mines are dynamic, based upon which one - // the player is in. So this is just a simple registration. - List placeHoldersBN = - PrisonPlaceHolders.getTypes( PlaceholderFlags.PLAYERBLOCKS ); - - for ( PrisonPlaceHolders bn : placeHoldersBN ) { - String key = bn.name().toLowerCase(); - // There is a special condition when a MINEPLAYERS placeholder may have a suffix of - // _minename so they need to be expanded the same as a MINES placeholder. - if ( key.endsWith( PlaceholderManager.PRISON_PLACEHOLDER_PLAYERBLOCK_SUFFIX ) ) { + + + // Next we need to register all the PLAYERMINES. The mines are dynamic, based upon which one + // the player is in. So this is just a simple registration. + List placeHoldersBN = + PrisonPlaceHolders.getTypes( PlaceholderFlags.PLAYERBLOCKS ); + + for ( PrisonPlaceHolders bn : placeHoldersBN ) { + String key = bn.name().toLowerCase(); - for ( String blockName : blockNames ) { - String mineKey = bn.name().replace( - PlaceholderManager.PRISON_PLACEHOLDER_PLAYERBLOCK_SUFFIX, "__" + blockName ). - toLowerCase(); + // There is a special condition when a MINEPLAYERS placeholder may have a suffix of + // _minename so they need to be expanded the same as a MINES placeholder. + if ( key.endsWith( PlaceholderManager.PRISON_PLACEHOLDER_PLAYERBLOCK_SUFFIX ) ) { - PlaceHolderKey placeholder = new PlaceHolderKey(mineKey, bn, blockName ); - if ( bn.getAlias() != null ) { - String aliasName = bn.getAlias().name().replace( + for ( String blockName : blockNames ) { + String mineKey = bn.name().replace( PlaceholderManager.PRISON_PLACEHOLDER_PLAYERBLOCK_SUFFIX, "__" + blockName ). toLowerCase(); + + PlaceHolderKey placeholder = new PlaceHolderKey(mineKey, bn, blockName ); + if ( bn.getAlias() != null ) { + String aliasName = bn.getAlias().name().replace( + PlaceholderManager.PRISON_PLACEHOLDER_PLAYERBLOCK_SUFFIX, "__" + blockName ). + toLowerCase(); + placeholder.setAliasName( aliasName ); + } + translatedPlaceHolderKeys.add( placeholder ); + } + } + else { + + PlaceHolderKey placeholder = new PlaceHolderKey(key, bn ); + if ( bn.getAlias() != null ) { + String aliasName = bn.getAlias().name().toLowerCase(); placeholder.setAliasName( aliasName ); } translatedPlaceHolderKeys.add( placeholder ); } -// PlaceHolderKey placeholder = new PlaceHolderKey(key, ph ); -// if ( ph.getAlias() != null ) { -// String aliasName = ph.getAlias().name().toLowerCase(); -// placeholder.setAliasName( aliasName ); -// } -// translatedPlaceHolderKeys.add( placeholder ); - } - else { - - PlaceHolderKey placeholder = new PlaceHolderKey(key, bn ); - if ( bn.getAlias() != null ) { - String aliasName = bn.getAlias().name().toLowerCase(); - placeholder.setAliasName( aliasName ); - } - translatedPlaceHolderKeys.add( placeholder ); } - } - - } - return translatedPlaceHolderKeys; + + } + return translatedPlaceHolderKeys; } /** @@ -1551,18 +1536,18 @@ public List getTranslatedPlaceHolderKeys() { *

    */ public void resetTranslatedPlaceHolderKeys() { - translatedPlaceHolderKeys = null; + translatedPlaceHolderKeys = null; } @Override public void reloadPlaceholders() { - // clear the class variable so they will regenerate: - translatedPlaceHolderKeys = null; - - // Regenerate the translated placeholders: - getTranslatedPlaceHolderKeys(); + // clear the class variable so they will regenerate: + translatedPlaceHolderKeys = null; + + // Regenerate the translated placeholders: + getTranslatedPlaceHolderKeys(); } diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java index 66a3f2263..bd9fc4e83 100644 --- a/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/tasks/MinePagedResetAsyncTask.java @@ -73,9 +73,6 @@ public MinePagedResetAsyncTask( Mine mine, MineResetType resetType ) { } -// public void submitTaskSync() { -// submitTaskAsync(); -// } public void submitTaskAsync() { // Prevent the task from being submitted if it is a virtual mine: @@ -199,7 +196,6 @@ public void run() { for ( int i = position; i < endIndex; i++ ) { subList.add( targetBlocks.get( i ) ); } -// targetBlocks.subList( position, endIndex ) ); List tBlocks = new ArrayList<>(); for (MineTargetPrisonBlock mtpb : subList ) { diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/wip/data/MineBlockConstraints.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/wip/data/MineBlockConstraints.java new file mode 100644 index 000000000..ae0b4602b --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/wip/data/MineBlockConstraints.java @@ -0,0 +1,5 @@ +package tech.mcprison.prison.mines.wip.data; + +public class MineBlockConstraints { + +} diff --git a/prison-mines/src/main/java/tech/mcprison/prison/mines/wip/data/MineQuestData.java b/prison-mines/src/main/java/tech/mcprison/prison/mines/wip/data/MineQuestData.java new file mode 100644 index 000000000..d2f81310a --- /dev/null +++ b/prison-mines/src/main/java/tech/mcprison/prison/mines/wip/data/MineQuestData.java @@ -0,0 +1,33 @@ +package tech.mcprison.prison.mines.wip.data; + +public class MineQuestData { + + private String questName; + + private MineQuestType questType; + + private boolean completed = false; + + + + public enum MineQuestSource { + byMine, + byBlockType + ; + } + + public enum MineQuestType { + money, + token, + block, + time + ; + } + + public MineQuestData() { + super(); + + + } + +} diff --git a/prison-mines/src/test/java/tech/mcprison/prison/mines/data/PrisonSortableMinesTest.java b/prison-mines/src/test/java/tech/mcprison/prison/mines/data/PrisonSortableMinesTest.java index 6b9d26292..6f7a33697 100644 --- a/prison-mines/src/test/java/tech/mcprison/prison/mines/data/PrisonSortableMinesTest.java +++ b/prison-mines/src/test/java/tech/mcprison/prison/mines/data/PrisonSortableMinesTest.java @@ -29,13 +29,6 @@ public void testGetSortedSet() Mine b = new Mine( MineUnitTestUsage.TRUE, "b" ); // note lower case 'b' Mine c = new Mine( MineUnitTestUsage.TRUE, "C" ); -// Mine a = new Mine(); -// a.setName( "A" ); -// Mine b = new Mine(); -// b.setName( "b" ); -// Mine c = new Mine(); -// c.setName( "C" ); - List unsortedList = new ArrayList<>(); unsortedList.add( b ); unsortedList.add( c ); diff --git a/prison-mines/src/test/java/tech/mcprison/prison/mines/managers/MineManagerTest.java b/prison-mines/src/test/java/tech/mcprison/prison/mines/managers/MineManagerTest.java index 58ea9cc4f..0e089cedb 100644 --- a/prison-mines/src/test/java/tech/mcprison/prison/mines/managers/MineManagerTest.java +++ b/prison-mines/src/test/java/tech/mcprison/prison/mines/managers/MineManagerTest.java @@ -23,15 +23,6 @@ private List getTestMines() { Mine c = new Mine( MineUnitTestUsage.TRUE, "C" ); Mine d = new Mine( MineUnitTestUsage.TRUE, "D" ); -// Mine a = new Mine(); -// a.setName( "A" ); -// Mine b = new Mine(); -// b.setName( "b" ); -// Mine c = new Mine(); -// c.setName( "C" ); -// Mine d = new Mine(); -// d.setName( "D" ); - mines.add( d ); mines.add( b ); mines.add( a ); diff --git a/prison-misc/PrisonEnchants-API-v1.0__v2.jardesc b/prison-misc/PrisonEnchants-API-v1.0__v2.jardesc new file mode 100644 index 000000000..d9a68db20 --- /dev/null +++ b/prison-misc/PrisonEnchants-API-v1.0__v2.jardesc @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/prison-misc/TheNewEconomy_prisonBuild_v0.1.3.jardesc b/prison-misc/TheNewEconomy_prisonBuild_v0.1.3.jardesc new file mode 100644 index 000000000..345bf73eb --- /dev/null +++ b/prison-misc/TheNewEconomy_prisonBuild_v0.1.3.jardesc @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/prison-misc/build.gradle b/prison-misc/build.gradle index f7695a752..710d849e2 100644 --- a/prison-misc/build.gradle +++ b/prison-misc/build.gradle @@ -21,42 +21,9 @@ group 'tech.mcprison' compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = "UTF-8" -repositories { - 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/" } -} +ext.targetArchiveClassifier = 'Java1.8' +//ext.targetArchiveClassifier = 'Java16' @@ -71,7 +38,8 @@ dependencies { implementation 'org.jetbrains:annotations:24.0.1' - compileOnly 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT' +// compileOnly 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT' + compileOnly( libs.spigotApi ) testImplementation group: 'junit', name: 'junit', version: '4.12' diff --git a/prison-misc/src/main/java/me/pulsi_/prisonenchants/events/PEExplosionEvent.java b/prison-misc/src/main/java/me/pulsi_/prisonenchants/events/PEExplosionEvent.java new file mode 100644 index 000000000..35008ec65 --- /dev/null +++ b/prison-misc/src/main/java/me/pulsi_/prisonenchants/events/PEExplosionEvent.java @@ -0,0 +1,118 @@ +package me.pulsi_.prisonenchants.events; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Support for Prison Enchant's v1.0 and v2.0 of the API... + * + * + * + { + // PrisonEnchants-API-v1.0.0: + //me.pulsi_.prisonenchants.events.PEExplosionEvent + + PEExplosionEvent peEE = new PEExplosionEvent(); + Block block = peEE.getBlockBroken(); + String eventName = peEE.getEventName(); + List explodedBlocks = peEE.getExplodedBlocks(); + HandlerList handlers = peEE.getHandlers(); + HandlerList handlerList = peEE.getHandlerList(); + Player player = peEE.getPlayer(); + boolean async = peEE.isAsynchronous(); + boolean canceled = peEE.isCancelled(); + peEE.setCancelled(false); + + } + { + // PrisonEnchants-API-v2.2.0: + //me.pulsi_.prisonenchants.events.PEExplosionEvent + + PEExplosionEvent peEE = new PEExplosionEvent(); + List blocks = peEE.getBlocks(); + PEEnchant enchantSource = peEE.getEnchantSource(); // not needed + String eventName = peEE.getEventName(); + HandlerList handlers = peEE.getHandlers(); + HandlerList handlerList = peEE.getHandlerList(); + Player player = peEE.getPlayer(); + boolean async = peEE.isAsynchronous(); + boolean canceled = peEE.isCancelled(); + peEE.setBlocks( blocks ); + peEE.setCancelled(false); + } + { + // PrisonEnchants-API-v2.2.1: + //me.pulsi_.prisonenchants.events.PEExplosionEvent + NOTE: v2.2.1 adds the function getOrigin(); + + Location locationOfOriginalBlock = peEE.getOrigin(); + } + * + */ +public class PEExplosionEvent + extends Event { + + public String getEventName() { + return ""; + } + + /** + * PrisonEnchants v1.0: + * @return + */ + public Block getBlockBroken() { + Block results = null; + return results; + } + + /** + * PrisonEnchants v1.0: + * @return + */ + public List getExplodedBlocks() { + List results = new ArrayList<>(); + return results; + } + + /** + * PrisonEnchants v2.2: + * @return + */ + public List getBlocks() { + List results = new ArrayList<>(); + return results; + } + + public HandlerList getHandlers() { + return null; + } + public static HandlerList getHandlerList() { + return null; + } + + public Player getPlayer() { + return null; + } + + public Location getOrigin() { + return null; + } + +// public boolean isAsynchronous() { +// return true; +// } + + public boolean isCancelled() { + return true; + } + + public void setCancelled( boolean cancel ) { + } + +} diff --git a/prison-misc/src/main/java/net/tnemc/core/TNECore.java b/prison-misc/src/main/java/net/tnemc/core/TNECore.java new file mode 100644 index 000000000..c0ffc8b16 --- /dev/null +++ b/prison-misc/src/main/java/net/tnemc/core/TNECore.java @@ -0,0 +1,21 @@ +package net.tnemc.core; + +public class TNECore { + + + public static TNECore eco() { + return new TNECore(); + } + + public TNECore currency() { + return this; + } + + public TNECore findCurrency( String currency ) { + return this; + } + + public boolean isPresent() { + return true; + } +} diff --git a/prison-misc/src/main/java/net/tnemc/core/api/TNEAPI.java b/prison-misc/src/main/java/net/tnemc/core/api/TNEAPI.java new file mode 100644 index 000000000..eb7bb7060 --- /dev/null +++ b/prison-misc/src/main/java/net/tnemc/core/api/TNEAPI.java @@ -0,0 +1,54 @@ +package net.tnemc.core.api; + +import java.math.BigDecimal; +import java.util.UUID; + +public class TNEAPI { + + public boolean hasPlayerAccount( UUID playerUUID ) { + return true; + } + + public boolean hasHoldings( String playerUUID, String worldName, + String currency, BigDecimal amount ) { + return true; + } + + + public boolean setHoldings( String playerUUID, String worldName, + String currency, BigDecimal amount ) { + return true; + } + + + public BigDecimal getHoldings( String playerUUID, String worldName, + String currency ) { + return BigDecimal.ZERO; + } + + + public TNEAPI getDefaultCurrency() { + return this; + } + + public String getIdentifier() { + return ""; + } + + + public TNEAPI addHoldings( String playerUUID, String worldName, + String currency, BigDecimal amount, String source ) { + return this; + } + + + public TNEAPI removeHoldings( String playerUUID, String worldName, + String currency, BigDecimal amount, String source ) { + return this; + } + + public boolean isSuccessful() { + return true; + } + +} diff --git a/prison-ranks/build.gradle b/prison-ranks/build.gradle index cc15db280..70c7f3313 100644 --- a/prison-ranks/build.gradle +++ b/prison-ranks/build.gradle @@ -3,6 +3,12 @@ group 'tech.mcprison' compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = "UTF-8" + +ext.targetArchiveClassifier = 'Java1.8' +//ext.targetArchiveClassifier = 'Java16' + + + dependencies { implementation project(':prison-core') testImplementation group: 'junit', name: 'junit', version: '4.12' diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/ChatHandler.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/ChatHandler.java index 0400dc7f3..1c3ce52e7 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/ChatHandler.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/ChatHandler.java @@ -13,54 +13,27 @@ */ public class ChatHandler { - /* - * Constructor - */ public ChatHandler() { Prison.get().getEventBus().register(this); - - // This is pushed back in to the place holder integrations: -// Optional placeholderIntegration = Prison.get().getIntegrationManager().getForType(IntegrationType.PLACEHOLDER); -// if (placeholderIntegration.isPresent()) { -// PlaceholderIntegration integration = ((PlaceholderIntegration) placeholderIntegration.get()); -// -// PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); -// for ( PrisonPlaceHolders placeHolder : PrisonPlaceHolders.values() ) { -// if ( !placeHolder.isSuppressed() ) { -// integration.registerPlaceholder(placeHolder.name(), -// player -> Text.translateAmpColorCodes( -// pm.getTranslatePlayerPlaceHolder( player.getUUID(), placeHolder.name() ) -// )); -// } -// } - -//// integration.registerPlaceholder("PRISON_RANK", -//// player -> Text.translateAmpColorCodes(getPrefix(player.getUUID()))); -// } } - /* - * Listeners - */ @Subscribe public void onPlayerChat(PlayerChatEvent e) { - String newFormat = e.getFormat(); + String newFormat = e.getFormat(); // Output.get().logDebug( "ChatHandler.onPlayerChat: before: %s", newFormat.replace( "%", "^" ) ); - Player player = e.getPlayer(); - - String results = Prison.get().getPlatform().getPlaceholders() - .placeholderTranslateText( player.getUUID(), player.getName(), newFormat ); + Player player = e.getPlayer(); + + String results = Prison.get().getPlatform().getPlaceholders() + .placeholderTranslateText( player.getUUID(), player.getName(), newFormat ); // Output.get().logDebug( "ChatHandler.onPlayerChat: after: %s", results.replace( "%", "^" ) ); - e.setFormat( results ); + e.setFormat( results ); } - - } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandler.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandler.java index a84d4be9e..93b4076eb 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandler.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandler.java @@ -31,29 +31,16 @@ public class FirstJoinHandler extends FirstJoinHandlerMessages { - /* - * Constructor - */ - public FirstJoinHandler() { Prison.get().getEventBus().register(this); } - /* - * Listeners - */ - @Subscribe public void onFirstJoin(FirstJoinEvent event) { + @Subscribe + public void onFirstJoin(FirstJoinEvent event) { RankPlayer player = event.getPlayer(); PrisonRanks.getInstance().getPlayerManager().checkPlayerDefaultRank(player); - -// // Try to perform the first join processing to give them the default rank: -// RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); -// rankPlayerFactory.firstJoin( player ); -// -// PrisonRanks.getInstance().getPlayerManager().savePlayer(player); - } } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandlerMessages.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandlerMessages.java index 4cd3cc3fd..7893df761 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandlerMessages.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/FirstJoinHandlerMessages.java @@ -4,8 +4,8 @@ public class FirstJoinHandlerMessages { public String firstJoinWarningNoRanksOnServer() { return PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_firstJoinHandler__no_ranks_on_server" ) - .localize(); + .getLocalizable( "ranks_firstJoinHandler__no_ranks_on_server" ) + .localize(); } protected String firstJoinErrorCouldNotSavePlayer() { 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 80527e11c..3a3091013 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 @@ -26,7 +26,6 @@ import tech.mcprison.prison.PrisonAPI; import tech.mcprison.prison.convert.ConversionManager; 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; @@ -57,10 +56,6 @@ public class PrisonRanks extends PrisonRanksMessages { public static final String MODULE_NAME = ModuleManager.MODULE_NAME_RANKS; -// public static final String MODULE_NAME = "Ranks"; - /* - * Fields & Constants - */ private static PrisonRanks instance; private RankManager rankManager; @@ -74,10 +69,6 @@ public class PrisonRanks private LocaleManager localeManager; - /* - * Constructor - */ - public PrisonRanks(String version) { super(MODULE_NAME, version, 3); @@ -87,20 +78,27 @@ public PrisonRanks(String version) { @Override public String getBaseCommands() { - return "/ranks /rankup /rankupMax /prestige /prestiges"; + return "/ranks /rankup /rankupMax /prestige /prestiges"; } - /* - * Methods - */ public static PrisonRanks getInstance() { + if ( instance == null ) { + synchronized (PrisonRanks.class) { + if ( instance == null ) { + instance = new PrisonRanks( "disabled" ); + instance.setEnabled( false ); + } + } + } return instance; } @Override public void enable() { instance = this; + + setEnabled( true ); this.localeManager = new LocaleManager(this, "lang/ranks"); @@ -137,7 +135,7 @@ public void enable() { rankManager.loadRanks(); } catch (IOException e) { - getStatus().setStatus(ModuleStatus.Status.FAILED); + getStatus().setStatus(ModuleStatus.Status.FAILED); getStatus().setMessage( prisonRanksFailureLoadingRankStatusMsg( e.getMessage() ) ); @@ -145,69 +143,42 @@ public void enable() { } // Load up the ladders - - ladderManager = new LadderManager(initCollection("ladders"), this); try { - ladderManager.loadLadders(); + ladderManager.loadLadders( getRankManager() ); } catch (IOException e) { - getStatus().setStatus(ModuleStatus.Status.FAILED); + getStatus().setStatus(ModuleStatus.Status.FAILED); getStatus().setMessage( prisonRanksFailureLoadingLadderStatusMsg( e.getMessage() ) ); logStartupMessageError( prisonRanksFailureLoadingLadderMsg( e.getMessage() ) ); } - createDefaultLadder(); + ladderManager.createDefaultLadder(); -// // Set the rank relationships: -// rankManager.connectRanks(); - - - - // NOTE: The following is not needed since the ladders are already hooked up to the ranks. -// for ( Rank rank : rankManager.getRanks() ) { -// -// if ( rank.getLadder() == null ) { -// // Hook up the ladder if it has not been setup yet: -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( rank ); -// -// rank.setLadder( ladder ); -// } -// } - // Verify that all ranks that use currencies have valid currencies: rankManager.identifyAllRankCurrencies( getPrisonStartupDetails() ); // Load up the players - - playerManager = new PlayerManager(initCollection("players")); + try { - playerManager.loadPlayers(); + playerManager.loadAllPlayers(); } catch (IOException e) { - getStatus().setStatus(ModuleStatus.Status.FAILED); + getStatus().setStatus(ModuleStatus.Status.FAILED); getStatus().setMessage( prisonRanksFailureLoadingPlayersStatusMsg( e.getMessage() ) ); logStartupMessageError( prisonRanksFailureLoadingPlayersMsg( e.getMessage() ) ); - getStatus().addMessage( prisonRanksFailedLoadingPlayersMsg( e.getMessage() )); - logStartupMessageError( prisonRanksFailedToLoadPlayFileMsg( e.getMessage() )); + getStatus().addMessage( prisonRanksFailedLoadingPlayersMsg( e.getMessage() )); + logStartupMessageError( prisonRanksFailedToLoadPlayFileMsg( e.getMessage() )); } - - - // Hook up all players to the ranks: - // - parameter checkPlayerBalances is set to false - playerManager.connectPlayersToRanks( false ); - - Output.get().logInfo( "Ranks: Finished Connecting Players to Ranks." ); - // Load up the commands @@ -257,8 +228,6 @@ public void enable() { for (String msg : rankDetails) { Output.get().logInfo(msg); } -// boolean includeAll = true; -// PrisonRanks.getInstance().getRankManager().ranksByLadders( includeAll ); @@ -272,12 +241,60 @@ public void enable() { // Check all players to see if any need to join: RanksStartupPlayerValidationsAsyncTask.submitTaskSync( this ); -// checkAllPlayersForJoin(); } + + public boolean reloadRanksAndLadders() { + boolean success = false; + + try { + + // New temp RankManager to reload ranks: + RankManager rManager = new RankManager(initCollection("ranks")); + + rManager.reloadAllRanks(); + + // Load up the ladders + + // New temp LadderManager to reload ladders: + LadderManager lManager = new LadderManager(initCollection("ladders"), this); + + // NOTE: This instance of the LadderManager requires the new temp instance of the rank manager: + lManager.reloadAllLadders( rManager ); + + + // Now replace all rank data and ladder data with the newly loaded data: + getRankManager().setLoadedRanks( rManager.getRanks() ); + getRankManager().setRanksByName( rManager.getRanksByName() ); + getRankManager().setRanksById( rManager.getRanksById() ); + + getLadderManager().setLoadedLadders( lManager.getLoadedLadders() ); + + + // Must reload all players now, so they are properly aligned with the ranks and ladders: + getPlayerManager().reloadAllPlayers(); + + + } catch (IOException e) { + String msg = String.format( + "PrisonRanks: reloadRanksAndLadders: Failed. [%s]", + e.getMessage()); + + Output.get().logInfo( msg ); + } + + return success; + } + /** + *

    This is actually a very bad idea to add any players that have not joined. + * This should be disabled. When a player joins the server for the first time, + * then it will add them successfully. + *

    + * + */ public void checkAllPlayersForJoin() { @@ -289,28 +306,26 @@ public void checkAllPlayersForJoin() if ( addNewPlayers ) { + long startMs = System.currentTimeMillis(); + RankUpCommand rankupCommands = rankManager.getRankupCommands(); // If there is a default rank on the default ladder, then // check to see if there are any players not in prison: add them: RankLadder defaultLadder = getLadderManager().getLadderDefault(); -// RankLadder defaultLadder = getLadderManager().getLadder( LadderManager.LADDER_DEFAULT ); if ( defaultLadder != null && defaultLadder.getRanks().size() > 0 ) { int addedPlayers = 0; int fixedPlayers = 0; - for ( Player player : Prison.get().getPlatform().getOfflinePlayers() ) { - - // getPlayer() will add a player who does not exist: - RankPlayer rPlayer = playerManager.getPlayer( player ); - if ( rPlayer != null ) { - if ( rPlayer.checkName( player.getName() ) ) { - playerManager.savePlayer( rPlayer ); - addedPlayers++; - } - } - } + List rPlayers = playerManager.getPlayers(); + + // NOTE: The Platform.getOfflinePlayers() only returns the playerManager.getPlayers() because + // bukkit can seriously lag the server and kill it. +// List players = Prison.get().getPlatform().getOfflinePlayers(); + + + // Prison will no longer add offline players. They must join to be added. Causes massive lag on huge servers! RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); @@ -329,28 +344,12 @@ public void checkAllPlayersForJoin() } - for ( RankPlayer rPlayer : playerManager.getPlayers() ) { - -// @SuppressWarnings( "unused" ) -// String rp = rPlayer.toString(); + for ( RankPlayer rPlayer : rPlayers ) { - Rank rankOnDefault = null; PlayerRank pRank = rankPlayerFactory.getRank( rPlayer, defaultLadder ); - if ( pRank != null ) { - - rankOnDefault = pRank.getRank(); - -// Output.get().logInfo( "#### %s ladder = %s isRankNull= %s rank= %s %s [%s]" , -// rPlayer.getName(), -// defaultLadder.getName(), -// (rankOnDefault == null ? "true" : "false"), (rankOnDefault == null ? "null" : rankOnDefault.getName()), -// (rankOnDefaultStr == null ? "true" : "false"), (rankOnDefaultStr == null ? "null" : rankOnDefaultStr.getName()), -// rp ); - - } - if ( rankOnDefault == null ) { + if ( pRank == null || pRank.getRank() == null ) { rankupCommands.setPlayerRank( rPlayer, defaultRank ); @@ -371,7 +370,11 @@ public void checkAllPlayersForJoin() } } - Output.get().logInfo( "Ranks: Finished First Join Checks." ); + long endMs = System.currentTimeMillis(); + + long duration = endMs - startMs; + + Output.get().logInfo( "Ranks: Finished First Join Checks: " + duration + " ms" ); } else { @@ -398,6 +401,7 @@ public void deferredStartup() { */ @Override public void disable() { + setEnabled( false ); } @@ -411,82 +415,38 @@ private Collection initCollection(String collName) { return collectionOptional.orElseThrow(RuntimeException::new); } - /** - * A default ladder is absolutely necessary on the server, so let's create it if it doesn't exist, this also create the prestiges ladder. - */ - private void createDefaultLadder() { - if ( ladderManager.getLadder(LadderManager.LADDER_DEFAULT) == null ) { - RankLadder rankLadder = ladderManager.createLadder(LadderManager.LADDER_DEFAULT); - - if ( rankLadder == null ) { - - String failureMsg = prisonRanksFailureCreateDefaultLadderMsg(); - - Output.get().logError( failureMsg ); - super.getStatus().toFailed( failureMsg ); - return; - } - - if ( !ladderManager.save( rankLadder ) ) { - - String failureMsg = prisonRanksFailureSavingDefaultLadderMsg(); - - Output.get().logError( failureMsg ); - super.getStatus().toFailed( failureMsg ); - } - } - - if ( ladderManager.getLadder(LadderManager.LADDER_PRESTIGES) == null ) { - RankLadder rankLadder = ladderManager.createLadder(LadderManager.LADDER_PRESTIGES); - - if ( rankLadder == null ) { - - String failureMsg = prisonRanksFailureCreatePrestigeLadderMsg(); - - Output.get().logError( failureMsg ); - super.getStatus().toFailed( failureMsg ); - return; - } - - if ( !ladderManager.save( rankLadder ) ) { - - String failureMsg = prisonRanksFailureSavingPrestigeLadderMsg(); - - Output.get().logError( failureMsg ); - super.getStatus().toFailed( failureMsg ); - } - } - - } - private void logStartupMessageError( String message ) { - logStartupMessage( LogLevel.ERROR, message ); + logStartupMessage( LogLevel.ERROR, message ); } private void logStartupMessage( String message ) { - logStartupMessage( LogLevel.INFO, message ); + logStartupMessage( LogLevel.INFO, message ); } + private void logStartupMessage( LogLevel logLevel, String message ) { - Output.get().log( message, logLevel ); - - getPrisonStartupDetails().add( message ); + Output.get().log( message, logLevel ); + + getPrisonStartupDetails().add( message ); } public List getPrisonStartupDetails() { - return prisonStartupDetails; + return prisonStartupDetails; } public void setPrisonStartupDetails( List prisonStartupDetails ){ - this.prisonStartupDetails = prisonStartupDetails; + this.prisonStartupDetails = prisonStartupDetails; } public RankManager getRankManager() { + if ( rankManager == null && !isEnabled() ) { + rankManager = new RankManager(); + } return rankManager; } @@ -495,6 +455,10 @@ public LadderManager getLadderManager() { } public PlayerManager getPlayerManager() { + + if ( playerManager == null && !isEnabled() ) { + playerManager = new PlayerManager( null ); + } return playerManager; } @@ -503,7 +467,7 @@ public RankLadder getDefaultLadder() { } public RankLadder getPrestigesLadder() { - return getLadderManager().getLadder(LadderManager.LADDER_PRESTIGES); + return getLadderManager().getLadder(LadderManager.LADDER_PRESTIGES); } public Database getDatabase() { @@ -511,44 +475,65 @@ public Database getDatabase() { } public int getRankCount() { - int rankCount = getRankManager() == null ||getRankManager().getRanks() == null ? 0 : + int rankCount = getRankManager() == null ||getRankManager().getRanks() == null ? 0 : getRankManager().getRanks().size(); - return rankCount; + return rankCount; } private int getLadderRankCount( String ladderName ) { - int rankCount = 0; - - if ( getLadderManager() != null && getLadderManager().getLadders() != null ) { - RankLadder ladder = getLadderManager().getLadder( ladderName ); - if ( ladder != null ) { - rankCount = ladder.getRanks().size(); - } - } - return rankCount; + int rankCount = 0; + + if ( getLadderManager() != null && getLadderManager().getLadders() != null ) { + RankLadder ladder = getLadderManager().getLadder( ladderName ); + if ( ladder != null ) { + rankCount = ladder.getRanks().size(); + } + } + return rankCount; } public int getDefaultLadderRankCount() { - return getLadderRankCount( LadderManager.LADDER_DEFAULT ); + return getLadderRankCount( LadderManager.LADDER_DEFAULT ); } public int getPrestigesLadderRankCount() { - return getLadderRankCount( LadderManager.LADDER_PRESTIGES ); + return getLadderRankCount( LadderManager.LADDER_PRESTIGES ); } public int getladderCount() { - int ladderCount = getLadderManager() == null || getLadderManager().getLadders() == null ? 0 : + int ladderCount = getLadderManager() == null || getLadderManager().getLadders() == null ? 0 : getLadderManager().getLadders().size(); - return ladderCount; + return ladderCount; } public int getPlayersCount() { - int playersCount = getPlayerManager() == null || getPlayerManager().getPlayers() == null ? 0 : + int playersCount = getPlayerManager() == null || getPlayerManager().getPlayers() == null ? 0 : getPlayerManager().getPlayers().size(); - return playersCount; + return playersCount; } public LocaleManager getRanksMessages() { return localeManager; } + + + /** + * For modules that have elements, this will return the count. If a module has no + * elements, then it will return a -1. Otherwise a zero would indicate that a module + * should have elements, but it currently has none. + * + * Example would be ranks and mines. For these, if it returns a zero, then they have + * no ranks or mines defined. If it return a -1 then the module is not active. + * + * @return + */ + public int getElementCount() { + int results = isEnabled() ? 0 : -1; + + if ( isEnabled() ) { + results = getRankCount(); + } + + return results; + } } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanksMessages.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanksMessages.java index 579db0592..54213f8a7 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanksMessages.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/PrisonRanksMessages.java @@ -14,8 +14,8 @@ public PrisonRanksMessages( String name, String version, int target ) protected String prisonRanksFailureNoEconomyStatusMsg() { return PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_prisonRanks__failure_no_economy_status" ) - .localize(); + .getLocalizable( "ranks_prisonRanks__failure_no_economy_status" ) + .localize(); } protected String prisonRanksFailureNoEconomyMsg( String integrationDebug ) { @@ -132,12 +132,12 @@ public String prisonRanksStatusLoadedPlayersMsg( int playerCount ) { } - protected String prisonRanksFailureCreateDefaultLadderMsg() { + public String prisonRanksFailureCreateDefaultLadderMsg() { String msgCreate = PrisonRanks.getInstance().getRanksMessages() .getLocalizable( "ranks_prisonRanks__failure_with_ladder_create" ) .localize(); - String msgDefault = PrisonRanks.getInstance().getRanksMessages() + String msgDefault = PrisonRanks.getInstance().getRanksMessages() .getLocalizable( "ranks_prisonRanks__failure_with_ladder_default" ) .localize(); @@ -151,7 +151,7 @@ protected String prisonRanksFailureCreateDefaultLadderMsg() { } - protected String prisonRanksFailureSavingDefaultLadderMsg() { + public String prisonRanksFailureSavingDefaultLadderMsg() { String msgSave = PrisonRanks.getInstance().getRanksMessages() .getLocalizable( "ranks_prisonRanks__failure_with_ladder_save" ) @@ -171,16 +171,16 @@ protected String prisonRanksFailureSavingDefaultLadderMsg() { - protected String prisonRanksFailureCreatePrestigeLadderMsg() { + public String prisonRanksFailureCreatePrestigeLadderMsg() { String msgCreate = PrisonRanks.getInstance().getRanksMessages() .getLocalizable( "ranks_prisonRanks__failure_with_ladder_create" ) .localize(); - String msgDefault = PrisonRanks.getInstance().getRanksMessages() + String msgDefault = PrisonRanks.getInstance().getRanksMessages() .getLocalizable( "ranks_prisonRanks__failure_with_ladder_prestiges" ) .localize(); - return PrisonRanks.getInstance().getRanksMessages() + return PrisonRanks.getInstance().getRanksMessages() .getLocalizable( "ranks_prisonRanks__failure_with_ladder" ) .withReplacements( msgCreate, @@ -189,7 +189,7 @@ protected String prisonRanksFailureCreatePrestigeLadderMsg() { } - protected String prisonRanksFailureSavingPrestigeLadderMsg() { + public String prisonRanksFailureSavingPrestigeLadderMsg() { String msgSave = PrisonRanks.getInstance().getRanksMessages() .getLocalizable( "ranks_prisonRanks__failure_with_ladder_save" ) diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankConversionAgent.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankConversionAgent.java index ea2c494a3..aa9380c5d 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankConversionAgent.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankConversionAgent.java @@ -10,97 +10,13 @@ public class RankConversionAgent implements ConversionAgent { @Override public ConversionResult convert() { - // NOTE this is obsolete: - -// File oldFolder = new File(PrisonAPI.getPluginDirectory().getParent(), "Prison.old"); -// File ranksFolder = new File(oldFolder, "ranks"); -// -// File alreadyConverted = new File(ranksFolder, ".converted"); -// if (alreadyConverted.exists()) { -// return ConversionResult.failure(getName(), -// "Already converted. Delete the '/plugins/Prison.old/ranks' folder."); -// } -// -// String[] ranksJson = ranksFolder.list((dir, name) -> name.endsWith(".json")); -// -// try { -// -// if (ranksJson != null) { -// for (String rankJson : ranksJson) { -// File rankFile = new File(ranksFolder, rankJson); -// String json = new String(Files.readAllBytes(rankFile.toPath())); -// -// JsonObject obj = JsonParser.parseString(json).getAsJsonObject(); -// String name = obj.getAsJsonPrimitive("name").getAsString(); -// double price = obj.getAsJsonPrimitive("price").getAsDouble(); -// String prefix = obj.getAsJsonPrimitive("prefix").getAsString(); -// if (!prefix.contains("[")) { -// prefix = "&3[" + prefix; -// } -// if (!prefix.contains("]")) { -// prefix = prefix + "&3]"; -// } -// -// if(PrisonRanks.getInstance().getRankManager().getRank(name) != null) { -// break; // Already added -// } -// -// RankLadder rankLadder = -// PrisonRanks.getInstance().getLadderManager().getLadder("default"); -// if ( rankLadder == null ) { -// break; // Idek how this is possible. -// } -// -// Optional ourRank = -// PrisonRanks.getInstance().getRankManager().createRank(name, prefix, price); -// if (!ourRank.isPresent()) { -// Output.get().logWarn(String.format("Could not convert rank '%s'", name)); -// break; // It failed -// } -// -//// try { -// PrisonRanks.getInstance().getRankManager().saveRank(ourRank.get()); -//// } catch (IOException e) { -//// String nonNullName = name == null ? "null" : name; -//// PrisonRanks.getInstance().getErrorManager().throwError( -//// new Error("while converting ranks") -//// .appendStackTrace("while saving rank " + nonNullName, e)); -//// break; // Skip this... -//// } -// -// rankLadder.addRank(ourRank.get()); -// try { -// PrisonRanks.getInstance().getLadderManager().saveLadder( rankLadder ); -// } catch (IOException e) { -// PrisonRanks.getInstance().getErrorManager().throwError( -// new Error("while converting ranks") -// .appendStackTrace("while saving default ladder", e)); -// break; // Skip this... -// } -// -// } -// -// Output.get().logInfo("Notice: While we converted your ranks data, Prison 3 no longer ties itself to the permissions plugin." -// + "That means that if you want users to change permissions groups when they rank up, you'll have to use rank-up commands."); -// Output.get().logInfo("For more information, see this article:&b https://github.com/MC-Prison/Prison/wiki/Ranks-Guidebook#rank-up-commands"); -// -// alreadyConverted.createNewFile(); -// return new ConversionResult(getName(), ConversionResult.Status.Success, -// "Converted " + ranksJson.length + " ranks."); -// } else { -// alreadyConverted.createNewFile(); -// return new ConversionResult(getName(), ConversionResult.Status.Success, -// "Converted 0 ranks."); -// } -// } catch (IOException e) { -// PrisonRanks.getInstance().getErrorManager().throwError( -// new Error("while converting ranks").appendStackTrace("while loading ranks", e)); -// return ConversionResult.failure(getName(), "IOException, check console for details."); -// } - - return new ConversionResult("Rank Conversion Failure", ConversionResult.Status.Failure, - "To upgrade ranks to v3.1.1 format, please first upgrade to prison v3.1.1. " + - "Then upgrade to a newer version of prison."); + // NOTE this is obsolete: + + // commented out code was removed. See history in git. + + return new ConversionResult("Rank Conversion Failure", ConversionResult.Status.Failure, + "To upgrade ranks to v3.1.1 format, please first upgrade to prison v3.1.1. " + + "Then upgrade to a newer version of prison."); } @Override public String getName() { diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java index 642d26442..1c324a2e7 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankUtil.java @@ -37,7 +37,7 @@ import tech.mcprison.prison.ranks.events.RankUpEvent; import tech.mcprison.prison.ranks.managers.LadderManager; import tech.mcprison.prison.tasks.PrisonCommandTaskData; -import tech.mcprison.prison.tasks.PrisonCommandTaskData.CustomPlaceholders; +import tech.mcprison.prison.tasks.PrisonCommandTaskData.BlockEventCustomPlaceholders; /** * Utilities for changing the ranks of players. @@ -202,7 +202,7 @@ public static PromoteForceCharge fromString( String forceCharge ) { } public RankUtil() { - super(); + super(); } @@ -210,7 +210,7 @@ public RankUtil() { public RankupResults rankupPlayer(Player player, RankPlayer rankPlayer, String ladderName, String playerName, List cmdTasks ) { - return rankupPlayer(RankupCommands.rankup, player, rankPlayer, ladderName, null, + return rankupPlayer(RankupCommands.rankup, player, rankPlayer, ladderName, null, playerName, null, PromoteForceCharge.charge_player, cmdTasks ); } @@ -218,7 +218,7 @@ public RankupResults promotePlayer(Player player, RankPlayer rankPlayer, String String playerName, String executorName, PromoteForceCharge pForceCharge, List cmdTasks ) { - return rankupPlayer(RankupCommands.promote, player, rankPlayer, ladderName, null, + return rankupPlayer(RankupCommands.promote, player, rankPlayer, ladderName, null, playerName, executorName, pForceCharge, cmdTasks ); } @@ -226,7 +226,7 @@ public RankupResults demotePlayer(Player player, RankPlayer rankPlayer, String l String playerName, String executorName, PromoteForceCharge pForceCharge, List cmdTasks ) { - return rankupPlayer(RankupCommands.demote, player, rankPlayer, ladderName, null, + return rankupPlayer(RankupCommands.demote, player, rankPlayer, ladderName, null, playerName, executorName, pForceCharge, cmdTasks ); } @@ -234,10 +234,10 @@ public RankupResults setRank(Player player, RankPlayer rankPlayer, String ladder String playerName, String executorName, List cmdTasks ) { - RankupCommands rankupCmd = "FirstJoinEvent".equalsIgnoreCase( executorName ) ? + RankupCommands rankupCmd = "FirstJoinEvent".equalsIgnoreCase( executorName ) ? RankupCommands.firstJoin : RankupCommands.setrank; - return rankupPlayer( rankupCmd, player, rankPlayer, ladderName, rankName, + return rankupPlayer( rankupCmd, player, rankPlayer, ladderName, rankName, playerName, executorName, PromoteForceCharge.no_charge, cmdTasks ); } @@ -260,81 +260,79 @@ private RankupResults rankupPlayer(RankupCommands command, Player player, RankPl String rankName, String playerName, String executorName, PromoteForceCharge pForceCharge, List cmdTasks ) { - RankupResults results = new RankupResults(command, rankPlayer, executorName, ladderName, rankName); - - switch ( command ) { - case rankup: - results.addTransaction(RankupTransactions.tring_to_rankup); - break; - - case promote: - results.addTransaction(RankupTransactions.tring_to_promote); - break; - - case demote: - results.addTransaction(RankupTransactions.trying_to_demote); - break; - - case setrank: - results.addTransaction(RankupTransactions.trying_to_setrank); - break; - - case firstJoin: - results.addTransaction(RankupTransactions.trying_to_firstJoin); - break; - - default: - break; - } - - switch ( pForceCharge ) { - case no_charge: - results.addTransaction( RankupTransactions.bypassing_cost_for_player ); - break; - - case charge_player: - results.addTransaction( RankupTransactions.costs_paid_by_player ); - break; - - case refund_player: - results.addTransaction( RankupTransactions.costs_refunded_to_player ); - - break; - - default: - break; + RankupResults results = new RankupResults(command, rankPlayer, executorName, ladderName, rankName); + + switch ( command ) { + case rankup: + results.addTransaction(RankupTransactions.tring_to_rankup); + break; + + case promote: + results.addTransaction(RankupTransactions.tring_to_promote); + break; + + case demote: + results.addTransaction(RankupTransactions.trying_to_demote); + break; + + case setrank: + results.addTransaction(RankupTransactions.trying_to_setrank); + break; + + case firstJoin: + results.addTransaction(RankupTransactions.trying_to_firstJoin); + break; + + default: + break; + } + + switch ( pForceCharge ) { + case no_charge: + results.addTransaction( RankupTransactions.bypassing_cost_for_player ); + break; + + case charge_player: + results.addTransaction( RankupTransactions.costs_paid_by_player ); + break; + + case refund_player: + results.addTransaction( RankupTransactions.costs_refunded_to_player ); + + break; + + default: + break; } -// Player prisonPlayer = rankPlayer; -// Player prisonPlayer = PrisonAPI.getPlayer(player.uid).orElse(null); - if( player == null ) { - results.addTransaction( RankupStatus.RANKUP_FAILURE_COULD_NOT_LOAD_PLAYER, RankupTransactions.failed_player ); - return results; - } - + if( player == null ) { + results.addTransaction( RankupStatus.RANKUP_FAILURE_COULD_NOT_LOAD_PLAYER, RankupTransactions.failed_player ); + return results; + } + // If ladderName is null, then assign it the default ladder: if ( ladderName == null ) { - ladderName = LadderManager.LADDER_DEFAULT; - results.addTransaction(RankupTransactions.assigned_default_ladder); + ladderName = LadderManager.LADDER_DEFAULT; + results.addTransaction(RankupTransactions.assigned_default_ladder); } - try { - rankupPlayerInternal(results, command, player, rankPlayer, ladderName, - rankName, pForceCharge, cmdTasks ); - } catch (Exception e ) { - results.addTransaction( RankupTransactions.failure_exception_caught_check_server_logs ); - - Output.get().logError( rankUtilFailureInternalMsg( e.getMessage() ), e ); - } - - // Log the results: - logTransactionResults(results); - - return results; + try { + rankupPlayerInternal(results, command, player, rankPlayer, ladderName, + rankName, pForceCharge, cmdTasks ); + } catch (Exception e ) { + results.addTransaction( RankupTransactions.failure_exception_caught_check_server_logs ); + + Output.get().logError( rankUtilFailureInternalMsg( e.getMessage() ), e ); + } + + // Log the results: + logTransactionResults(results); + + return results; } @@ -350,12 +348,13 @@ private void rankupPlayerInternal(RankupResults results, String rankName, PromoteForceCharge pForceCharge, List cmdTasks ) { - Output.get().logDebug( DebugTarget.rankup, "Rankup: rankupPlayerInternal: "); + Output.get().logDebug( DebugTarget.rankup, "Rankup: rankupPlayerInternal: "); - RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); + RankLadder ladder = !PrisonRanks.getInstance().isEnabled() ? null : + PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); if( ladder == null ) { - results.addTransaction( RankupStatus.RANKUP_FAILURE_COULD_NOT_LOAD_LADDER, RankupTransactions.failed_ladder ); - return; + results.addTransaction( RankupStatus.RANKUP_FAILURE_COULD_NOT_LOAD_LADDER, RankupTransactions.failed_ladder ); + return; } results.setLadder( ladder ); @@ -377,16 +376,6 @@ private void rankupPlayerInternal(RankupResults results, results.addTransaction( RankupTransactions.player_has_no_rank_on_ladder ); } -// if ( originalRank == null && ladder.getName().equals( "default" ) ) { -// -// // Only default ladder should be logged as an error if there is no rank: -// results.addTransaction( RankupStatus.RANKUP_FAILURE_NO_PLAYERRANK, -// RankupTransactions.failure_orginal_playerRank_does_not_exist ); -// return; -// } - -// Optional currentRankOptional = player.getRank(ladder); -// Rank originalRank = currentRankOptional.orElse( null ); results.addTransaction( RankupTransactions.orginal_rank ); results.setPlayerRankOriginal( originalRank ); @@ -402,45 +391,45 @@ private void rankupPlayerInternal(RankupResults results, if ( results.getStatus() != RankupStatus.IN_PROGRESS ) { - // Failed while calculatingTargetRank so return now: - return; + // Failed while calculatingTargetRank so return now: + return; } // Process the remove rank request if ( command == RankupCommands.setrank && "-remove-".equalsIgnoreCase( rankName ) ) { - results.addTransaction(RankupTransactions.attempting_to_delete_ladder_from_player); - - if (LadderManager.LADDER_DEFAULT.equalsIgnoreCase( ladderName ) ) { - results.addTransaction(RankupTransactions.cannot_delete_default_ladder); - } - else { - boolean success = rankPlayerFactory.removeLadder( rankPlayer, ladder.getName() ); - - if ( success ) { - if ( savePlayerRank( results, rankPlayer ) ) { - - results.addTransaction( RankupStatus.RANKUP_LADDER_REMOVED, - RankupTransactions.ladder_was_removed_from_player ); - - return; - } - } - } - - results.addTransaction( RankupStatus.RANKUP_FAILURE_REMOVING_LADDER, - RankupTransactions.could_not_delete_ladder ); - - return; + results.addTransaction(RankupTransactions.attempting_to_delete_ladder_from_player); + + if (LadderManager.LADDER_DEFAULT.equalsIgnoreCase( ladderName ) ) { + results.addTransaction(RankupTransactions.cannot_delete_default_ladder); + } + else { + boolean success = rankPlayerFactory.removeLadder( rankPlayer, ladder.getName() ); + + if ( success ) { + if ( savePlayerRank( results, rankPlayer ) ) { + + results.addTransaction( RankupStatus.RANKUP_LADDER_REMOVED, + RankupTransactions.ladder_was_removed_from_player ); + + return; + } + } + } + + results.addTransaction( RankupStatus.RANKUP_FAILURE_REMOVING_LADDER, + RankupTransactions.could_not_delete_ladder ); + + return; } // Target rank is still null, so something failed so terminate: if ( targetRank == null ) { - results.addTransaction( RankupStatus.RANKUP_FAILURE_UNABLE_TO_ASSIGN_RANK, - RankupTransactions.failed_unable_to_assign_rank ); - return; + results.addTransaction( RankupStatus.RANKUP_FAILURE_UNABLE_TO_ASSIGN_RANK, + RankupTransactions.failed_unable_to_assign_rank ); + return; } @@ -452,29 +441,25 @@ private void rankupPlayerInternal(RankupResults results, PlayerRank pRankNext = null; + + // ??? Why not use targetRank here? Isn't that always non-null? if ( originalRank == null ) { - Rank nextRank = PrisonRanks.getInstance().getDefaultLadder().getLowestRank().orElse( null ); - pRankNext = rankPlayer.createPlayerRank(nextRank); + Rank nextRank = ladder.getLowestRank().orElse( null ); + + pRankNext = rankPlayer.createPlayerRank(nextRank); } else { - pRankNext = rankPlayer.calculateTargetPlayerRank( targetRank ); + pRankNext = rankPlayer.calculateTargetPlayerRank( targetRank ); } -// originalRank.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); -// new PlayerRank( targetRank, originalRank.getRankMultiplier() ); // If player does not have a rank on this ladder, then grab the first rank on the ladder since they need // to be added to the ladder. if ( pRankNext == null ) { - results.addTransaction( RankupStatus.RANKUP_FAILURE_RANK_DOES_NOT_EXIST, - RankupTransactions.failed_rank_not_in_ladder ); - return; - - -// pRankNext = rankPlayerFactory.createPlayerRank( targetRank ); - -// pRankNext = originalRank.getTargetPlayerRankForPlayer( rankPlayer, ladder.getLowestRank().get() ); + results.addTransaction( RankupStatus.RANKUP_FAILURE_RANK_DOES_NOT_EXIST, + RankupTransactions.failed_rank_not_in_ladder ); + return; } @@ -482,7 +467,6 @@ private void rankupPlayerInternal(RankupResults results, results.setTargetRank( targetRank ); -// String currency = ""; double nextRankCost = pRankNext == null || pRankNext.getRankCost() == null ? 0.0d : pRankNext.getRankCost(); @@ -499,11 +483,9 @@ private void rankupPlayerInternal(RankupResults results, if ( rankupEvent.isCanceled() ) { - - results.addTransaction( RankupStatus.RANKUP_EVENT_CANCELED, - RankupTransactions.failed_rankup_event_canceled_outside_of_prison ); - return; - + results.addTransaction( RankupStatus.RANKUP_EVENT_CANCELED, + RankupTransactions.failed_rankup_event_canceled_outside_of_prison ); + return; } @@ -586,7 +568,7 @@ else if ( pForceCharge == PromoteForceCharge.refund_player) { } else { - results.addTransaction( RankupTransactions.zero_cost_to_player ); + results.addTransaction( RankupTransactions.zero_cost_to_player ); } // Actually apply the new rank here: @@ -596,44 +578,44 @@ else if ( pForceCharge == PromoteForceCharge.refund_player) { // Validate that the player's rank was actually changed: PlayerRank newRank = rankPlayer.getPlayerRank( ladderName ); - if ( newRank.equals( originalRank ) || - !targetRank.equals( newRank.getRank() ) ) { - - results.setUnexpectedRank( newRank.getRank() ); - - results.addTransaction( RankupStatus.RANKUP_FAILURE_UNABLE_TO_ASSIGN_RANK, - RankupTransactions.failed_rankup_validation__target_rank_is_not_expected ); - - boolean success = false; - - // Refund charges and payments: - if ( pForceCharge == PromoteForceCharge.charge_player) { - - results.addTransaction( RankupTransactions.player_balance_refund_increased); - success = rankPlayer.addBalanceBypassCache( results.getOriginalRank().getCurrency(), currentRankCost ); - } - else if ( pForceCharge == PromoteForceCharge.refund_player) { - - - results.addTransaction( RankupTransactions.player_balance_refund_decreased ); - success = rankPlayer.removeBalanceBypassCache( targetRank.getCurrency(), nextRankCost ); - } else { - // Should never hit this code!! - } - - if ( !success ) { - // unable to reverse rankup costs or refunds - results.addTransaction( RankupTransactions.economy_failed_to_reverse_player_rankup_cost ); - } - - return; + if ( newRank != null && (newRank.equals( originalRank ) || + !targetRank.equals( newRank.getRank() )) ) { + + results.setUnexpectedRank( newRank.getRank() ); + + results.addTransaction( RankupStatus.RANKUP_FAILURE_UNABLE_TO_ASSIGN_RANK, + RankupTransactions.failed_rankup_validation__target_rank_is_not_expected ); + + boolean success = false; + + // Refund charges and payments: + if ( pForceCharge == PromoteForceCharge.charge_player) { + + results.addTransaction( RankupTransactions.player_balance_refund_increased); + success = rankPlayer.addBalanceBypassCache( results.getOriginalRank().getCurrency(), currentRankCost ); + } + else if ( pForceCharge == PromoteForceCharge.refund_player) { + + + results.addTransaction( RankupTransactions.player_balance_refund_decreased ); + success = rankPlayer.removeBalanceBypassCache( targetRank.getCurrency(), nextRankCost ); + } else { + // Should never hit this code!! + } + + if ( !success ) { + // unable to reverse rankup costs or refunds + results.addTransaction( RankupTransactions.economy_failed_to_reverse_player_rankup_cost ); + } + + return; } if ( !savePlayerRank( results, rankPlayer ) ) { - return; + return; } // Now, we'll run the rank up commands. @@ -650,20 +632,20 @@ else if ( pForceCharge == PromoteForceCharge.refund_player) { for ( int row = 0; row < rankupCommands.size(); row++ ) { - String cmd = rankupCommands.get( row ); - if ( cmd != null && - ( !cmd.contains( "{firstJoin}" ) || - cmd.contains( "{firstJoin}" ) && command == RankupCommands.firstJoin ) ) { - - PlayerRank opRank = results.getPlayerRankOriginal(); - PlayerRank tpRank = results.getPlayerRankTarget(); - - Rank oRank = results.getOriginalRank(); - Rank tRank = results.getTargetRank(); - - if ( command == RankupCommands.firstJoin && cmd.contains( "{firstJoin}" ) ) { - cmd = cmd.replace( "{firstJoin}", "" ); - } + String cmd = rankupCommands.get( row ); + if ( cmd != null && + ( !cmd.contains( "{firstJoin}" ) || + cmd.contains( "{firstJoin}" ) && command == RankupCommands.firstJoin ) ) { + + PlayerRank opRank = results.getPlayerRankOriginal(); + PlayerRank tpRank = results.getPlayerRankTarget(); + + Rank oRank = results.getOriginalRank(); + Rank tRank = results.getTargetRank(); + + if ( command == RankupCommands.firstJoin && cmd.contains( "{firstJoin}" ) ) { + cmd = cmd.replace( "{firstJoin}", "" ); + } PrisonCommandTaskData cmdTask = new PrisonCommandTaskData( command.name(), cmd, row ); @@ -672,44 +654,33 @@ else if ( pForceCharge == PromoteForceCharge.refund_player) { cmdTask.setRankOriginal( opRank ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.balanceInitial, Double.toString( results.getBalanceInitial()) ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.balanceFinal, Double.toString( results.getBalanceFinal()) ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.currency, results.getCurrency() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.balanceInitial, Double.toString( results.getBalanceInitial()) ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.balanceFinal, Double.toString( results.getBalanceFinal()) ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.currency, results.getCurrency() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.originalRankCost, + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.originalRankCost, opRank == null ? "" : Double.toString( opRank.getRankCost() ) ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.rankupCost, + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.rankupCost, tpRank == null ? "" : Double.toString( tpRank.getRankCost() ) ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.ladder, results.getLadderName() ); + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.ladder, results.getLadderName() ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.rank, + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.rank, (oRank == null ? "none" : oRank.getName()) ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.rankTag, + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.rankTag, (oRank == null ? "none" : oRank.getTag()) ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.targetRank, + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.targetRank, (tRank == null ? "none" : tRank.getName()) ); - cmdTask.addCustomPlaceholder( CustomPlaceholders.targetRankTag, + cmdTask.addCustomPlaceholder( BlockEventCustomPlaceholders.targetRankTag, (tRank == null ? "none" : tRank.getTag()) ); cmdTasks.add( cmdTask ); - // Comment this out to stack the rank commands: - // cmdTask.submitCommandTask( prisonPlayer ); - - -// String formatted = cmd.replace("{player}", prisonPlayer.getName()) -// .replace("{player_uid}", rankPlayer.getUUID().toString()); - -// Prison.get().getPlatform().logPlain( -// String.format( "RankUtil.rankupPlayerInternal: Rank Command: [%s]", -// formatted )); - -// PrisonAPI.dispatchCommand(formatted); - count++; - } + + count++; + } } results.setRankupCommandsExecuted( count ); results.addTransaction( RankupTransactions.rankupCommandsCompleted ); @@ -723,20 +694,12 @@ else if ( pForceCharge == PromoteForceCharge.refund_player) { // Sort the Top ranked list: -// rankPlayer.forcePlayerToRecalculateRankScore(); TopNPlayers.getInstance().updatePlayerData(rankPlayer); -// results.addTransaction( RankupTransactions.fireRankupEvent ); -// -// // Nothing can cancel a RankUpEvent: -// RankUpEvent rankupEvent = new RankUpEvent(rankPlayer, originalRank, targetRank, nextRankCost); -// Prison.get().getEventBus().post(rankupEvent); - - if ( RankupCommands.demote == command ) { - results.addTransaction( RankupStatus.DEMOTE_SUCCESS, RankupTransactions.demote_successful ); + results.addTransaction( RankupStatus.DEMOTE_SUCCESS, RankupTransactions.demote_successful ); } else { @@ -749,49 +712,42 @@ else if ( pForceCharge == PromoteForceCharge.refund_player) { private boolean savePlayerRank( RankupResults results, RankPlayer rankPlayer ) { boolean success = false; -// try { - PrisonRanks.getInstance().getPlayerManager().savePlayer(rankPlayer); - - results.addTransaction( - RankupTransactions.successfully_saved_player_rank_data ); - - success = true; -// } -// catch (IOException e) { -// -// Output.get().logError( rankUtilFailureSavingPlayerMsg( e.getMessage() ), e ); -// -// results.addTransaction( RankupStatus.RANKUP_FAILURE_COULD_NOT_SAVE_PLAYER_FILE, -// RankupTransactions.failure_cannot_save_player_file ); -// } - + PrisonRanks.getInstance().getPlayerManager().savePlayer(rankPlayer); + + results.addTransaction( + RankupTransactions.successfully_saved_player_rank_data ); + + success = true; + return success; } private Rank calculateTargetRank(RankupCommands command, RankupResults results, // Rank originalRank, // RankLadder ladder, String ladderName, - String rankName ) { - Rank targetRank = null; + String rankName ) { + + Rank targetRank = null; // For all commands except for setrank, if the player does not have a current rank, then // set it to the default and skip all other rank processing: - // NOTE: With new processing using PlayerRank, not sure if the default rank should be set to anything... - // I'm thinking no... + // NOTE: With new processing using PlayerRank, not sure if the default rank should be set to anything... + // I'm thinking no... if ( results.getOriginalRank() == null && ( command == RankupCommands.rankup || command == RankupCommands.promote || command == RankupCommands.demote )) { - // Set the default rank: + + // Set the default rank: Optional lowestRank = results.getLadder().getLowestRank(); -// Optional lowestRank = ladder.getByPosition(0); + if (!lowestRank.isPresent()) { - results.addTransaction( RankupStatus.RANKUP_NO_RANKS, - RankupTransactions.no_ranks_found_on_ladder ); - return targetRank; + results.addTransaction( RankupStatus.RANKUP_NO_RANKS, + RankupTransactions.no_ranks_found_on_ladder ); + return targetRank; } results.addTransaction( RankupTransactions.set_to_default_rank ); targetRank = lowestRank.get(); @@ -801,7 +757,7 @@ private Rank calculateTargetRank(RankupCommands command, RankupResults results, } if ( results.getOriginalRank() == null ) { - results.addTransaction( RankupTransactions.original_rank_is_null ); + results.addTransaction( RankupTransactions.original_rank_is_null ); } @@ -810,267 +766,209 @@ private Rank calculateTargetRank(RankupCommands command, RankupResults results, // If default ladder and rank is null at this point, that means use the "default" rank: if ( command == RankupCommands.setrank || command == RankupCommands.firstJoin ) { - if ( "-remove-".equalsIgnoreCase( rankName ) ) { - - // process the -remove- rank after this function returns: - return targetRank; - } - - else if (LadderManager.LADDER_DEFAULT.equalsIgnoreCase( results.getLadder().getName() ) && rankName == null ) { - Optional lowestRank = results.getLadder().getLowestRank(); - if ( lowestRank.isPresent() ) { - targetRank = lowestRank.get(); - rankName = targetRank.getName(); - - results.addTransaction(RankupTransactions.assigned_default_rank); + if ( "-remove-".equalsIgnoreCase( rankName ) ) { + + // process the -remove- rank after this function returns: + return targetRank; + } + + else if (LadderManager.LADDER_DEFAULT.equalsIgnoreCase( results.getLadder().getName() ) && rankName == null ) { + Optional lowestRank = results.getLadder().getLowestRank(); + if ( lowestRank.isPresent() ) { + targetRank = lowestRank.get(); + rankName = targetRank.getName(); + + results.addTransaction(RankupTransactions.assigned_default_rank); + } + } - - } - - if ( targetRank == null && rankName != null ) { - - targetRank = PrisonRanks.getInstance().getRankManager().getRank( rankName ); - - if ( targetRank != null ) { - - if ( !results.getLadder().containsRank( targetRank )) { - results.addTransaction( RankupStatus.RANKUP_FAILURE_RANK_IS_NOT_IN_LADDER, - RankupTransactions.failed_rank_not_in_ladder ); - return targetRank; - } - } else { - results.addTransaction( RankupStatus.RANKUP_FAILURE_RANK_DOES_NOT_EXIST, - RankupTransactions.failed_rank_not_found ); - return targetRank; - } - } else { - results.addTransaction( RankupTransactions.failed_setrank ); - - // Got a problem... if using setrank and no rankName is provided, this is a problem - // But it should never get this far if that is the situation - } + + if ( targetRank == null && rankName != null ) { + + targetRank = PrisonRanks.getInstance().getRankManager().getRank( rankName ); + + if ( targetRank != null ) { + + if ( !results.getLadder().containsRank( targetRank )) { + results.addTransaction( RankupStatus.RANKUP_FAILURE_RANK_IS_NOT_IN_LADDER, + RankupTransactions.failed_rank_not_in_ladder ); + return targetRank; + } + } else { + results.addTransaction( RankupStatus.RANKUP_FAILURE_RANK_DOES_NOT_EXIST, + RankupTransactions.failed_rank_not_found ); + return targetRank; + } + } else { + results.addTransaction( RankupTransactions.failed_setrank ); + + // Got a problem... if using setrank and no rankName is provided, this is a problem + // But it should never get this far if that is the situation + } } if ( targetRank == null ) { - if ( command == RankupCommands.rankup || command == RankupCommands.promote ) { - // Trying to promote: -// nextRankOptional = ladder.getNext(ladder.getPositionOfRank(currentRankOptional.get())); - - if ( results.getOriginalRank().getRankNext() == null ) { - // We're already at the highest rank. - results.addTransaction( RankupStatus.RANKUP_HIGHEST, - RankupTransactions.no_higher_rank_found ); - return targetRank; - } - targetRank = results.getOriginalRank().getRankNext(); - results.addTransaction( RankupTransactions.set_to_next_higher_rank ); - - } else if ( command == RankupCommands.demote ) { - // Trying to demote: -// nextRankOptional = ladder.getPrevious(ladder.getPositionOfRank(currentRankOptional.get())); - - if ( results.getOriginalRank().getRankPrior() == null ) { - // We're already at the lowest rank. - results.addTransaction( RankupStatus.RANKUP_LOWEST, - RankupTransactions.no_lower_rank_found ); - return targetRank; - } - targetRank = results.getOriginalRank().getRankPrior(); - results.addTransaction( RankupTransactions.set_to_prior_lower_rank ); - } + if ( command == RankupCommands.rankup || command == RankupCommands.promote ) { + // Trying to promote: + + if ( results.getOriginalRank().getRankNext() == null ) { + // We're already at the highest rank. + results.addTransaction( RankupStatus.RANKUP_HIGHEST, + RankupTransactions.no_higher_rank_found ); + return targetRank; + } + targetRank = results.getOriginalRank().getRankNext(); + results.addTransaction( RankupTransactions.set_to_next_higher_rank ); + + } else if ( command == RankupCommands.demote ) { + // Trying to demote: + + if ( results.getOriginalRank().getRankPrior() == null ) { + // We're already at the lowest rank. + results.addTransaction( RankupStatus.RANKUP_LOWEST, + RankupTransactions.no_lower_rank_found ); + return targetRank; + } + targetRank = results.getOriginalRank().getRankPrior(); + results.addTransaction( RankupTransactions.set_to_prior_lower_rank ); + } } return targetRank; } - -// public static int doubleToInt(Object d) { -// return Math.toIntExact(Math.round((double) d)); -// } -// -// public static long doubleToLong(Object d) { -// return Math.round((double) d); -// } - - private void logTransactionResults( RankupResults results ) { - StringBuilder sb = new StringBuilder(); - DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); - DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); - - Rank oRank = results.getOriginalRank(); - PlayerRank opRank = results.getPlayerRankOriginal(); - - Rank tRank = results.getTargetRank(); - PlayerRank tpRank = results.getPlayerRankTarget(); - - for ( RankupTransactions rt : RankupTransactions.values() ) { - - // Log the entry if it exists in the results: - if ( results.getTransactions().contains( rt ) ) { - if ( sb.length() > 0 ) { - sb.append( " " ); - } - - // Log the transaction: - sb.append( rt.name() ); - - // If the transaction has supporting data, log it too: - switch ( rt ) { - case orginal_rank: - sb.append( "=" ); - sb.append( oRank == null ? "" : oRank.getName() ); - - break; - - case custom_currency: - sb.append( "=" ); - sb.append( tRank == null || tRank.getCurrency() == null ? "" : tRank.getCurrency() ); - - break; - - case specified_currency_not_found: - sb.append( "=" ); - sb.append( tRank == null || tRank.getCurrency() == null ? "" : tRank.getCurrency() ); - - break; - - case player_balance_initial: - sb.append( "=" ); - sb.append( dFmt.format( results.getBalanceInitial() ) ); - - break; - - case player_balance_decreased: - sb.append( "=" ); - sb.append( tpRank == null ? "" : dFmt.format( tpRank.getRankCost() ) ); - - break; - - case player_balance_increased: - sb.append( "=" ); - sb.append( opRank == null ? "" : dFmt.format( opRank.getRankCost() ) ); - - break; - - case player_balance_final: - sb.append( "=" ); - sb.append( dFmt.format( results.getBalanceFinal() ) ); - - break; - - case accuracy_out_of_range: - sb.append( "=" ); - DecimalFormat sFmt = Prison.get().getDecimalFormat("#,##0.00000000"); - sb.append( sFmt.format( results.getRankupCostFinalAccuracy() ) ); - - break; - - case rankupCommandsStart: - sb.append( "=" ); - sb.append( iFmt.format( results.getRankupCommandsAvailable() ) ); - - break; - - case rankupCommandsCompleted: - sb.append( "=" ); - sb.append( iFmt.format( results.getRankupCommandsExecuted() ) ); - - break; - - case failed_rankup_validation__target_rank_is_not_expected: - - default: - break; - } - } - } + StringBuilder sb = new StringBuilder(); + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); + DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); + + Rank oRank = results.getOriginalRank(); + PlayerRank opRank = results.getPlayerRankOriginal(); + + Rank tRank = results.getTargetRank(); + PlayerRank tpRank = results.getPlayerRankTarget(); + for ( RankupTransactions rt : RankupTransactions.values() ) { + + // Log the entry if it exists in the results: + if ( results.getTransactions().contains( rt ) ) { + if ( sb.length() > 0 ) { + sb.append( " " ); + } + + // Log the transaction: + sb.append( rt.name() ); + + // If the transaction has supporting data, log it too: + switch ( rt ) { + case orginal_rank: + sb.append( "=" ); + sb.append( oRank == null ? "" : oRank.getName() ); + + break; + + case custom_currency: + sb.append( "=" ); + sb.append( tRank == null || tRank.getCurrency() == null ? "" : tRank.getCurrency() ); + + break; + + case specified_currency_not_found: + sb.append( "=" ); + sb.append( tRank == null || tRank.getCurrency() == null ? "" : tRank.getCurrency() ); + + break; + + case player_balance_initial: + sb.append( "=" ); + sb.append( dFmt.format( results.getBalanceInitial() ) ); + + break; + + case player_balance_decreased: + sb.append( "=" ); + sb.append( tpRank == null ? "" : dFmt.format( tpRank.getRankCost() ) ); + + break; + + case player_balance_increased: + sb.append( "=" ); + sb.append( opRank == null ? "" : dFmt.format( opRank.getRankCost() ) ); + + break; + + case player_balance_final: + sb.append( "=" ); + sb.append( dFmt.format( results.getBalanceFinal() ) ); + + break; + + case accuracy_out_of_range: + sb.append( "=" ); + DecimalFormat sFmt = Prison.get().getDecimalFormat("#,##0.00000000"); + sb.append( sFmt.format( results.getRankupCostFinalAccuracy() ) ); + + break; + + case rankupCommandsStart: + sb.append( "=" ); + sb.append( iFmt.format( results.getRankupCommandsAvailable() ) ); + + break; + + case rankupCommandsCompleted: + sb.append( "=" ); + sb.append( iFmt.format( results.getRankupCommandsExecuted() ) ); + + break; + + case failed_rankup_validation__target_rank_is_not_expected: + + default: + break; + } + } + } - // Add in the prefix for the log entry: - String prefix = String.format( - "Rankup: command=%s player=%s executor=%s status=%s " + - "ladderName=%s rankName=%s " + - "originalRank=(%s%s%s) targetRank=(%s%s%s) " + - "runtime=%s ms message=[%s] ", - - results.getCommand().name(), - results.getRankPlayer().getName(), - (results.getExecutor() == null ? "(see player)" : results.getExecutor()), - (results.getStatus() == null ? "" : results.getStatus().name()), - - (results.getLadderName() == null ? "" : results.getLadderName() ), - (results.getRankName() == null ? "" : results.getRankName() ), - - - (oRank == null ? "none" : oRank.getName()), - (opRank == null ? "" : " " + dFmt.format( opRank.getRankCost() )), - (oRank == null || oRank.getCurrency() == null ? "" : " " + oRank.getCurrency()), - - (tRank == null ? "none" : tRank.getName()), - (tpRank == null || tpRank.getRankCost() == null ? - "" : " " + dFmt.format( tpRank.getRankCost())), - (tRank == null || tRank.getCurrency() == null ? "" : " " + tRank.getCurrency()), - - iFmt.format( results.getElapsedTime() ), - (results.getMessage() == null ? "" : results.getMessage()) - ); - sb.insert( 0, prefix ); + // Add in the prefix for the log entry: + String prefix = String.format( + "Rankup: command=%s player=%s executor=%s status=%s " + + "ladderName=%s rankName=%s " + + "originalRank=(%s%s%s) targetRank=(%s%s%s) " + + "runtime=%s ms message=[%s] ", + + results.getCommand().name(), + results.getRankPlayer().getName(), + (results.getExecutor() == null ? "(see player)" : results.getExecutor()), + (results.getStatus() == null ? "" : results.getStatus().name()), + + (results.getLadderName() == null ? "" : results.getLadderName() ), + (results.getRankName() == null ? "" : results.getRankName() ), + + + (oRank == null ? "none" : oRank.getName()), + (opRank == null ? "" : " " + dFmt.format( opRank.getRankCost() )), + (oRank == null || oRank.getCurrency() == null ? "" : " " + oRank.getCurrency()), + + (tRank == null ? "none" : tRank.getName()), + (tpRank == null || tpRank.getRankCost() == null ? + "" : " " + dFmt.format( tpRank.getRankCost())), + (tRank == null || tRank.getCurrency() == null ? "" : " " + tRank.getCurrency()), + + iFmt.format( results.getElapsedTime() ), + (results.getMessage() == null ? "" : results.getMessage()) + ); + + sb.insert( 0, prefix ); - Output.get().logInfo( sb.toString() ); + Output.get().logInfo( sb.toString() ); } - -// @Deprecated -// public static class RankUpResult { -// -// private RankupStatus status; -// private Rank rank; -// private String message; -// -// public RankUpResult(RankupStatus status, Rank rank, String message) { -// this.status = status; -// this.rank = rank; -// this.message = message; -// } -// -// public RankUpResult(RankupStatus status, Rank rank) { -// this(status, rank, null); -// } -// -// public RankUpResult(RankupStatus status) { -// this(status, null, null); -// } -// -// -// public RankupStatus getStatus() { -// return status; -// } -// public void setStatus( RankupStatus status ) { -// this.status = status; -// } -// -// public Rank getRank() { -// return rank; -// } -// public void setRank( Rank rank ) { -// this.rank = rank; -// } -// -// public String getMessage() { -// return message; -// } -// public void setMessage( String message ) { -// this.message = message; -// } -// } - - } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankupResults.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankupResults.java index f934bd2ab..41a245bf1 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankupResults.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/RankupResults.java @@ -17,7 +17,6 @@ public class RankupResults { private RankupCommands command; RankPlayer rankPlayer; -// private String player; private String executor; private RankupStatus status; @@ -51,12 +50,12 @@ public RankupResults(RankupCommands command, RankPlayer rankPlayer, String execu this.status = RankupStatus.IN_PROGRESS; - this.transactions = new ArrayList<>(); - - this.command = command; - - this.rankPlayer = rankPlayer; -// this.player = playerName; + this.transactions = new ArrayList<>(); + + this.command = command; + + this.rankPlayer = rankPlayer; + this.executor = executorName; this.ladderName = ladderName; @@ -69,22 +68,22 @@ public RankupResults(RankupCommands command, RankPlayer rankPlayer, String execu public RankupResults addTransaction( RankupStatus status, RankupTransactions transaction ) { - setStatus( status ); - getTransactions().add( transaction ); - this.timestampStop = System.currentTimeMillis(); - return this; + setStatus( status ); + getTransactions().add( transaction ); + this.timestampStop = System.currentTimeMillis(); + return this; } public RankupResults addTransaction( RankupTransactions transaction ) { - getTransactions().add( transaction ); - this.timestampStop = System.currentTimeMillis(); - return this; + getTransactions().add( transaction ); + this.timestampStop = System.currentTimeMillis(); + return this; } public long getElapsedTime() { - long elapsed = getTimestampStart() - getTimestampStop(); - - return ( elapsed < 0 ? 0 : elapsed); + long elapsed = getTimestampStart() - getTimestampStop(); + + return ( elapsed < 0 ? 0 : elapsed); } @@ -102,14 +101,6 @@ public void setRankPlayer( RankPlayer rankPlayer ) { this.rankPlayer = rankPlayer; } -// public String getPlayer() { -// return player; -// } -// public void setPlayer( String player ) { -// this.player = player; -// } - - public RankLadder getLadder() { return ladder; } @@ -164,20 +155,10 @@ public PlayerRank getPlayerRankTarget() { getOriginalRank() != null && getOriginalRank().getRankNext() != null && targetRank != null ) { -// RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - -// PlayerRank pRank = rankPlayerFactory.createPlayerRank( getOriginalRank() ); // This calculates the target rank, and takes in to consideration the player's existing rank: playerRankTarget = rankPlayer.calculateTargetPlayerRank( targetRank ); -// playerRankTarget = pRank.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); -// playerRankTarget = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, targetRank ); - -// PlayerRank pRank = rankPlayer.getRank( originalRank.getLadder() ); -// PlayerRank pRankNext = new PlayerRank( targetRank, pRank.getRankMultiplier() ); - -// playerRankTarget = pRankNext; } return playerRankTarget; } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/CommandCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/CommandCommands.java index 57c40c769..1c7e36dfd 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/CommandCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/CommandCommands.java @@ -50,29 +50,29 @@ public void commandAdd(CommandSender sender, } if ( command.contains( "%" ) ) { - ranksCommandAddCannotUsePercentSymbols( sender ); - return; + ranksCommandAddCannotUsePercentSymbols( sender ); + return; } if ( rankName != null && "placeholders".equalsIgnoreCase( rankName ) ) { - String placeholders = - - PrisonCommandTaskData.CustomPlaceholders.listPlaceholders( - PrisonCommandTaskData.CommandEnvironment.all_commands ) + " " + - - PrisonCommandTaskData.CustomPlaceholders.listPlaceholders( - PrisonCommandTaskData.CommandEnvironment.rank_commands ); - - String message = ranksCommandAddPlaceholdersMsg( placeholders ); - - sender.sendMessage( message ); - return; + String placeholders = + + PrisonCommandTaskData.BlockEventCustomPlaceholders.listPlaceholders( + PrisonCommandTaskData.CommandEnvironment.all_commands ) + " " + + + PrisonCommandTaskData.BlockEventCustomPlaceholders.listPlaceholders( + PrisonCommandTaskData.CommandEnvironment.rank_commands ); + + String message = ranksCommandAddPlaceholdersMsg( placeholders ); + + sender.sendMessage( message ); + return; } Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); if ( rank == null ) { - rankDoesNotExistMsg( sender, rankName ); + rankDoesNotExistMsg( sender, rankName ); return; } @@ -108,13 +108,13 @@ public void commandRemove(CommandSender sender, Integer row) { if ( row == null || row <= 0 ) { - rankRowNumberMustBeGreaterThanZero( sender, row ); - return; + rankRowNumberMustBeGreaterThanZero( sender, row ); + return; } Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); if ( rank == null) { - rankDoesNotExistMsg( sender, rankName ); + rankDoesNotExistMsg( sender, rankName ); return; } @@ -123,20 +123,20 @@ public void commandRemove(CommandSender sender, } if ( row > rank.getRankUpCommands().size() ) { - rankRowNumberTooHigh( sender, rank.getRankUpCommands().size(), row ); - return; + rankRowNumberTooHigh( sender, rank.getRankUpCommands().size(), row ); + return; } String oldCommand = rank.getRankUpCommands().remove( (int) row - 1 ); if ( oldCommand != null ) { - - PrisonRanks.getInstance().getRankManager().saveRank( rank ); - - ranksCommandRemoveSuccessMsg( sender, oldCommand, rank.getName() ); + + PrisonRanks.getInstance().getRankManager().saveRank( rank ); + + ranksCommandRemoveSuccessMsg( sender, oldCommand, rank.getName() ); } else { - ranksCommandRemoveFailedMsg( sender ); + ranksCommandRemoveFailedMsg( sender ); } // Redisplay the the rank command list: @@ -152,12 +152,12 @@ public void commandList(CommandSender sender, Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); if ( rank == null ) { - rankDoesNotExistMsg( sender, rankName ); + rankDoesNotExistMsg( sender, rankName ); return; } if (rank.getRankUpCommands() == null || rank.getRankUpCommands().size() == 0) { - ranksCommandListContainsNoneMsg( sender, rank.getName() ); + ranksCommandListContainsNoneMsg( sender, rank.getName() ); return; } @@ -176,7 +176,7 @@ protected ChatDisplay commandListDetails( Rank rank, boolean noRemoves ) ChatDisplay display = new ChatDisplay( ranksCommandListCmdHeaderMsg( title )); if ( !noRemoves ) { - display.addText( ranksCommandListClickCmdToRemoveMsg() ); + display.addText( ranksCommandListClickCmdToRemoveMsg() ); } BulletedListComponent.BulletedListBuilder builder = new BulletedListComponent.BulletedListBuilder(); @@ -184,18 +184,18 @@ protected ChatDisplay commandListDetails( Rank rank, boolean noRemoves ) int rowNumber = 1; for (String command : rank.getRankUpCommands()) { - RowComponent row = new RowComponent(); - - row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); + RowComponent row = new RowComponent(); + + row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); FancyMessage msg = new FancyMessage("&3/" + command); row.addFancy( msg ); if ( !noRemoves ) { - FancyMessage msgRemove = new FancyMessage( " &4Remove&3" ) - .suggest("/ranks command remove " + rank.getName() + " " + (rowNumber - 1) ) - .tooltip( ranksCommandListClickToRemoveMsg() ); - row.addFancy( msgRemove ); + FancyMessage msgRemove = new FancyMessage( " &4Remove&3" ) + .suggest("/ranks command remove " + rank.getName() + " " + (rowNumber - 1) ) + .tooltip( ranksCommandListClickToRemoveMsg() ); + row.addFancy( msgRemove ); } builder.add( row ); @@ -224,37 +224,38 @@ public void commandLadderAdd(CommandSender sender, @Arg(name = "command", description = "The command to add without / prefix. Will be ran as a console command.") @Wildcard String command) { + if (command.startsWith("/")) { command = command.replaceFirst("/", ""); } if ( command.contains( "%" ) ) { - ranksCommandAddCannotUsePercentSymbols( sender ); - return; + ranksCommandAddCannotUsePercentSymbols( sender ); + return; } if ( ladderName != null && "placeholders".equalsIgnoreCase( ladderName ) ) { - String placeholders = PrisonCommandTaskData.CustomPlaceholders.listPlaceholders( - PrisonCommandTaskData.CommandEnvironment.all_commands ) + " " + - - PrisonCommandTaskData.CustomPlaceholders.listPlaceholders( - PrisonCommandTaskData.CommandEnvironment.rank_commands ); - - String message = ladderCommandAddPlaceholdersMsg( placeholders ); - - sender.sendMessage( message ); - return; + String placeholders = PrisonCommandTaskData.BlockEventCustomPlaceholders.listPlaceholders( + PrisonCommandTaskData.CommandEnvironment.all_commands ) + " " + + + PrisonCommandTaskData.BlockEventCustomPlaceholders.listPlaceholders( + PrisonCommandTaskData.CommandEnvironment.rank_commands ); + + String message = ladderCommandAddPlaceholdersMsg( placeholders ); + + sender.sendMessage( message ); + return; } RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); if ( ladder == null ) { - ladderDoesNotExistMsg( sender, ladderName ); + ladderDoesNotExistMsg( sender, ladderName ); return; } if (ladder.getRankUpCommands() == null) { - ladder.setRankUpCommands( new ArrayList<>() ); + ladder.setRankUpCommands( new ArrayList<>() ); } @@ -286,13 +287,13 @@ public void commandLadderRemove(CommandSender sender, Integer row) { if ( row == null || row <= 0 ) { - rankRowNumberMustBeGreaterThanZero( sender, row ); - return; + rankRowNumberMustBeGreaterThanZero( sender, row ); + return; } RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); if ( ladder == null) { - ladderDoesNotExistMsg( sender, ladderName ); + ladderDoesNotExistMsg( sender, ladderName ); return; } @@ -301,20 +302,20 @@ public void commandLadderRemove(CommandSender sender, } if ( row > ladder.getRankUpCommands().size() ) { - rankRowNumberTooHigh( sender, ladder.getRankUpCommands().size(), row ); - return; + rankRowNumberTooHigh( sender, ladder.getRankUpCommands().size(), row ); + return; } String oldCommand = ladder.getRankUpCommands().remove( (int) row - 1 ); if ( oldCommand != null ) { - PrisonRanks.getInstance().getLadderManager().save( ladder ); - - ladderCommandRemoveSuccessMsg( sender, oldCommand, ladder.getName() ); + PrisonRanks.getInstance().getLadderManager().save( ladder ); + + ladderCommandRemoveSuccessMsg( sender, oldCommand, ladder.getName() ); } else { - ladderCommandRemoveFailedMsg( sender ); + ladderCommandRemoveFailedMsg( sender ); } // Redisplay the the rank command list: @@ -329,12 +330,12 @@ public void commandLadderList(CommandSender sender, RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); if ( ladder == null ) { - ladderDoesNotExistMsg( sender, ladderName ); + ladderDoesNotExistMsg( sender, ladderName ); return; } if (ladder.getRankUpCommands() == null || ladder.getRankUpCommands().size() == 0) { - ladderCommandListContainsNoneMsg( sender, ladder.getName() ); + ladderCommandListContainsNoneMsg( sender, ladder.getName() ); return; } @@ -350,7 +351,7 @@ protected ChatDisplay commandLadderListDetail( RankLadder ladder, boolean noRemo { ChatDisplay display = new ChatDisplay( ladderCommandListCmdHeaderMsg( ladder.getName() )); if ( !noRemoves ) { - display.addText( ranksCommandListClickCmdToRemoveMsg() ); + display.addText( ranksCommandListClickCmdToRemoveMsg() ); } BulletedListComponent.BulletedListBuilder builder = @@ -358,20 +359,20 @@ protected ChatDisplay commandLadderListDetail( RankLadder ladder, boolean noRemo int rowNumber = 1; for (String command : ladder.getRankUpCommands()) { - - RowComponent row = new RowComponent(); - - row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); + + RowComponent row = new RowComponent(); + + row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); FancyMessage msg = new FancyMessage("&3/" + command); row.addFancy( msg ); if ( !noRemoves ) { - FancyMessage msgRemove = new FancyMessage( " &4Remove&3" ) - .suggest("/ranks ladder command remove " + ladder.getName() + " " + (rowNumber - 1) ) - .tooltip( ranksCommandListClickToRemoveMsg() ); - row.addFancy( msgRemove ); + FancyMessage msgRemove = new FancyMessage( " &4Remove&3" ) + .suggest("/ranks ladder command remove " + ladder.getName() + " " + (rowNumber - 1) ) + .tooltip( ranksCommandListClickToRemoveMsg() ); + row.addFancy( msgRemove ); } builder.add( row ); diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/CommandCommandsMessages.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/CommandCommandsMessages.java index 8d12ab51a..3a85fb33e 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/CommandCommandsMessages.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/CommandCommandsMessages.java @@ -113,19 +113,19 @@ protected String ranksCommandListAddNewCommandToolTipMsg() { protected void rankRowNumberMustBeGreaterThanZero( CommandSender sender, Integer row ) { PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_commandCommands__command_row_number_must_be_greater_than_zero" ) - .withReplacements( - Integer.toString( row ) ) - .sendTo( sender ); + .getLocalizable( "ranks_commandCommands__command_row_number_must_be_greater_than_zero" ) + .withReplacements( + Integer.toString( row ) ) + .sendTo( sender ); } protected void rankRowNumberTooHigh( CommandSender sender, Integer maxValue, Integer row ) { - PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_commandCommands__command_row_number_too_high" ) - .withReplacements( - Integer.toString( maxValue ), - Integer.toString( row ) ) - .sendTo( sender ); + PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_commandCommands__command_row_number_too_high" ) + .withReplacements( + Integer.toString( maxValue ), + Integer.toString( row ) ) + .sendTo( sender ); } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/FailedRankCommands.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/FailedRankCommands.java index 5c03dbe8b..79efc168d 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/FailedRankCommands.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/FailedRankCommands.java @@ -58,9 +58,6 @@ public void failedRanks( CommandSender sender ) { display.send( player ); } -// if ( sender.isPlayer() ) { -// display.send( sender ); -// } } 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 a5e73fa1f..e4f7cb3ba 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 @@ -32,7 +32,7 @@ public void ladderAdd(CommandSender sender, @Arg(name = "ladderName") String lad RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); if ( ladder != null ) { - ladderAddAlreadyExistsMsg( sender, ladderName ); + ladderAddAlreadyExistsMsg( sender, ladderName ); return; } @@ -40,7 +40,7 @@ public void ladderAdd(CommandSender sender, @Arg(name = "ladderName") String lad if ( rankLadder == null ) { - ladderAddCreationErrorMsg( sender, ladderName ); + ladderAddCreationErrorMsg( sender, ladderName ); return; } @@ -48,17 +48,17 @@ public void ladderAdd(CommandSender sender, @Arg(name = "ladderName") String lad if ( PrisonRanks.getInstance().getLadderManager().save(rankLadder) ) { - Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); - - - ladderAddCreatedMsg( sender, ladderName ); + Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); + + + ladderAddCreatedMsg( sender, ladderName ); } else { - ladderAddCreationErrorMsg( sender, ladderName ); - - ladderAddCouldNotSaveMsg( sender ); + ladderAddCreationErrorMsg( sender, ladderName ); + + ladderAddCouldNotSaveMsg( sender ); } } @@ -68,30 +68,30 @@ public void ladderRemove(CommandSender sender, @Arg(name = "ladderName") String RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); if ( ladder == null ) { - ladderDoesNotExistsMsg( sender, ladderName ); + ladderDoesNotExistsMsg( sender, ladderName ); return; } if (ladder.getName().equalsIgnoreCase( LadderManager.LADDER_DEFAULT )) { - ladderDeleteCannotDeleteDefaultMsg( sender ); - return; + ladderDeleteCannotDeleteDefaultMsg( sender ); + return; } if (ladder.getName().equalsIgnoreCase( LadderManager.LADDER_PRESTIGES )) { - ladderDeleteCannotDeletePrestigesMsg( sender ); - return; + ladderDeleteCannotDeletePrestigesMsg( sender ); + return; } if ( ladder.getRanks().size() > 0 ) { - ladderDeleteCannotDeleteWithRanksMsg( sender ); - return; + ladderDeleteCannotDeleteWithRanksMsg( sender ); + return; } if ( PrisonRanks.getInstance().getLadderManager().removeLadder(ladder) ) { - ladderDeletedMsg( sender, ladderName ); + ladderDeletedMsg( sender, ladderName ); } else { - ladderErrorMsg( sender ); + ladderErrorMsg( sender ); } } @@ -99,49 +99,8 @@ public void ladderRemove(CommandSender sender, @Arg(name = "ladderName") String onlyPlayers = false, permissions = "ranks.ladder") public void ladderList(CommandSender sender) { - ChatDisplay display = getLadderList(); + 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); } @@ -187,84 +146,32 @@ public ChatDisplay getLadderList() { display.addComponent(list.build()); - return display; + return display; } -// @Command(identifier = "ranks ladder listranks", description = "Lists the ranks within a ladder.", -// onlyPlayers = false, permissions = "ranks.ladder") -// public void ladderInfo( -// CommandSender sender, -// @Arg(name = "ladderName", def = "default", -// description = "The ladder name to display the ranks on. " + -// "Defaults to the default ladder") String ladderName -// -// ) { -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); -// -// if ( ladder == null ) { -// ladderDoesNotExistsMsg( sender, ladderName ); -// return; -// } -// -// ChatDisplay display = new ChatDisplay(ladder.getName()); -// display.addText( ladderHasRankMsg() ); -// -// BulletedListComponent.BulletedListBuilder builder = -// new BulletedListComponent.BulletedListBuilder(); -// -// boolean first = true; -// for (Rank rank : ladder.getRanks()) { -//// Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankPos.getRankId()); -// if ( rank == null ) { -// continue; -// } -// -//// Optional rankOptional = -//// PrisonRanks.getInstance().getRankManager().getRankOptional(rankPos.getRankId()); -//// if(!rankOptional.isPresent()) { -//// continue; // Skip it -//// } -// -// boolean defaultRank = ("default".equalsIgnoreCase( ladderName ) && first); -// -// String defaultRankValue = ladderDefaultRankMsg(); -// -// builder.add("&3(#%s) &8- &3%s (rankId: %s%s%s) %s", -// Integer.toString( rank.getPosition() ), -// rank.getName(), -// -// Integer.toString( rank.getId() ), -// (rank.getRankPrior() == null ? "" : " -"), -// (rank.getRankNext() == null ? "" : " +"), -// -// (defaultRank ? defaultRankValue : "") -// ); -// first = false; -// } -// -// String seeRanksList = ladderSeeRanksListMsg(); -// -// builder.add( seeRanksList ); -// -// display.addComponent(builder.build()); -// -// display.send(sender); -// } @Command(identifier = "ranks ladder moveRank", description = "Moves a rank to a new " + "ladder position or a new ladder.", onlyPlayers = false, permissions = "ranks.ladder") public void ladderMoveRank(CommandSender sender, - @Arg(name = "ladderName") String ladderName, + @Arg(name = "ladderName", + description = "Use a valid ladder name, or '*no-ladder*' " + + "to remove the ladder.") String ladderName, @Arg(name = "rankName") String rankName, @Arg(name = "position", def = "0", verifiers = "min[0]", description = "Position where you want the rank to be moved to. " + "0 is the first position in the ladder.") int position) { - ladderMoveRankNoticeMsg( sender ); - - ladderRemoveRank( sender, rankName ); - ladderAddRank(sender, ladderName, rankName, position ); + ladderMoveRankNoticeMsg( sender ); + + ladderRemoveRank( sender, rankName ); + + // If '*no-ladder*' then don't try to reassign it to another ladder: + if ( !ladderName.equalsIgnoreCase( "*no-ladder*" ) ) { + + ladderAddRank(sender, ladderName, rankName, position ); + } + } // @Command(identifier = "ranks ladder addrank", description = "Adds a rank to a ladder, or move a rank.", @@ -278,19 +185,19 @@ public void ladderAddRank(CommandSender sender, RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); if ( ladder == null ) { - ladderDoesNotExistsMsg( sender, ladderName ); + ladderDoesNotExistsMsg( sender, ladderName ); return; } Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); // Optional rank = PrisonRanks.getInstance().getRankManager().getRankOptional(rankName); if ( rank == null ) { - ladderRankDoesNotExistMsg( sender, rankName ); + ladderRankDoesNotExistMsg( sender, rankName ); return; } if (ladder.containsRank( rank )) { - ladderAlreadyHasRankMsg( sender, ladderName, rankName ); + ladderAlreadyHasRankMsg( sender, ladderName, rankName ); return; } @@ -302,7 +209,7 @@ public void ladderAddRank(CommandSender sender, if ( PrisonRanks.getInstance().getLadderManager().save(ladder) ) { - Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); + Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); // Recalculate the ladder's base rank cost multiplier: @@ -313,9 +220,9 @@ public void ladderAddRank(CommandSender sender, } else { - ladderErrorAddingMsg( sender ); - - ladderErrorSavingMsg( sender ); + ladderErrorAddingMsg( sender ); + + ladderErrorSavingMsg( sender ); } } @@ -326,24 +233,23 @@ public void ladderRemoveRank(CommandSender sender, // "But note, this is ignored and the real ladder used is the ladder tied to the rank.") String ladderName, // @Arg(name = "rankName") String rankName) { -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); - -// if ( ladder == null ) { -// ladderDoesNotExistsMsg( sender, ladderName ); -// return; -// } Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); -// Optional rank = PrisonRanks.getInstance().getRankManager().getRankOptional(rankName); if ( rank == null ) { - ladderRankDoesNotExistMsg( sender, rankName ); + ladderRankDoesNotExistMsg( sender, rankName ); return; } RankLadder ladder = rank.getLadder(); + if ( ladder == null ) { + Output.get().logInfo( + "The rank %s has no ladder, so ladder cannot be removed.", + rank.getName() ); + return; + } ladder.removeRank( rank ); -// ladder.removeRank(ladder.getPositionOfRank(rank)); + if ( PrisonRanks.getInstance().getLadderManager().save(ladder) ) { @@ -362,8 +268,8 @@ public void ladderRemoveRank(CommandSender sender, ladderRemovedRankFromLadderMsg( sender, rankName, ladder.getName() ); } else { - ladderErrorRemovingingMsg( sender ); - ladderErrorSavingMsg( sender ); + ladderErrorRemovingingMsg( sender ); + ladderErrorSavingMsg( sender ); } } @@ -438,11 +344,6 @@ public void ladderSetRankCostMultiplier( CommandSender sender, return; } -// if ( rankCostMultiplier < -100d || rankCostMultiplier > 100d ) { -// -// ladderSetRankCostMultiplierOutOfRangeMsg( sender, rankCostMultiplier ); -// return; -// } double oldRankCostMultiplier = ladder.getRankCostMultiplierPerRank() * 100; @@ -566,73 +467,56 @@ public void ladderResetRankCosts(CommandSender sender, RankLadder ladder = lm.getLadder(ladderName); if ( ladder == null ) { - ladderDoesNotExistsMsg( sender, ladderName ); + ladderDoesNotExistsMsg( sender, ladderName ); return; } if ( exponent <= 0 ) { - sender.sendMessage("Error: ranks ladder resetRankCosts: Exponent parameter must be greater than zero."); - return; + 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." ); - + 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++; - } + 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 ); + // 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/LadderCommandsPerms.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/LadderCommandsPerms.java index 5f578064a..3a7ef03f7 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/LadderCommandsPerms.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/LadderCommandsPerms.java @@ -7,309 +7,12 @@ public abstract class LadderCommandsPerms extends LadderCommandsMessages { - public LadderCommandsPerms( String cmdGroup ) { super( cmdGroup ); } + // About 5 commented out methods were removed. See hithub history for details. -// NOT USED: -// @Command(identifier = "ranks ladder perms list", description = "Lists ladder permissions", -// onlyPlayers = false, permissions = "ranks.set") -// public void ladderPermsList(CommandSender sender, -// @Arg(name = "ladderName", def = "default", -// description = "Ladder name to list the permissions.") String ladderName -// ){ -// sender.sendMessage( "&cWarning: &3This feature is not yet functional." ); -// -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); -// -// if ( ladder == null ) { -// ladderDoesNotExistsMsg( sender, ladderName ); -// return; -// } -// -// if ( ladder.getPermissions() == null ||ladder.getPermissions().size() == 0 && -// ladder.getPermissionGroups() == null && ladder.getPermissionGroups().size() == 0 ) { -// -// PrisonRanks.getInstance().getRanksMessages() -// .getLocalizable( "ranks_LadderCommands__ladder_has_no_perms" ) -// .withReplacements( -// ladder.getName() ) -// .sendTo( sender ); -// return; -// } -// -// -// -// ChatDisplay display = new ChatDisplay("Ladder Permissions and Groups for " + ladder.getName()); -// display.addText("&8Click the 'Remove' tag to remove it."); -// display.addText(" &3Placeholders: &7{rank}&3 - Rank Name"); -// display.addText(" &3All Ladder perms will be applied automatically to all ladder ranks."); -// -// BulletedListComponent.BulletedListBuilder builder = -// new BulletedListComponent.BulletedListBuilder(); -// -// -// int rowNumber = 1; -// -// if ( ladder.getPermissions().size() > 0 ) { -// builder.add( "&7Permissions:" ); -// } -// for (String perm : ladder.getPermissions() ) { -// -// RowComponent row = new RowComponent(); -// -// row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); -// -// FancyMessage msgPermission = new FancyMessage( String.format( "&7%s ", perm ) ) -// .command( "/ranks ladder perms edit " + ladder.getName() + " " + rowNumber + " " ) -// .tooltip("Permission - Click to Edit"); -// row.addFancy( msgPermission ); -// -// -// FancyMessage msgRemove = new FancyMessage( String.format( " &cRemove " ) ) -// .command( "/ranks ladder perms remove " + ladder.getName() + " " + rowNumber + " " ) -// .tooltip("Remove Permission - Click to Delete"); -// row.addFancy( msgRemove ); -// -// builder.add( row ); -// } -// -// if ( ladder.getPermissionGroups().size() > 0 ) { -// builder.add( "&7Permission Groups:" ); -// } -// for (String permGroup : ladder.getPermissionGroups() ) { -// -// RowComponent row = new RowComponent(); -// -// row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); -// -// FancyMessage msgPermission = new FancyMessage( String.format( "&7%s ", permGroup ) ) -// .command( "/ranks ladder perms edit " + ladder.getName() + " " + rowNumber + " " ) -// .tooltip("Permission Group - Click to Edit"); -// row.addFancy( msgPermission ); -// -// -// FancyMessage msgRemove = new FancyMessage( String.format( " &cRemove " ) ) -// .command( "/ranks ladder perms remove " + ladder.getName() + " " + rowNumber + " " ) -// .tooltip("Remove Permission Group - Click to Delete"); -// row.addFancy( msgRemove ); -// -// builder.add( row ); -// } -// -// -// display.addComponent(builder.build()); -// display.addComponent(new FancyMessageComponent( -// new FancyMessage("&7[&a+&7] Add Permission") -// .suggest("/ranks ladder perms addPerm " + ladder.getName() + " [perm] /") -// .tooltip("&7Add a new Permission."))); -// display.addComponent(new FancyMessageComponent( -// new FancyMessage("&7[&a+&7] Add Permission Group") -// .suggest("/ranks ladder perms addPermGroup " + ladder.getName() + " [permGroup] /") -// .tooltip("&7Add a new Permission Group."))); -// -// display.send(sender); -// -// } - - -//NOT USED: -// @Command(identifier = "ranks ladder perms addPerm", -// description = "Add a ladder permission. Valid placeholder: {rank}.", -// onlyPlayers = false, permissions = "ranks.set") -// public void ladderPermsAddPerm(CommandSender sender, -// @Arg(name = "ladderName", def = "default", -// description = "Ladder name to add the permission to.") String ladderName, -// @Arg(name = "permission", description = "Permission") String permission -// ){ -// sender.sendMessage( "&cWarning: &3This feature is not yet functional." ); -// -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); -// -// if ( ladder == null ) { -// Output.get().sendError(sender, "The ladder '%s' doesn't exist.", ladderName); -// return; -// } -// -// if ( permission == null || permission.trim().isEmpty() ) { -// -// Output.get().sendInfo(sender, "&3The &7permission &3parameter is required." ); -// return; -// } -// -// -// if ( ladder.hasPermission( permission ) ) { -// -// Output.get().sendInfo(sender, "&3The permission &7%s &3already exists.", permission ); -// return; -// } -// -// ladder.getPermissions().add( permission ); -// -// boolean saved = PrisonRanks.getInstance().getLadderManager().save( ladder ); -// -// if ( saved ) { -// -// Output.get().sendInfo(sender, "&3The permission &7%s &3was successfully added " + -// "to the ladder &7%s&3.", permission, ladder.getName() ); -// } -// else { -// -// Output.get().sendInfo(sender, "&cFailure: &3The permission &7%s &3was unable to " + -// "be saved to the ladder &7%s&3. See the console for additional informatio.", -// permission, ladder.getName() ); -// } -// -// ladderPermsList( sender, ladder.getName() ); -// } - -//NOT USED: -// @Command(identifier = "ranks ladder perms addGroup", -// description = "Add a ladder permission group. Valid placeholder: {rank}.", -// onlyPlayers = false, permissions = "ranks.set") -// public void ladderPermsAddGroup(CommandSender sender, -// @Arg(name = "ladderName", def = "default", -// description = "Ladder name to add the permission group to.") String ladderName, -// @Arg(name = "permissionGroup", description = "Permission Group") String permissionGroup -// ){ -// sender.sendMessage( "&cWarning: &3This feature is not yet functional." ); -// -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); -// -// if ( ladder == null ) { -// Output.get().sendError(sender, "The ladder '%s' doesn't exist.", ladderName); -// return; -// } -// -// if ( permissionGroup == null || permissionGroup.trim().isEmpty() ) { -// -// Output.get().sendInfo(sender, "&3The &7permissionGroup &3parameter is required." ); -// return; -// } -// -// -// if ( ladder.hasPermissionGroup( permissionGroup ) ) { -// -// Output.get().sendInfo(sender, "&3The permission group &7%s &3already exists.", -// permissionGroup ); -// return; -// } -// -// ladder.getPermissionGroups().add( permissionGroup ); -// -// boolean saved = PrisonRanks.getInstance().getLadderManager().save( ladder ); -// -// if ( saved ) { -// -// Output.get().sendInfo(sender, "&3The permission group &7%s &3was successfully added " + -// "to the ladder &7%s&3.", permissionGroup, ladder.getName() ); -// } -// else { -// -// Output.get().sendInfo(sender, "&cFailure: &3The permission group &7%s &3was unable to " + -// "be saved to the ladder &7%s&3. See the console for additional information.", -// permissionGroup, ladder.getName() ); -// } -// -// ladderPermsList( sender, ladder.getName() ); -// } - -// Since we are strictly dealing with a single value for perms, editing makes no sense; -// just delete the 'bad' perm and re-add it. -// @Command(identifier = "ranks ladder perms edit", description = "Lists ladder permissions", -// onlyPlayers = false, permissions = "ranks.set") -// public void ladderPermsEdit(CommandSender sender, -// @Arg(name = "ladderName", def = "default", -// description = "Ladder name to list the permissions.") String ladderName, -// @Arg(name = "row") Integer row -// ){ -// sender.sendMessage( "&cWarning: &3This feature is not yet functional." ); -// -// Optional ladderOptional = -// PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); -// if (!ladderOptional.isPresent()) { -// Output.get().sendError(sender, "The ladder '%s' doesn't exist.", ladderName); -// return; -// } -// -// RankLadder ladder = ladderOptional.get(); -// -// } - - -//NOT USED: -// @Command(identifier = "ranks ladder perms remove", description = "Lists ladder permissions", -// onlyPlayers = false, permissions = "ranks.set") -// public void ladderPermsRemove(CommandSender sender, -// @Arg(name = "ladderName", def = "default", -// description = "Ladder name to list the permissions.") String ladderName, -// @Arg(name = "row") Integer row -// ){ -// sender.sendMessage( "&cWarning: &3This feature is not yet functional." ); -// -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); -// -// if ( ladder == null ) { -// Output.get().sendError(sender, "The ladder '%s' doesn't exist.", ladderName); -// return; -// } -// -// boolean dirty = false; -// String removedPerm = ""; -// boolean permGroup = false; -// -// if ( row == null || row <= 0 ) { -// sender.sendMessage( -// String.format("&7Please provide a valid row number greater than zero. " + -// "Was row=[&b%d&7]", -// (row == null ? "null" : row) )); -// return; -// } -// -// if ( row <= ladder.getPermissions().size() ) { -// removedPerm = ladder.getPermissions().remove( row - 1 ); -// dirty = true; -// } -// else { -// // Remove from row the size of permissions so the row will align to the permissionGroups. -// row -= ladder.getPermissions().size(); -// -// if ( row <= ladder.getPermissionGroups().size() ) { -// -// removedPerm = ladder.getPermissions().remove( row - 1 ); -// dirty = true; -// permGroup = true; -// } -// } -// -// if ( dirty ) { -// boolean saved = PrisonRanks.getInstance().getLadderManager().save( ladder ); -// -// if ( saved ) { -// -// Output.get().sendInfo(sender, "&3The permission%s &7%s &3was successfully removed " + -// "to the ladder &7%s&3.", -// ( permGroup ? " group" : "" ), -// removedPerm, ladder.getName() ); -// } -// else { -// -// Output.get().sendInfo(sender, "&cFailure: &3The permission%s &7%s &3was unable to " + -// "be saved to the ladder &7%s&3. See the console for additional information.", -// ( permGroup ? " group" : "" ), -// removedPerm, ladder.getName() ); -// } -// } -// else { -// Output.get().sendInfo(sender, "&3The permission on row &7%s &3was unable to be removed " + -// "from the &7%s &3ladder. " + -// "Is that a valid row number?", -// Integer.toString( row ), ladder.getName() ); -// } -// } - } 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 2a53095dd..c12862f9a 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 @@ -76,60 +76,61 @@ public void rankUpMax(CommandSender sender, @Arg(name = "ladder", description = "The ladder to rank up on.", def = "default") String ladder ) { - String perms = "ranks.rankupmax."; - String permsLadder = perms + ladder; + String perms = "ranks.rankupmax."; + String permsLadder = perms + ladder; boolean isPrestigesEnabled = Prison.get().getPlatform().getConfigBooleanFalse( "prestiges" ) || Prison.get().getPlatform().getConfigBooleanFalse( "prestige.enabled" ); boolean isLadderPrestiges = ladder.equalsIgnoreCase(LadderManager.LADDER_PRESTIGES); -// boolean isLadderDefault = ladder.equalsIgnoreCase(LadderManager.LADDER_DEFAULT); - if ( (isPrestigesEnabled && isLadderPrestiges || - !isLadderPrestiges ) && - sender.hasPermission( permsLadder) - ) { - Output.get().logDebug( DebugTarget.rankup, - "Rankup: cmd '/rankupmax %s' Passed perm check: %s", - ladder, permsLadder ); - - boolean success = false; - - List cmdTasks = new ArrayList<>(); - StringBuilder sbRanks = new StringBuilder(); - - - RankupModes mode = RankupModes.MAX_RANKS; - - if ( !LadderManager.LADDER_PRESTIGES.equalsIgnoreCase( ladder ) && - !LadderManager.LADDER_DEFAULT.equalsIgnoreCase( ladder )) { - - success = rankUpPrivate(sender, "", ladder, mode, perms, cmdTasks, sbRanks ); - } - else { - - // Run rankupmax on the default ladder only: - success = rankUpPrivate(sender, "", LadderManager.LADDER_DEFAULT, mode, perms, cmdTasks, sbRanks ); - - // If they specified the prestiges ladder, then try to prestige that one rank: - if ( success && LadderManager.LADDER_PRESTIGES.equalsIgnoreCase( ladder ) ) { - - success = rankUpPrivate(sender, "", LadderManager.LADDER_PRESTIGES, RankupModes.ONE_RANK, perms, cmdTasks, sbRanks ); - } - } - + RankPlayer rPlayer = sender.getRankPlayer(); + + if ( (isPrestigesEnabled && isLadderPrestiges || + !isLadderPrestiges ) && + sender.hasPermission( permsLadder) + ) { + Output.get().logDebug( DebugTarget.rankup, + "Rankup: cmd '/rankupmax %s' Passed perm check: %s", + ladder, permsLadder ); + + boolean success = false; + + List cmdTasks = new ArrayList<>(); + StringBuilder sbRanks = new StringBuilder(); + + + RankupModes mode = RankupModes.MAX_RANKS; + + if ( !LadderManager.LADDER_PRESTIGES.equalsIgnoreCase( ladder ) && + !LadderManager.LADDER_DEFAULT.equalsIgnoreCase( ladder )) { + + success = rankUpPrivate(sender, rPlayer, ladder, mode, perms, cmdTasks, sbRanks ); + } + else { + + // Run rankupmax on the default ladder only: + success = rankUpPrivate(sender, rPlayer, LadderManager.LADDER_DEFAULT, mode, perms, cmdTasks, sbRanks ); + + // If they specified the prestiges ladder, then try to prestige that one rank: + if ( success && LadderManager.LADDER_PRESTIGES.equalsIgnoreCase( ladder ) ) { + + success = rankUpPrivate(sender, rPlayer, LadderManager.LADDER_PRESTIGES, RankupModes.ONE_RANK, perms, cmdTasks, sbRanks ); + } + } + - Player player = getPlayer( sender, null ); // submit cmdTasks if ( cmdTasks.size() > 0 ) { - submitCmdTasks( player, cmdTasks ); + submitCmdTasks( rPlayer, cmdTasks ); } if ( sbRanks.length() > 0 ) { - ranksRankupMaxSuccessMsg( sender, sbRanks, player.getRankPlayer() ); + ranksRankupMaxSuccessMsg( sender, sbRanks, rPlayer ); +// ranksRankupMaxSuccessMsg( sender, sbRanks, player.getRankPlayer() ); } // If the ran rankupmax for prestiges, and the last prestige was successful, then @@ -138,13 +139,12 @@ public void rankUpMax(CommandSender sender, rankUpMax( sender, ladder ); } } - else { - Player player = getPlayer( sender, null ); - Output.get().logDebug( DebugTarget.rankup, - "Rankup: Failed: cmd '/rankupmax %s' Does not have the permission ranks.rankupmax.%s", - ladder, ladder ); - rankupMaxNoPermissionMsg( sender, "ranks.rankupmax." + ladder, player.getRankPlayer() ); - } + else { + Output.get().logDebug( DebugTarget.rankup, + "Rankup: Failed: cmd '/rankupmax %s' Does not have the permission ranks.rankupmax.%s", + ladder, ladder ); + rankupMaxNoPermissionMsg( sender, "ranks.rankupmax." + ladder, rPlayer ); + } } @@ -156,8 +156,9 @@ public void rankUpMax(CommandSender sender, "command with other ladders, the users must have the correct perms as listed with this " + "command's help information. " , - permissions = "ranks.user", - altPermissions = {"ranks.rankup.default", "ranks.rankup.prestiges", "ranks.rankup.[ladderName]"}, +// permissions = "ranks.user", + altPermissions = {"ranks.user", "ranks.rankup.default", "ranks.rankup.prestiges", + "ranks.rankup.[ladderName]"}, onlyPlayers = false) public void rankUp(CommandSender sender, @Arg(name = "ladder", description = "The ladder to rank up on. Defaults to 'default'.", def = "default") String ladder, @@ -176,96 +177,102 @@ public void rankUp(CommandSender sender, boolean isPlayer = sender.isPlayer(); - if ( isPlayer ) { + if ( isPlayer && sender.isOp() && playerName != null && playerName.trim().length() > 0 ) { + // use playerName as is since the OP'd player is using this command on someone else: + } + else if ( isPlayer ) { playerName = ""; } - if ( !isPlayer && playerName.length() == 0 ) { - Output.get().logInfo( rankupCannotRunFromConsoleMsg() ); - return; + + // NOTE: If this is being ran from the console, the a 'playerName' parameter must be supplied: + else if ( !isPlayer && playerName.length() == 0 ) { + Output.get().logInfo( rankupCannotRunFromConsoleMsg() ); + return; } - -// RankPlayer rPlayer = getRankPlayer(sender, null, playerName); -// boolean isConfirmed = ( confirm != null && confirm.toLowerCase().contains("confirm") ); -// if ( !isConfirmed && playerName != null && playerName.toLowerCase().equals( "confirm" ) ) { -// isConfirmed = true; -// playerName = ""; -// } -// else if ( !isConfirmed && ladder != null && ladder.toLowerCase().equals( "confirm" ) ) { -// isConfirmed = true; -// ladder = ""; -// } + + RankPlayer rPlayer = isPlayer ? + sender.getRankPlayer() : + getRankPlayer(sender, null, playerName); + + if ( rPlayer == null ) { + rankupInvalidPlayerNameMsg( sender, playerName ); + return; + } + + + boolean isLadderDefault = ladder.equalsIgnoreCase(LadderManager.LADDER_DEFAULT); + boolean isLadderPrestiges = ladder.equalsIgnoreCase(LadderManager.LADDER_PRESTIGES); - -// boolean isConfirmationEnabled = Prison.get().getPlatform().getConfigBooleanFalse( "ranks.confirmation-enabled" ); -// if ( isConfirmationEnabled && !isConfirmed ) { -// if ( isConfirmGUI && isPlayer ) { -// -// // call the gui prestige confirmation: -//// callGuiPrestigeConfirmation( sender, ); -// String guiConfirmParms = -// prestigeConfirmationGUIMsg( sender, rPlayer, nextRank, isResetDefaultLadder, isResetMoney ); -// -// String guiConfirmCmd = "gui prestigeConfirm " + guiConfirmParms; -//// Output.get().logInfo( guiConfirmCmd ); -// -// submitCmdTask( rPlayer, guiConfirmCmd ); -// -// } -// else { -// -// prestigeConfirmationMsg( sender, rPlayer, nextRank, isResetDefaultLadder, isResetMoney, isPlayer ); -// } -// return; -// } + boolean isPrestigesEnabled = Prison.get().getPlatform().getConfigBooleanFalse( "prestiges" ) || + Prison.get().getPlatform().getConfigBooleanFalse( "prestige.enabled" ); + + + boolean isDefaultBypassPermCheck = isLadderDefault && + Prison.get().getPlatform().getConfigBooleanTrue( + "ranks.rankup-bypass-perm-check" ); + + boolean hasDefaultPerm = sender.hasPermission( "ranks.user" ) || + sender.hasPermission( "ranks.rankup.default"); + + boolean isPrestigeBypassPermCheck = isLadderPrestiges && + isPrestigesEnabled && + Prison.get().getPlatform().getConfigBooleanTrue( + "prestige.prestige-bypass-perm-check" ); + String perms = "ranks.rankup."; String permsLadder = perms + ladder; + + boolean hasLadderPerm = sender.hasPermission(permsLadder); - boolean isPrestigesEnabled = Prison.get().getPlatform().getConfigBooleanFalse( "prestiges" ) || - Prison.get().getPlatform().getConfigBooleanFalse( "prestige.enabled" ); - - boolean isLadderPrestiges = ladder.equalsIgnoreCase(LadderManager.LADDER_PRESTIGES); - boolean isLadderDefault = ladder.equalsIgnoreCase(LadderManager.LADDER_DEFAULT); - - if ( isLadderDefault || - - (isPrestigesEnabled && isLadderPrestiges || - !isLadderPrestiges ) && - sender.hasPermission( permsLadder) - ) { - Output.get().logDebug( DebugTarget.rankup, - "Rankup: cmd '/rankup %s%s' Passed perm check: %s", - ladder, - ( playerName.length() == 0 ? "" : " " + playerName ), - permsLadder ); + String permsCheck = String.format( + "isDefaultBypassPermCheck: %s, isPrestigeBypassPermCheck: %s, 'ranks.user': %s, '%s': %s ", + Boolean.toString(isDefaultBypassPermCheck), + Boolean.toString(isPrestigeBypassPermCheck), + Boolean.toString( sender.hasPermission( "ranks.user" ) ), + + permsLadder, + Boolean.toString(hasLadderPerm) + ); - -// Output.get().logDebug( DebugTarget.rankup, -// "Rankup: cmd '/rankup %s%s' Processing %s", -// ladder, -// ( playerName.length() == 0 ? "" : " " + playerName ), -// permsLadder -// ); - - List cmdTasks = new ArrayList<>(); - - rankUpPrivate(sender, playerName, ladder, RankupModes.ONE_RANK, perms, cmdTasks, null ); - - // submit cmdTasks - Player player = getPlayer( sender, playerName ); - submitCmdTasks( player, cmdTasks ); + + if ( isDefaultBypassPermCheck || + isPrestigeBypassPermCheck || + + isLadderDefault && hasDefaultPerm || + + isPrestigesEnabled && isLadderPrestiges && + hasLadderPerm || + + + !isLadderDefault && !isLadderPrestiges && + hasLadderPerm + + ) { + + Output.get().logDebug( DebugTarget.rankup, + "Rankup: cmd '/rankup %s%s' Passed perm check: %s [%s]]", + ladder, + ( playerName.length() == 0 ? "" : " " + playerName ), + permsLadder, + permsCheck ); + + List cmdTasks = new ArrayList<>(); + + rankUpPrivate(sender, rPlayer, ladder, RankupModes.ONE_RANK, perms, cmdTasks, null ); + + submitCmdTasks( rPlayer, cmdTasks ); } - else { - Player player = getPlayer( sender, playerName ); - Output.get().logDebug( DebugTarget.rankup, - "Rankup: Failed: cmd '/rankup %s' Does not have the permission %s", - ladder, permsLadder ); - rankupMaxNoPermissionMsg( sender, permsLadder, player.getRankPlayer() ); - } + else { + Output.get().logDebug( DebugTarget.rankup, + "Rankup: Failed: cmd '/rankup %s' Does not have the permission %s. [%s]", + ladder, permsLadder, permsCheck ); + rankupMaxNoPermissionMsg( sender, permsLadder, rPlayer ); + } } @@ -279,8 +286,8 @@ public void rankUp(CommandSender sender, + "if the config.yml setting 'prestige.enable__ranks_rankup_prestiges__permission` is set to a " + "value of 'true' (defaults to 'false'). " + "Examples: '/prestige', '/presetige confirm', '/prestige confirm'.", - permissions = "ranks.user", - altPermissions = {"ranks.rankup.prestiges"}, +// permissions = "ranks.user", + altPermissions = {"ranks.user", "ranks.rankup.prestiges"}, onlyPlayers = false) public void prestigeCmd(CommandSender sender, @Arg(name = "playerName", def = "", @@ -288,7 +295,7 @@ public void prestigeCmd(CommandSender sender, "this can only be provided by a non-player such as console or ran from a script. " + "Players cannot run Prestige for other players.") String playerName, - @Arg(name = "confirm", def = "", + @Arg(name = "confirm", def = "", description = "If confirmations are enabled, then the prestige command " + "must be repeated with the addition of 'confirm'. If the prestige command is ran by a " + "non-player, such as console or from script, then the confirmation will be skipped, or " @@ -312,34 +319,46 @@ public void prestigeCmd(CommandSender sender, if ( !isPlayer && playerName.length() == 0 ) { - Output.get().logInfo( rankupCannotRunFromConsoleMsg() ); - return; + Output.get().logInfo( rankupCannotRunFromConsoleMsg() ); + return; } - RankPlayer rPlayer = getRankPlayer(sender, null, playerName); + RankPlayer rPlayer = isPlayer ? + sender.getRankPlayer() : + getRankPlayer(sender, null, playerName); if ( rPlayer == null ) { - rankupInvalidPlayerNameMsg( sender, playerName ); - return; + rankupInvalidPlayerNameMsg( sender, playerName ); + return; } + + boolean isPrestigesEnabled = Prison.get().getPlatform().getConfigBooleanFalse( "prestiges" ) || + Prison.get().getPlatform().getConfigBooleanFalse( "prestige.enabled" ); + boolean hasPrestigePerm = sender.hasPermission( "ranks.user" ) || + sender.hasPermission( "ranks.rankup.prestiges"); - String perms = "ranks.rankup."; - String permsLadder = perms + LadderManager.LADDER_PRESTIGES; - boolean hasPermsLadder = sender.hasPermission(permsLadder); - boolean usePerms = Prison.get().getPlatform().getConfigBooleanFalse( "enable__ranks_rankup_prestiges__permission" ); - boolean hasAcessToPrestige = usePerms && hasPermsLadder || !usePerms; + boolean isPrestigeBypassPermCheck = + isPrestigesEnabled && + Prison.get().getPlatform().getConfigBooleanTrue( + "prestige.prestige-bypass-perm-check" ); + + String permsCheck = String.format( + "isPrestigesEnabled: %s, isPrestigeBypassPermCheck: %s, 'ranks.user': %s, 'ranks.rankup.prestiges': %s ", + Boolean.toString(isPrestigesEnabled), + Boolean.toString(isPrestigeBypassPermCheck), + Boolean.toString( sender.hasPermission( "ranks.user" ) ), + + Boolean.toString( sender.hasPermission( "ranks.rankup.prestiges") ) + ); - boolean isPrestigesEnabled = Prison.get().getPlatform().getConfigBooleanFalse( "prestiges" ) || - Prison.get().getPlatform().getConfigBooleanFalse( "prestige.enabled" ); + + String perms = "ranks.rankup."; boolean isResetDefaultLadder = Prison.get().getPlatform().getConfigBooleanFalse( "prestige.resetDefaultLadder" ); boolean isResetMoney = Prison.get().getPlatform().getConfigBooleanFalse( "prestige.resetMoney" ); boolean isConfirmationEnabled = Prison.get().getPlatform().getConfigBooleanFalse( "prestige.confirmation-enabled" ); boolean isConfirmGUI = Prison.get().getPlatform().getConfigBooleanFalse( "prestige.prestige-confirm-gui" ); - //boolean isforceSellall = Prison.get().getPlatform().getConfigBooleanFalse( "prestige.force-sellall" ); - -// boolean isLadderPrestiges = ladder.equalsIgnoreCase(LadderManager.LADDER_PRESTIGES); PlayerRank nextRank = rPlayer.getNextPlayerRank(); Rank nRank = nextRank == null ? null : nextRank.getRank(); @@ -374,7 +393,6 @@ public void prestigeCmd(CommandSender sender, if ( isConfirmGUI && isPlayer ) { // call the gui prestige confirmation: -// callGuiPrestigeConfirmation( sender, ); String guiConfirmParms = prestigeConfirmationGUIMsg( sender, rPlayer, nextRank, isResetDefaultLadder, isResetMoney ); @@ -391,98 +409,54 @@ public void prestigeCmd(CommandSender sender, return; } - if ( isPrestigesEnabled && hasAcessToPrestige ) { + if ( isPrestigeBypassPermCheck || + isPrestigesEnabled && hasPrestigePerm ) { - Output.get().logDebug( DebugTarget.rankup, - "Rankup: cmd '/prestige %s%s' Has Access to '/prestiges': %b " - + "Has perms: %b Perms: %s", - (playerName.length() == 0 ? "" : " " + playerName ), - (confirm == null ? "" : " " + confirm ), - - hasAcessToPrestige, - hasPermsLadder, - permsLadder ); - - - List cmdTasks = new ArrayList<>(); - - String ladder = nRank.getLadder().getName(); - rankUpPrivate(sender, playerName, ladder, RankupModes.ONE_RANK, perms, cmdTasks, null ); - - // submit cmdTasks - Player player = getPlayer( sender, playerName ); - submitCmdTasks( player, cmdTasks ); + Output.get().logDebug( DebugTarget.rankup, + "Rankup: cmd '/prestige %s%s' [%s]", + (playerName.length() == 0 ? "" : " " + playerName ), + (confirm == null ? "" : " " + confirm ), + permsCheck ); + + + List cmdTasks = new ArrayList<>(); + + String ladder = nRank.getLadder().getName(); + rankUpPrivate(sender, rPlayer, ladder, RankupModes.ONE_RANK, perms, cmdTasks, null ); + + // submit cmdTasks + submitCmdTasks( rPlayer, cmdTasks ); } + else { + Output.get().logDebug( DebugTarget.rankup, + "Rankup: Failed: cmd '/prestige %s%s' Does not have the permission %s. [%s]", + (playerName.length() == 0 ? "" : " " + playerName ), + (confirm == null ? "" : " " + confirm ), + permsCheck ); + + } } - - - private boolean rankUpPrivate(CommandSender sender, String playerName, String ladder, RankupModes mode, + + + + private boolean rankUpPrivate(CommandSender sender, + RankPlayer rankPlayer, +// String playerName, + String ladder, RankupModes mode, String permission, List cmdTasks, StringBuilder sbRanks ) { boolean rankupSuccess = false; - // RETRIEVE THE LADDER -// // Perms have already been checked on the RankupModes.MAX_RANKS: -// if ( mode != RankupModes.MAX_RANKS ) { -// -// boolean isPrestigesEnabled = Prison.get().getPlatform().getConfigBooleanFalse( "prestiges" ) || -// Prison.get().getPlatform().getConfigBooleanFalse( "prestige.enabled" ); -// -// boolean isLadderPrestiges = ladder.equalsIgnoreCase(LadderManager.LADDER_PRESTIGES); -// boolean isLadderDefault = ladder.equalsIgnoreCase(LadderManager.LADDER_DEFAULT); -// -// String permCheck = permission + ladder.toLowerCase(); -// -// // This player has to have permission to rank up on this ladder, but -// // ignore if either the default or prestiges ladder. This only is to check for -// // other ladders. -// if (!( isLadderPrestiges && isPrestigesEnabled ) && -// !isLadderDefault && -// !sender.hasPermission( permCheck )) { -// -// Output.get().logDebug( DebugTarget.rankup, -// "Rankup: rankUpPrivate: failed rankup perm check. Missing perm: %s", -// permCheck ); -// -// rankupMaxNoPermissionMsg( sender, permCheck ); -// return false; -// } -// -// } - - - // if ( mode == null ) { - Output.get().logInfo( rankupInternalFailureMsg() ); - return false; - } - - - if ( sender.isPlayer() ) { - playerName = ""; - } - - if ( !sender.isPlayer() && playerName.length() == 0 ) { - Output.get().logInfo( rankupCannotRunFromConsoleMsg() ); - return false; - } - - - // Player will always be the player since they have to be online and must be a player: - Player player = getPlayer( sender, playerName ); - - if ( player == null ) { - rankupInvalidPlayerNameMsg( sender, playerName ); - return false; + Output.get().logInfo( rankupInternalFailureMsg() ); + return false; } - - //UUID playerUuid = player.getUUID(); - RankPlayer rankPlayer = getRankPlayer( sender, player.getUUID(), player.getName() ); + // RETRIEVE THE LADDER ladder = confirmLadder( sender, ladder, rankPlayer ); if ( ladder == null ) { @@ -494,82 +468,72 @@ private boolean rankUpPrivate(CommandSender sender, String playerName, String la RankLadder targetLadder = lm.getLadder( ladder ); if ( targetLadder == null ){ - rankupErrorNoLadderMsg( sender, ladder ); - return false; - } - - if (!targetLadder.getLowestRank().isPresent()){ - rankupErrorNoRankOnLadderMsg( sender, ladder ); - return false; - } + rankupErrorNoLadderMsg( sender, ladder ); + return false; + } + + if (!targetLadder.getLowestRank().isPresent()){ + rankupErrorNoRankOnLadderMsg( sender, ladder ); + return false; + } - - - 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, rankPlayer ); - return false; + rankupAtLastRankMsg(sender, rankPlayer ); + 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 // prestiges rank. - PlayerRank playerRankTarget = rankPlayer.getNextPlayerRank(); - + PlayerRank playerRankTarget = null; - // If the nextRank is null or the ladder does not match selected ladder, then exit: - if ( playerRankTarget == null || playerRankTarget.getRank() == null || - !playerRankTarget.getRank().getLadder().getName().equalsIgnoreCase( ladder ) ) { + if ( targetLadder.isDefault() || targetLadder.isPrestiges() ) { - return false; + playerRankTarget = rankPlayer.getNextPlayerRank(); + + // If the nextRank is null or the ladder does not match selected ladder, then exit: + if ( playerRankTarget == null || playerRankTarget.getRank() == null ) { + + if ( Output.get().isDebug() ) { + Output.get().logInfo( + "RankUp ladder= %s currentRank= %s " + + "No next default or prestige rank. At end of both ladders?", + ladder, rankCurrent.getRank().getName() ); + } + + return false; + } } RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - - // If the target ladder is either default or prestiges, then use the getNextPlayerRank() value - // that is provided. Only use the following code if not these two ladders. - if ( !ladder.equalsIgnoreCase( LadderManager.LADDER_DEFAULT ) && - !ladder.equalsIgnoreCase( LadderManager.LADDER_PRESTIGES ) ) { - - - PlayerRank playerRankCurrent = rankPlayerFactory.getRank( rankPlayer, ladder ); -// PlayerRank playerRankCurrent = rankPlayer.getPlayerRankDefault(); - + // If ranking up on neither default or prestige ladders: + if ( !targetLadder.isDefault() && !targetLadder.isPrestiges() ) { - // If the player does not have a rank on the current ladder, then assign the - // default rank for the ladder to be their next rank. - if ( playerRankCurrent == null ) { - - playerRankTarget = rankPlayer.calculateTargetPlayerRank( - targetLadder.getLowestRank().get() ); - -// playerRankTarget = rankPlayerFactory.createPlayerRank( -// targetLadder.getLowestRank().get() ); - } - else { - - playerRankTarget = rankPlayer.calculateTargetPlayerRank( playerRankCurrent.getRank() ); -// playerRankTarget = playerRankCurrent.getTargetPlayerRankForPlayer( rankPlayer, -// playerRankCurrent.getRank() ); - } + PlayerRank playerRankCurrent = rankPlayerFactory.getRank( rankPlayer, ladder ); + + // If the player does not have a rank on the current ladder, then assign the + // default rank for the ladder to be their next rank. + if ( playerRankCurrent == null ) { + + playerRankTarget = rankPlayer.calculateTargetPlayerRank( + targetLadder.getLowestRank().get() ); + } + else { + + playerRankTarget = rankPlayer.calculateTargetPlayerRank( playerRankCurrent.getRank() ); + } } - - - - Output.get().logDebug( DebugTarget.rankup, @@ -631,45 +595,33 @@ private boolean rankUpPrivate(CommandSender sender, String playerName, String la if (rankPlayer != null ) { - // Performs the actual rankup here: - RankupResults results = new RankUtil().rankupPlayer(player, rankPlayer, ladder, - sender.getName(), cmdTasks ); - - - processResults( sender, player.getName(), results, null, ladder, currency, sbRanks ); - - // If the last rankup attempt was successful and they are trying to rankup as many times as possible: - // Note they used to restrict rankupmax from working on prestige ladder... - if (results.getStatus() == RankupStatus.RANKUP_SUCCESS && mode == RankupModes.MAX_RANKS ) { -// if (results.getStatus() == RankupStatus.RANKUP_SUCCESS && mode == RankupModes.MAX_RANKS && -// !ladder.equals(LadderManager.LADDER_PRESTIGES)) { - rankUpPrivate( sender, playerName, ladder, mode, permission, cmdTasks, sbRanks ); - } - if (results.getStatus() == RankupStatus.RANKUP_SUCCESS){ - rankupSuccess = true; - } - - - // Get the player rank after -// PlayerRank playerRankAfter = rankPlayer.getNextPlayerRank(); -// PlayerRank playerRankAfter = rankPlayerFactory.getRank( rankPlayer, ladder ); - -// if ( playerRankAfter != null ) { -// -// pRankAfter = playerRankAfter.getRank(); -// } - - // Prestige method if canPrestige and a successful rankup. - // pRankTarget now contains the target rank prior to processing the rankup. SO it should be - // the same as pRankAfter, but if it is wrong, then rankupWithSuccess will not be true. So ignore... - if ( canPrestige && rankupSuccess ) { - prestigePlayer( sender, rankPlayer, lm, cmdTasks, sbRanks ); -// prestigePlayer( sender, player, rankPlayer, pRankAfter, lm ); - - } - else if ( canPrestige ) { - rankupNotAbleToPrestigeMsg( sender, rankPlayer ); - } + // Performs the actual rankup here: + RankupResults results = new RankUtil().rankupPlayer(rankPlayer, rankPlayer, ladder, + sender.getName(), cmdTasks ); + + + processResults( sender, rankPlayer.getName(), results, null, ladder, currency, sbRanks, mode ); + + // If the last rankup attempt was successful and they are trying to rankup as many times as possible: + // Note they used to restrict rankupmax from working on prestige ladder... + if (results.getStatus() == RankupStatus.RANKUP_SUCCESS && mode == RankupModes.MAX_RANKS ) { + rankUpPrivate( sender, rankPlayer, ladder, mode, permission, cmdTasks, sbRanks ); + } + if (results.getStatus() == RankupStatus.RANKUP_SUCCESS){ + rankupSuccess = true; + } + + + // Prestige method if canPrestige and a successful rankup. + // pRankTarget now contains the target rank prior to processing the rankup. SO it should be + // the same as pRankAfter, but if it is wrong, then rankupWithSuccess will not be true. So ignore... + if ( canPrestige && rankupSuccess ) { + prestigePlayer( sender, rankPlayer, lm, cmdTasks, sbRanks ); + + } + else if ( canPrestige ) { + rankupNotAbleToPrestigeMsg( sender, rankPlayer ); + } } @@ -713,48 +665,28 @@ private void prestigePlayer(CommandSender sender, RankPlayer rankPlayer, if ( resetDefaultLadder ) { - // Get the player rank after, just to check if it has success Conditions -// if (willPrestige && rankupWithSuccess && pRankAfter != null && pRank != pRankAfter) { - // Set the player rank to the first one of the default ladder - - RankLadder ladder = lm.getLadder(LadderManager.LADDER_DEFAULT); Rank dRank = ladder.getLowestRank().get(); setPlayerRank( rankPlayer, ladder, dRank, sender, cmdTasks, sbRanks ); - -// String ladderName = LadderManager.LADDER_DEFAULT; -// String defaultRank = lm.getLadder(LadderManager.LADDER_DEFAULT).getLowestRank().get().getName(); -// -// setPlayerRank( rankPlayer, defaultRank, ladderName, sender ); + PlayerRank playerRankSecond = rankPlayer.getPlayerRankDefault(); - // Call the function directly and skip using dispatch commands: -// setRank( sender, player.getName(), -// lm.getLadder(LadderManager.LADDER_DEFAULT).getLowestRank().get().getName(), -// LadderManager.LADDER_DEFAULT ); - + if ( playerRankSecond != null ) { - PlayerRank playerRankSecond = rankPlayer.getPlayerRankDefault(); + Rank pRankSecond = playerRankSecond.getRank(); + // Check if the ranks match - - - if ( playerRankSecond != null ) { - - Rank pRankSecond = playerRankSecond.getRank(); - // Check if the ranks match - - if ( !pRankSecond.equals( lm.getLadder(LadderManager.LADDER_DEFAULT).getLowestRank().get()) ) { - - rankupNotAbleToResetRankMsg( sender, rankPlayer ); - success = false; - } - } - else { + if ( !pRankSecond.equals( lm.getLadder(LadderManager.LADDER_DEFAULT).getLowestRank().get()) ) { rankupNotAbleToResetRankMsg( sender, rankPlayer ); success = false; } -// } + } + else { + + rankupNotAbleToResetRankMsg( sender, rankPlayer ); + success = false; + } } if ( success && resetBalance ) { @@ -774,19 +706,29 @@ private void prestigePlayer(CommandSender sender, RankPlayer rankPlayer, String title = newPRank == null || newPRank.getTag() == null ? newPRank.getName() : newPRank.getTag(); - if ( success ) { - // Send a message to the player because he did prestige! + if ( success ) { prestigePlayerSucessfulMsg( sender, title, rankPlayer ); } else { - prestigePlayerFailureMsg( sender, title, rankPlayer ); } } + + /** + *

    This command requires that a target player be specified and that this can only be + * ran by an admin. The act of promoting a player cannot ever fall back on the person + * issuing the command. + *

    + * + * @param sender + * @param playerName + * @param ladder + * @param chargePlayer + */ @Command(identifier = "ranks promote", description = "Promotes a player to the next rank. This is an admin command. " + "This command can be used from the console. There is an " + @@ -801,34 +743,32 @@ public void promotePlayer(CommandSender sender, def = "no_charge") String chargePlayer ) { - Player player = getPlayer( sender, playerName ); - UUID playerUuid = player.getUUID(); - - if (player == null) { - ranksPromotePlayerMustBeOnlineMsg( sender ); - return; - } - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - RankPlayer rankPlayer = getRankPlayer( sender, playerUuid, player.getName() ); - - PromoteForceCharge pForceCharge = PromoteForceCharge.fromString( chargePlayer ); - if ( pForceCharge == null|| pForceCharge == PromoteForceCharge.refund_player ) { - - ranksPromotePlayerInvalidChargeValueMsg( sender, rankPlayer ); - return; - } + RankPlayer rPlayer = getRankPlayer(sender, null, playerName); + + if ( rPlayer == null ) { + rankupInvalidPlayerNameMsg( sender, playerName ); + return; + } + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + PromoteForceCharge pForceCharge = PromoteForceCharge.fromString( chargePlayer ); + if ( pForceCharge == null|| pForceCharge == PromoteForceCharge.refund_player ) { + + ranksPromotePlayerInvalidChargeValueMsg( sender, rPlayer ); + return; + } - ladder = confirmLadder( sender, ladder, rankPlayer ); + ladder = confirmLadder( sender, ladder, rPlayer ); if ( ladder == null ) { return; } - PlayerRank playerRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + PlayerRank playerRank = rankPlayerFactory.getRank( rPlayer, ladder ); - if ( rankPlayer != null && playerRank != null ) { + if ( rPlayer != null && playerRank != null ) { Rank pRank = playerRank.getRank(); if ( pRank == null ) { @@ -843,19 +783,19 @@ public void promotePlayer(CommandSender sender, List cmdTasks = new ArrayList<>(); - RankupResults results = new RankUtil().promotePlayer(player, rankPlayer, ladder, - player.getName(), sender.getName(), pForceCharge, cmdTasks ); + RankupResults results = new RankUtil().promotePlayer( rPlayer, rPlayer, ladder, + rPlayer.getName(), sender.getName(), pForceCharge, cmdTasks ); // submit cmdTasks... - submitCmdTasks( player, cmdTasks ); + submitCmdTasks( rPlayer, cmdTasks ); - processResults( sender, player.getName(), results, null, ladder, currency, null ); + processResults( sender, rPlayer.getName(), results, null, ladder, currency, null, RankupModes.ONE_RANK ); } else { - // Message: Player is not on the ladder - sender.sendMessage( "Promote: Player is not on the specified ladder. " - + "Try using '/ranks set rank' to add them."); + // Message: Player is not on the ladder + sender.sendMessage( "Promote: Player is not on the specified ladder. " + + "Try using '/ranks set rank' to add them."); } } @@ -876,23 +816,22 @@ public void demotePlayer(CommandSender sender, def = "no_charge") String refundPlayer ) { - Player player = getPlayer( sender, playerName ); - - if (player == null) { - ranksPromotePlayerMustBeOnlineMsg( sender ); - return; - } - - UUID playerUuid = player.getUUID(); - RankPlayer rankPlayer = getRankPlayer( sender, playerUuid, player.getName() ); - - PromoteForceCharge pForceCharge = PromoteForceCharge.fromString( refundPlayer ); - if ( pForceCharge == null || pForceCharge == PromoteForceCharge.charge_player ) { - ranksDemotePlayerInvalidRefundValueMsg( sender, rankPlayer ); - return; - } + + RankPlayer rPlayer = getRankPlayer(sender, null, playerName); + + if ( rPlayer == null ) { + rankupInvalidPlayerNameMsg( sender, playerName ); + return; + } + + + PromoteForceCharge pForceCharge = PromoteForceCharge.fromString( refundPlayer ); + if ( pForceCharge == null || pForceCharge == PromoteForceCharge.charge_player ) { + ranksDemotePlayerInvalidRefundValueMsg( sender, rPlayer ); + return; + } - ladder = confirmLadder( sender, ladder, rankPlayer ); + ladder = confirmLadder( sender, ladder, rPlayer ); if ( ladder == null ) { // Already displayed error message about ladder not existing: return; @@ -900,36 +839,36 @@ public void demotePlayer(CommandSender sender, RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - PlayerRank playerRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + PlayerRank playerRank = rankPlayerFactory.getRank( rPlayer, ladder ); - if ( rankPlayer != null && playerRank != null ) { - - Rank pRank = playerRank.getRank(); - if ( pRank == null ) { - sender.sendMessage( "Demote: There was an error trying to access the " - + "current rank of the player. Try viewing the player's " - + "details: '/ranks player help'."); - return; - } - - // Get currency if it exists, otherwise it will be null if the Rank has no currency: - String currency = pRank.getCurrency(); - - List cmdTasks = new ArrayList<>(); - - RankupResults results = new RankUtil().demotePlayer(player, rankPlayer, ladder, - player.getName(), sender.getName(), pForceCharge, cmdTasks ); - - // submit cmdTasks - submitCmdTasks( player, cmdTasks ); - - processResults( sender, player.getName(), results, null, ladder, currency, null ); + if ( rPlayer != null && playerRank != null ) { + Rank pRank = playerRank.getRank(); + if ( pRank == null ) { + sender.sendMessage( "Demote: There was an error trying to access the " + + "current rank of the player. Try viewing the player's " + + "details: '/ranks player help'."); + return; + } + + // Get currency if it exists, otherwise it will be null if the Rank has no currency: + String currency = pRank.getCurrency(); + + List cmdTasks = new ArrayList<>(); + + RankupResults results = new RankUtil().demotePlayer( rPlayer, rPlayer, ladder, + rPlayer.getName(), sender.getName(), pForceCharge, cmdTasks ); + + // submit cmdTasks + submitCmdTasks( rPlayer, cmdTasks ); + + processResults( sender, rPlayer.getName(), results, null, ladder, currency, null, RankupModes.ONE_RANK ); + } else { - // Message: Player is not on the ladder - sender.sendMessage( "Demote: Player is not on the specified ladder. " - + "Try using '/ranks set rank' to add them."); + // Message: Player is not on the ladder + sender.sendMessage( "Demote: Player is not on the specified ladder. " + + "Try using '/ranks set rank' to add them."); } } @@ -948,41 +887,37 @@ public void setRank(CommandSender sender, "to deleete the player from the rank.") String rank, @Arg(name = "ladder", description = "The ladder to demote on.", def = "default") String ladder) { - if ( "*all*".equalsIgnoreCase( playerName )) { - PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); - - for ( RankPlayer player : pm.getPlayers() ) { - - Player targetPlayer = getPlayer( null, player.getName() ); - if ( targetPlayer != null ) { - - boolean isSameRank = rank.equalsIgnoreCase("*same*"); - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - PlayerRank pRank = rankPlayerFactory.getRank( player, ladder ); - String rankNameCurrent = isSameRank && - pRank != null && - pRank.getRank() != null ? - pRank.getRank().getName() : ""; - - String targetRank = isSameRank ? rankNameCurrent : rank; - setPlayerRank( targetPlayer, targetRank, ladder, sender ); - } - } - - } - else { - - Player player = getPlayer( sender, playerName ); - - if (player == null) { - ranksPromotePlayerMustBeOnlineMsg( sender ); - return; - } - - setPlayerRank( player, rank, ladder, sender ); - } + if ( "*all*".equalsIgnoreCase( playerName )) { + PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + for ( RankPlayer player : pm.getPlayers() ) { + + boolean isSameRank = rank.equalsIgnoreCase("*same*"); + + PlayerRank pRank = rankPlayerFactory.getRank( player, ladder ); + String rankNameCurrent = isSameRank && + pRank != null && + pRank.getRank() != null ? + pRank.getRank().getName() : ""; + + String targetRank = isSameRank ? rankNameCurrent : rank; + setPlayerRank( player, targetRank, ladder, sender ); + } + + } + else { + + Player player = getPlayerByName( playerName ); + + if (player == null) { + ranksPromotePlayerMustBeOnlineMsg( sender ); + return; + } + + setPlayerRank( player.getRankPlayer(), rank, ladder, sender ); + } } @@ -993,7 +928,7 @@ public void removeRank(CommandSender sender, @Arg(name = "playerName", def = "", description = "Player name") String playerName, @Arg(name = "ladder", description = "The ladder to demote on.", def = "default") String ladder) { - setRank( sender, playerName, "-remove-", ladder ); + setRank( sender, playerName, "-remove-", ladder ); } @@ -1002,21 +937,20 @@ public void setPlayerRank( RankPlayer rankPlayer, Rank pRank ) { if ( rankPlayer != null ) { - List cmdTasks = new ArrayList<>(); - - RankupResults results = - new RankUtil().setRank(rankPlayer, rankPlayer, - pRank.getLadder().getName(), pRank.getName(), - rankPlayer.getName(), rankPlayer.getName(), - cmdTasks ); - - // submit cmdTasks - Player player = getPlayer( null, rankPlayer.getName() ); - submitCmdTasks( player, cmdTasks ); - - processResults( rankPlayer, rankPlayer.getName(), results, - pRank.getName(), pRank.getLadder().getName(), - pRank.getCurrency(), null ); + List cmdTasks = new ArrayList<>(); + + RankupResults results = + new RankUtil().setRank(rankPlayer, rankPlayer, + pRank.getLadder().getName(), pRank.getName(), + rankPlayer.getName(), rankPlayer.getName(), + cmdTasks ); + + // submit cmdTasks + submitCmdTasks( rankPlayer, cmdTasks ); + + processResults( rankPlayer, rankPlayer.getName(), results, + pRank.getName(), pRank.getLadder().getName(), + pRank.getCurrency(), null, RankupModes.ONE_RANK ); } } @@ -1029,24 +963,23 @@ public void setPlayerRank( RankPlayer rankPlayer, Rank pRank ) { */ public void setPlayerRankFirstJoin( RankPlayer rankPlayer, Rank pRank ) { - if ( rankPlayer != null ) { - - List cmdTasks = new ArrayList<>(); - - RankupResults results = - new RankUtil().setRank(rankPlayer, rankPlayer, - pRank.getLadder().getName(), pRank.getName(), - rankPlayer.getName(), "FirstJoinEvent", - cmdTasks ); - - // submit cmdTasks - Player player = getPlayer( null, rankPlayer.getName() ); - submitCmdTasks( player, cmdTasks ); - - processResults( rankPlayer, rankPlayer.getName(), results, - pRank.getName(), pRank.getLadder().getName(), - pRank.getCurrency(), null ); - } + if ( rankPlayer != null ) { + + List cmdTasks = new ArrayList<>(); + + RankupResults results = + new RankUtil().setRank(rankPlayer, rankPlayer, + pRank.getLadder().getName(), pRank.getName(), + rankPlayer.getName(), "FirstJoinEvent", + cmdTasks ); + + // submit cmdTasks + submitCmdTasks( rankPlayer, cmdTasks ); + + processResults( rankPlayer, rankPlayer.getName(), results, + pRank.getName(), pRank.getLadder().getName(), + pRank.getCurrency(), null, RankupModes.ONE_RANK ); + } } @@ -1054,47 +987,44 @@ private void setPlayerRank( RankPlayer rankPlayer, RankLadder ladder, Rank pRank CommandSender sender, List cmdTasks, StringBuilder sbRanks ) { - // Get currency if it exists, otherwise it will be null if the Rank has no currency: - String currency = rankPlayer == null || pRank == null ? null : pRank.getCurrency(); - - - RankupResults results = new RankUtil().setRank( rankPlayer, rankPlayer, - ladder.getName(), pRank.getName(), - rankPlayer.getName(), sender.getName(), cmdTasks ); - - - processResults( sender, rankPlayer.getName(), results, pRank.getName(), ladder.getName(), - currency, sbRanks ); + // Get currency if it exists, otherwise it will be null if the Rank has no currency: + String currency = rankPlayer == null || pRank == null ? null : pRank.getCurrency(); + + + RankupResults results = new RankUtil().setRank( rankPlayer, rankPlayer, + ladder.getName(), pRank.getName(), + rankPlayer.getName(), sender.getName(), cmdTasks ); + + + processResults( sender, rankPlayer.getName(), results, pRank.getName(), ladder.getName(), + currency, sbRanks, RankupModes.ONE_RANK ); } - private void setPlayerRank( Player player, String rank, String ladderName, CommandSender sender ) { - UUID playerUuid = player.getUUID(); + private void setPlayerRank( RankPlayer rankPlayer, String rank, String ladderName, CommandSender sender ) { Output.get().logDebug( DebugTarget.rankup, "Rankup: setPlayerRank: "); - RankPlayer rankPlayer = getRankPlayer( sender, playerUuid, player.getName() ); ladderName = confirmLadder( sender, ladderName, rankPlayer ); if ( ladderName != null && rankPlayer != null ) { -// RankLadder rLadder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); - - Rank pRank = PrisonRanks.getInstance().getRankManager().getRank( rank ); - - // Get currency if it exists, otherwise it will be null if the Rank has no currency: - String currency = rankPlayer == null || pRank == null ? null : pRank.getCurrency(); - - List cmdTasks = new ArrayList<>(); - RankupResults results = new RankUtil().setRank(player, rankPlayer, ladderName, rank, - player.getName(), sender.getName(), cmdTasks ); - - // submit cmdTasks - submitCmdTasks( player, cmdTasks ); - - processResults( sender, player.getName(), results, rank, ladderName, currency, null ); + Rank pRank = PrisonRanks.getInstance().getRankManager().getRank( rank ); + + // Get currency if it exists, otherwise it will be null if the Rank has no currency: + String currency = rankPlayer == null || pRank == null ? null : pRank.getCurrency(); + + List cmdTasks = new ArrayList<>(); + + RankupResults results = new RankUtil().setRank(rankPlayer, rankPlayer, ladderName, rank, + rankPlayer.getName(), sender.getName(), cmdTasks ); + + // submit cmdTasks + submitCmdTasks( rankPlayer, cmdTasks ); + + processResults( sender, rankPlayer.getName(), results, rank, ladderName, currency, null, RankupModes.ONE_RANK ); } } @@ -1107,23 +1037,34 @@ private String confirmLadder( CommandSender sender, String ladderName, RankPlaye // The ladder doesn't exist if ( ladder == null ) { - ranksConfirmLadderMsg( sender, ladderName, rPlayer ); + ranksConfirmLadderMsg( sender, ladderName, rPlayer ); } else { - results = ladder.getName(); + results = ladder.getName(); } return results; } + /** + * This gets the RankPlayer for the given UUID or playerName. The 'sender' generally is the + * console, or an admin that is trying to run the command for a player. + * So although the sender has a 'getRankPlayer()' function, it may be for the wrong player. + * + + * + * @param sender The one who should get an messages, but is not the one for RankPlayer. + * @param playerUuid + * @param playerName + * @return + */ public RankPlayer getRankPlayer( CommandSender sender, UUID playerUuid, String playerName ) { - RankPlayer player = - PrisonRanks.getInstance().getPlayerManager().getPlayer(playerUuid, playerName); + RankPlayer player = PrisonRanks.getInstance().getPlayerManager().getPlayer(playerUuid, playerName); // Well, this isn't supposed to happen... if ( player == null ) { - ranksRankupFailureToGetRankPlayerMsg( sender ); + ranksRankupFailureToGetRankPlayerMsg( sender ); } return player; @@ -1133,60 +1074,78 @@ public RankPlayer getRankPlayer( CommandSender sender, UUID playerUuid, String p public void processResults( CommandSender sender, String playerName, RankupResults results, String rank, String ladder, String currency, - StringBuilder sbRanks ) { + StringBuilder sbRanks, + RankupModes mode ) { switch (results.getStatus()) { case RANKUP_SUCCESS: - ranksRankupSuccessMsg( sender, playerName, results, sbRanks ); - - break; + ranksRankupSuccessMsg( sender, playerName, results, sbRanks ); + + break; case DEMOTE_SUCCESS: - ranksRankupSuccessMsg( sender, playerName, results, null ); - - break; + ranksRankupSuccessMsg( sender, playerName, results, null ); + + break; + case RANKUP_CANT_AFFORD: - ranksRankupCannotAffordMsg( sender, results ); + + // If mode is MAX_RANKS and was already successful, then do not display + // cannot afford message when it hits the end of the max rankups... + if ( mode != RankupModes.MAX_RANKS || + mode == RankupModes.MAX_RANKS && sbRanks.length() == 0 ) { + + ranksRankupCannotAffordMsg( sender, results ); + } + break; - break; case RANKUP_LOWEST: - ranksRankupLowestRankMsg( sender, playerName, results ); + ranksRankupLowestRankMsg( sender, playerName, results ); + + break; - break; case RANKUP_HIGHEST: - ranksRankupHighestRankMsg( sender, playerName, results ); + ranksRankupHighestRankMsg( sender, playerName, results ); - break; + break; + case RANKUP_FAILURE: - ranksRankupFailureMsg( sender, results.getRankPlayer() ); + ranksRankupFailureMsg( sender, results.getRankPlayer() ); - break; + break; + case RANKUP_FAILURE_COULD_NOT_LOAD_PLAYER: - ranksRankupFailureCouldNotLoadPlayerMsg( sender, results.getRankPlayer() ); + ranksRankupFailureCouldNotLoadPlayerMsg( sender, results.getRankPlayer() ); - break; + break; + case RANKUP_FAILURE_COULD_NOT_LOAD_LADDER: - ranksRankupFailureCouldNotLoadLadderMsg( sender, results.getRankPlayer() ); + ranksRankupFailureCouldNotLoadLadderMsg( sender, results.getRankPlayer() ); - break; + break; + case RANKUP_FAILURE_UNABLE_TO_ASSIGN_RANK: - ranksRankupFailureUnableToAssignRankMsg( sender, results.getRankPlayer() ); + ranksRankupFailureUnableToAssignRankMsg( sender, results.getRankPlayer() ); - break; + break; + case RANKUP_FAILURE_COULD_NOT_SAVE_PLAYER_FILE: - ranksRankupFailureCouldNotSavePlayerFileMsg( sender, results.getRankPlayer() ); + ranksRankupFailureCouldNotSavePlayerFileMsg( sender, results.getRankPlayer() ); - break; + break; + case RANKUP_NO_RANKS: - ranksRankupFailureNoRanksMsg( sender, results.getRankPlayer() ); + ranksRankupFailureNoRanksMsg( sender, results.getRankPlayer() ); - break; + break; + case RANKUP_FAILURE_RANK_DOES_NOT_EXIST: - ranksRankupFailureRankDoesNotExistMsg( sender, rank, results.getRankPlayer() ); + ranksRankupFailureRankDoesNotExistMsg( sender, rank, results.getRankPlayer() ); - break; - case RANKUP_FAILURE_RANK_IS_NOT_IN_LADDER: + break; + + case RANKUP_FAILURE_RANK_IS_NOT_IN_LADDER: ranksRankupFailureRankIsNotInLadderMsg( sender, rank, ladder, results.getRankPlayer() ); break; @@ -1198,10 +1157,10 @@ public void processResults( CommandSender sender, String playerName, break; case RANKUP_FAILURE_ECONOMY_FAILED: - // TODO externalize message - String msg = "Failed to adjust player's balance. Could be an issue with vault or " + - "a cache timing issue. Try again."; - sender.sendMessage( results.getRankPlayer().convertStringPlaceholders( msg ) ); + ranksRankupFailureEconomyFailedMsg( sender, results.getRankPlayer() ); + //String msg = "Failed to adjust player's balance. Could be an issue with vault or " + + // "a cache timing issue. Try again."; + //sender.sendMessage( results.getRankPlayer().convertStringPlaceholders( msg ) ); break; @@ -1219,6 +1178,7 @@ public void processResults( CommandSender sender, String playerName, ranksRankupFailureInProgressMsg( sender, results.getRankPlayer() ); break; + default: break; } @@ -1229,16 +1189,12 @@ private void submitCmdTask( Player player, String command ) { Scheduler scheduler = Prison.get().getPlatform().getScheduler(); scheduler.performCommand( player, command ); -// scheduler.dispatchCommand( player, command ); - -// PrisonCommandTaskData task = new PrisonCommandTaskData( errorPrefix, command ); -// PrisonCommandTasks.submitTasks( player, task ); } private void submitCmdTasks( Player player, List cmdTasks ) { - PrisonCommandTasks.submitTasks( player, cmdTasks ); + PrisonCommandTasks.submitTasks( player, cmdTasks ); } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommandMessages.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommandMessages.java index 6c1a1c9aa..21d1f032d 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommandMessages.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RankUpCommandMessages.java @@ -35,8 +35,8 @@ protected void rankupMaxNoPermissionMsg( CommandSender sender, String permission protected String rankupCannotRunFromConsoleMsg() { return PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__cannot_run_from_console" ) - .localize(); + .getLocalizable( "ranks_rankup__cannot_run_from_console" ) + .localize(); } protected void rankupInvalidPlayerNameMsg(CommandSender sender, String playerName) { @@ -66,24 +66,24 @@ protected void rankupErrorNoLowerRankMsg( CommandSender sender ) { protected void rankupErrorNoLadderMsg( CommandSender sender, String ladderName ) { PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__error_no_ladder" ) - .withReplacements( ladderName ) - .sendTo( sender ); + .getLocalizable( "ranks_rankup__error_no_ladder" ) + .withReplacements( ladderName ) + .sendTo( sender ); } protected void rankupErrorNoRankOnLadderMsg( CommandSender sender, String ladderName ) { PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__error_no_lower_rank_on_ladder" ) - .withReplacements( ladderName ) - .sendTo( sender ); + .getLocalizable( "ranks_rankup__error_no_lower_rank_on_ladder" ) + .withReplacements( ladderName ) + .sendTo( sender ); } protected void rankupErrorPlayerNotOnDefaultLadder( CommandSender sender, RankPlayer rankPlayer ) { PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__error_player_not_on_default_ladder" ) - .withReplacements( rankPlayer.getName() ) - .sendTo( sender ); + .getLocalizable( "ranks_rankup__error_player_not_on_default_ladder" ) + .withReplacements( rankPlayer.getName() ) + .sendTo( sender ); } protected void rankupNotAtLastRankMsg( CommandSender sender, @@ -96,8 +96,8 @@ protected void rankupNotAtLastRankMsg( CommandSender sender, protected void rankupAtLastRankMsg( CommandSender sender, RankPlayer rPlayer ) { PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__at_last_rank" ) - .sendTo( sender, rPlayer ); + .getLocalizable( "ranks_rankup__at_last_rank" ) + .sendTo( sender, rPlayer ); } protected void rankupNotAbleToPrestigeMsg( CommandSender sender, @@ -134,9 +134,9 @@ protected void prestigePlayerSucessfulMsg( CommandSender sender, String tag, protected void prestigePlayerSucessfulBroadcastMsg( CommandSender sender, String tag, RankPlayer rPlayer ) { PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__prestige_successful_broadcast" ) - .withReplacements( tag ) - .sendTo( sender, rPlayer ); + .getLocalizable( "ranks_rankup__prestige_successful_broadcast" ) + .withReplacements( tag ) + .sendTo( sender, rPlayer ); } protected void prestigePlayerFailureMsg( CommandSender sender, String tag, @@ -233,7 +233,7 @@ protected void prestigeConfirmationMsg( CommandSender sender, .sendTo( sender, rPlayer ); rMsg.getLocalizable( "ranks_rankup__confirm_prestige_line_3" ) - .withReplacements( + .withReplacements( dFmt.format( balance), currency == null || currency.trim().length() == 0 ? "" : " " + currency ) @@ -275,7 +275,7 @@ protected void ranksRankupPlayerBalanceMsg( CommandSender sender, LocaleManager rMsg = PrisonRanks.getInstance().getRanksMessages(); rMsg.getLocalizable( "ranks_rankup__confirm_prestige_line_3" ) - .withReplacements( + .withReplacements( dFmt.format( balance), currency == null || currency.trim().length() == 0 ? "" : " " + currency ) @@ -334,7 +334,6 @@ protected void ranksRankupSuccessMsg( CommandSender sender, String playerName, RankPlayer rPlayer = results.getRankPlayer(); -// PlayerRank tpRank = results.getPlayerRankTarget(); Rank tRank = results.getTargetRank(); @@ -350,71 +349,96 @@ protected void ranksRankupSuccessMsg( CommandSender sender, String playerName, "ranks_rankup__demote_success" : "ranks_rankup__rankup_success" ; - String messagNoPlayerName = PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__rankup_no_player_name" ).localize(); - - Localizable localManager = PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( messageId ) - .withReplacements( - - (playerName == null ? messagNoPlayerName : playerName), - (tRank == null ? "" : tRank.getTag() ), - (results.getMessage() != null ? results.getMessage() : "") - ); - - Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__log_rank_change" ) - .withReplacements( - - sender.getName(), localManager.localize() - ); - Output.get().logInfo( - rPlayer.convertStringPlaceholders( - localManagerLog.localize() )); + String messagNoPlayerName = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankup__rankup_no_player_name" ).localize(); + + Localizable localManager = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( messageId ) + .withReplacements( + + (playerName == null ? messagNoPlayerName : playerName), + (tRank == null ? "" : tRank.getTag() ), + (results.getMessage() != null ? results.getMessage() : "") + ); + + Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankup__log_rank_change" ) + .withReplacements( + + sender.getName(), localManager.localize() + ); + Output.get().logInfo( + rPlayer.convertStringPlaceholders( + localManagerLog.localize() )); - if ( Prison.get().getPlatform().getConfigBooleanFalse( "broadcast-rankups" ) ) { - String messagNoPlayerNameBroadcast = PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__rankup_no_player_name_broadcast" ).localize(); - - PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( messageId ) - .withReplacements( - - (playerName == null ? messagNoPlayerNameBroadcast : playerName), - (tRank == null ? "" : tRank.getTag() ), - (results.getMessage() != null ? results.getMessage() : "") - ) - .broadcast( rPlayer ); - } - else { - localManager.sendTo( sender, rPlayer ); - } + if ( Prison.get().getPlatform().getConfigBooleanFalse( "broadcast-rankups" ) ) { + String messagNoPlayerNameBroadcast = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankup__rankup_no_player_name_broadcast" ).localize(); + + PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( messageId ) + .withReplacements( + + (playerName == null ? messagNoPlayerNameBroadcast : playerName), + (tRank == null ? "" : tRank.getTag() ), + (results.getMessage() != null ? results.getMessage() : "") + ) + .broadcast( rPlayer ); + } + else { + localManager.sendTo( sender, rPlayer ); + } } protected void ranksRankupMaxSuccessMsg( CommandSender sender, StringBuilder ranks, RankPlayer rPlayer ) { - Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__log_rank_change" ) - .withReplacements( - - sender.getName(), ranks.toString() - ); - - // Print to console for record: - Output.get().logInfo( localManagerLog.localize() ); - - - if ( Prison.get().getPlatform().getConfigBooleanFalse( "broadcast-rankups" ) ) { - - localManagerLog.broadcast( rPlayer ); - - } - else { - - localManagerLog.sendTo( sender, rPlayer ); - } + Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankup__log_rank_change" ) + .withReplacements( + + sender.getName(), ranks.toString() + ); + + // Print to console for record: + Output.get().logInfo( localManagerLog.localize() ); + + String messageId = "ranks_rankup__rankup_success" ; + + + + + String messagNoPlayerNameBroadcast = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankup__rankup_no_player_name_broadcast" ).localize(); + + if ( Prison.get().getPlatform().getConfigBooleanFalse( "broadcast-rankups" ) ) { + + PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( messageId ) + .withReplacements( + + (rPlayer.getName() == null ? messagNoPlayerNameBroadcast : rPlayer.getName() ), + ranks.toString(), + "" // no message - do not have anything configured for rankupmax on this? + ) + .broadcast( rPlayer ); + } + else { + + Localizable localManager = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( messageId ) + .withReplacements( + + (rPlayer.getName() == null ? messagNoPlayerNameBroadcast : rPlayer.getName() ), + ranks.toString(), + "" // no message - do not have anything configured for rankupmax on this? + + ); + + localManager.sendTo( sender, rPlayer ); + } + } protected void ranksRankupCannotAffordMsg( CommandSender sender, @@ -433,15 +457,15 @@ protected void ranksRankupCannotAffordMsg( CommandSender sender, Rank tRank = tpRank.getRank(); - PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__rankup_cant_afford" ) - .withReplacements( - - dFmt.format( tpRank == null ? 0 : tpRank.getRankCost()), - tRank == null || tRank.getCurrency() == null ? "" : - " " +tRank.getCurrency() - ) - .sendTo( sender, rPlayer ); + PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankup__rankup_cant_afford" ) + .withReplacements( + + dFmt.format( tpRank == null ? 0 : tpRank.getRankCost()), + tRank == null || tRank.getCurrency() == null ? "" : + " " +tRank.getCurrency() + ) + .sendTo( sender, rPlayer ); } protected void ranksRankupLowestRankMsg( CommandSender sender, String playerName, @@ -508,8 +532,8 @@ protected void ranksRankupFailureUnableToAssignRankWithRefundMsg( CommandSender RankPlayer rPlayer ) { PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankup__rankup_failed_to_assign_rank_with_refund" ) - .sendTo( sender, rPlayer ); + .getLocalizable( "ranks_rankup__rankup_failed_to_assign_rank_with_refund" ) + .sendTo( sender, rPlayer ); } protected void ranksRankupFailureCouldNotSavePlayerFileMsg( CommandSender sender, @@ -557,6 +581,14 @@ protected void ranksRankupFailureCurrencyIsNotSupportedMsg( CommandSender sender .sendTo( sender, rPlayer ); } + protected void ranksRankupFailureEconomyFailedMsg( CommandSender sender, + RankPlayer rPlayer ) { + + PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankup__rankup_economy_failed" ) + .sendTo( sender, rPlayer ); + } + protected void ranksRankupFailureLadderRemovedMsg( CommandSender sender, String ladder, RankPlayer rPlayer ) { 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 7503bccc8..7f21debfa 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 @@ -1,5 +1,6 @@ package tech.mcprison.prison.ranks.commands; +import java.io.IOException; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -10,12 +11,12 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.UUID; 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.cache.PlayerCache; import tech.mcprison.prison.cache.PlayerCachePlayerData; import tech.mcprison.prison.chat.FancyMessage; import tech.mcprison.prison.commands.Arg; @@ -26,7 +27,6 @@ import tech.mcprison.prison.integration.IntegrationType; import tech.mcprison.prison.integration.PermissionIntegration; import tech.mcprison.prison.internal.CommandSender; -import tech.mcprison.prison.internal.OfflineMcPlayer; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.modules.ModuleElement; import tech.mcprison.prison.modules.ModuleElementType; @@ -47,9 +47,10 @@ import tech.mcprison.prison.ranks.data.RankPlayerName; import tech.mcprison.prison.ranks.data.TopNPlayers; import tech.mcprison.prison.ranks.managers.LadderManager; -import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.ranks.managers.RankManager; import tech.mcprison.prison.ranks.managers.RankManager.RanksByLadderOptions; +import tech.mcprison.prison.ranks.tasks.PlayerNewFileNameCheckAsyncTask; +import tech.mcprison.prison.ranks.tasks.PlayerNewFileNameCheckAsyncTask.ReportMode; import tech.mcprison.prison.util.JumboTextFont; import tech.mcprison.prison.util.Text; @@ -81,19 +82,19 @@ public void setRankCommandCommands( CommandCommands rankCommandCommands ) { @Command(identifier = "ranks command", onlyPlayers = false, permissions = "prison.commands") public void ranksCommandSubcommands(CommandSender sender) { - sender.dispatchCommand( "ranks command help" ); + sender.dispatchCommand( "ranks command help" ); } @Command(identifier = "ranks ladder", onlyPlayers = false, permissions = "prison.commands") public void ranksLadderSubcommands(CommandSender sender) { - sender.dispatchCommand( "ranks ladder help" ); + sender.dispatchCommand( "ranks ladder help" ); } // @Command(identifier = "ranks perms", // onlyPlayers = false, permissions = "prison.commands") public void ranksPermsSubcommands(CommandSender sender) { - sender.dispatchCommand( "ranks perms help" ); + sender.dispatchCommand( "ranks perms help" ); } // @Command(identifier = "ranks remove", @@ -105,7 +106,7 @@ public void ranksPermsSubcommands(CommandSender sender) { @Command(identifier = "ranks set", onlyPlayers = false, permissions = "prison.commands") public void ranksSetSubcommands(CommandSender sender) { - sender.dispatchCommand( "ranks set help" ); + sender.dispatchCommand( "ranks set help" ); } @Command(identifier = "ranks create", description = "Creates a new rank", @@ -133,23 +134,23 @@ public boolean createRank(CommandSender sender, tag += " " + options; } - boolean updatePlaceholders = !tag.toLowerCase().contains( "noplaceholderupdate" ); - if ( !updatePlaceholders ) { - tag = tag.replaceAll( "(?i)noPlaceholderUpdate", "" ).trim(); - } + boolean updatePlaceholders = !tag.toLowerCase().contains( "noplaceholderupdate" ); + if ( !updatePlaceholders ) { + tag = tag.replaceAll( "(?i)noPlaceholderUpdate", "" ).trim(); + } boolean success = false; // Ensure a rank with the name doesn't already exist if (PrisonRanks.getInstance().getRankManager().getRank(name) != null) { - rankAlreadyExistsMsg( sender, name ); + rankAlreadyExistsMsg( sender, name ); return success; } // Ensure a rank with the name doesn't already exist if (name == null || name.trim().length() == 0 || name.contains( "&" )) { - rankNameRequiredMsg( sender ); - return success; + rankNameRequiredMsg( sender ); + return success; } // Fetch the ladder first, so we can see if it exists @@ -157,7 +158,7 @@ public boolean createRank(CommandSender sender, RankLadder rankLadder = PrisonRanks.getInstance().getLadderManager().getLadder(ladder); if ( rankLadder == null ) { - ladderDoesNotExistMsg( sender, ladder ); + ladderDoesNotExistMsg( sender, ladder ); return success; } @@ -172,20 +173,14 @@ public boolean createRank(CommandSender sender, // Ensure it was created if (!newRankOptional.isPresent()) { - rankCannotBeCreatedMsg( sender ); + rankCannotBeCreatedMsg( sender ); return success; } Rank newRank = newRankOptional.get(); // Save the rank -// try { - PrisonRanks.getInstance().getRankManager().saveRank(newRank); -// } catch (IOException e) { -// Output.get().sendError(sender, -// "The new rank could not be saved to disk. Check the console for details."); -// Output.get().logError("Rank could not be written to disk.", e); -// } + PrisonRanks.getInstance().getRankManager().saveRank(newRank); // Add the ladder @@ -195,7 +190,7 @@ public boolean createRank(CommandSender sender, success = true; if ( updatePlaceholders ) { - Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); + Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); } @@ -209,7 +204,7 @@ public boolean createRank(CommandSender sender, } else { - errorCouldNotSaveLadderMsg( sender, rankLadder.getName() ); + errorCouldNotSaveLadderMsg( sender, rankLadder.getName() ); } return success; @@ -422,40 +417,6 @@ public void autoConfigureRanks(CommandSender sender, return; } -// TreeMap plugins = -// Prison.get().getPrisonCommands().getRegisteredPluginData(); - - -// String permCmdAdd = null; -// String permCmdDel = null; -// String perm1 = "mines."; -// String perm2 = "mines.tp."; - -// if ( plugins.containsKey("LuckPerms") ){ -// permCmdAdd = "lp user {player} permission set "; -// permCmdDel = "lp user {player} permission unset "; -// } -// else if ( plugins.containsKey("PermissionsEx") ){ -// permCmdAdd = "pex user {player} add "; -// permCmdDel = "pex user {player} add -"; -// } -// else if ( plugins.containsKey("UltraPermissions") ){ -// permCmdAdd = "upc addplayerpermission {player} "; -// permCmdDel = "upc removeplayerpermission {player} "; -// } -// else if ( plugins.containsKey("GroupManager") ){ -// permCmdAdd = "manuaddp {player} "; -// permCmdDel = "manudelp {player} "; -// } -// else if ( plugins.containsKey("zPermissions") ){ -// permCmdAdd = "permissions player {player} set "; -// permCmdDel = "permissions player {player} unset "; -// } -// else if ( plugins.containsKey("PowerfulPerms") ){ -// permCmdAdd = "pp user {player} add "; -// permCmdAdd = "pp user {player} remove "; -// } - int countRanks = 0; @@ -475,93 +436,64 @@ public void autoConfigureRanks(CommandSender sender, String firstRankName = null; for ( char cRank = 'A'; cRank <= 'Z'; cRank++) { - String rankName = Character.toString( cRank ); - - rankMineNames.add( rankName ); - - String tag = "&7[&" + Integer.toHexString((colorID++ % 15) + 1) + rankName + "&7]"; - - if ( firstRankName == null ) { - firstRankName = rankName; - } - -// char cRankNext = (char) (cRank + 1); -// String rankNameNext = Character.toString( cRankNext ); + String rankName = Character.toString( cRank ); + + rankMineNames.add( rankName ); + + String tag = "&7[&" + Integer.toHexString((colorID++ % 15) + 1) + rankName + "&7]"; + + if ( firstRankName == null ) { + firstRankName = rankName; + } - boolean forceRank = force && PrisonRanks.getInstance().getRankManager().getRank( rankName ) != null; - if ( forceRank || - createRank(sender, rankName, price, - LadderManager.LADDER_DEFAULT, tag, "noPlaceholderUpdate") ) { - - if ( forceRank ) { - countRanksForced++; - } - else { - countRanks++; - } - - -// if ( permCmdAdd != null ) { -// getRankCommandCommands().commandAdd( sender, rankName, permCmdAdd + perm1 + rankName.toLowerCase()); -// countRankCmds++; -//// getRankCommandCommands().commandAdd( sender, rankName, permCmdAdd + perm2 + rankName.toLowerCase()); -//// countRankCmds++; -// -// // Add all the command removal statements to rank A's commands so if the command /ranks set rank A is -// // used then all perms are removed -// if ( !firstRankName.equalsIgnoreCase( rankName ) ) { -// getRankCommandCommands().commandAdd( sender, firstRankName, permCmdDel + perm1 + rankName.toLowerCase()); -// countRankCmds++; -//// getRankCommandCommands().commandAdd( sender, firstRankName, permCmdDel + perm2 + rankName.toLowerCase()); -//// countRankCmds++; -// } -// -// if ( cRankNext <= 'Z' ) { -// getRankCommandCommands().commandAdd( sender, rankName, permCmdDel + perm1 + rankNameNext.toLowerCase()); -// countRankCmds++; -//// getRankCommandCommands().commandAdd( sender, rankName, permCmdDel + perm2 + rankNameNext.toLowerCase()); -//// countRankCmds++; -// } -// -// } - - if ( mines ) { - - // Creates a virtual mine: - String perm = null; -// String perm = perm1 + rankName; - - - - ModuleElement mine = Prison.get().getPlatform().getModuleElement( ModuleElementType.MINE, rankName ); - - boolean forceMine = force && mine != null; - - if ( mine == null ) { - mine = Prison.get().getPlatform().createModuleElement( - sender, ModuleElementType.MINE, rankName, tag, perm ); - } - - - if ( mine != null ) { - if ( forceMine ) { - countMinesForced++; - } - else { - countMines++; - } - - // Links the virtual mine to generated rank and configure mines: - if ( Prison.get().getPlatform().linkModuleElements( mine, ModuleElementType.RANK, rankName ) ) { - countLinked++; - } - - } - } - } - else { - autoConfigRankExistsSkipMsg( sender, Character.toString( cRank ) ); - } + boolean forceRank = force && PrisonRanks.getInstance().getRankManager().getRank( rankName ) != null; + if ( forceRank || + createRank(sender, rankName, price, + LadderManager.LADDER_DEFAULT, tag, "noPlaceholderUpdate") ) { + + if ( forceRank ) { + countRanksForced++; + } + else { + countRanks++; + } + + + if ( mines ) { + + // Creates a virtual mine: + String perm = null; + + + ModuleElement mine = Prison.get().getPlatform().getModuleElement( ModuleElementType.MINE, rankName ); + + boolean forceMine = force && mine != null; + + if ( mine == null ) { + mine = Prison.get().getPlatform().createModuleElement( + sender, ModuleElementType.MINE, rankName, tag, perm ); + } + + + if ( mine != null ) { + if ( forceMine ) { + countMinesForced++; + } + else { + countMines++; + } + + // Links the virtual mine to generated rank and configure mines: + if ( Prison.get().getPlatform().linkModuleElements( mine, ModuleElementType.RANK, rankName ) ) { + countLinked++; + } + + } + } + } + else { + autoConfigRankExistsSkipMsg( sender, Character.toString( cRank ) ); + } if (price == 0){ price += startingPrice; @@ -643,11 +575,6 @@ public void autoConfigureRanks(CommandSender sender, // Reset all player to the first rank on the default ladder: PrisonRanks.getInstance().checkAllPlayersForJoin(); -// RankLadder defaultLadder = PrisonRanks.getInstance().getLadderManager().getLadder( "default" ); -// Rank defaultRank = defaultLadder.getLowestRank().get(); -// PrisonRanks.getInstance().getRankManager().getRankupCommands() -// .setRank( sender, "*all*", "*join*", defaultLadder.getName() ); - if ( countRanksForced > 0 ) { // message about number of ranks that preexisting and were force: @@ -677,13 +604,12 @@ public void autoConfigureRanks(CommandSender sender, Output.get().logInfo( ""); - - } 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 ); @@ -709,19 +635,19 @@ public void removeRank(CommandSender sender, // Check to ensure the rank exists Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); if ( rank == null ) { - rankDoesNotExistMsg( sender, rankName ); + rankDoesNotExistMsg( sender, rankName ); return; } if (PrisonRanks.getInstance().getDefaultLadder().getRanks().contains( rank ) && PrisonRanks.getInstance().getDefaultLadder().getRanks().size() == 1) { - rankCannotBeRemovedMsg( sender ); + rankCannotBeRemovedMsg( sender ); return; } if ( PrisonRanks.getInstance().getRankManager().removeRank(rank) ) { - Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); + Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); // Recalculate the ladder's base rank cost multiplier: PlayerRankRefreshTask rankRefreshTask = new PlayerRankRefreshTask(); @@ -729,7 +655,7 @@ public void removeRank(CommandSender sender, rankWasRemovedMsg( sender, rankName ); } else { - rankDeleteErrorMsg( sender, rankName ); + rankDeleteErrorMsg( sender, rankName ); } } @@ -738,34 +664,26 @@ public void removeRank(CommandSender sender, "ranks.", onlyPlayers = false, altPermissions = "ranks.list" ) - public void listRanks(CommandSender sender, - @Arg(name = "ladderName", def = "default", - description = "A ladder name, or 'all' to list all ranks by ladder.") String ladderName) { - - boolean hasPerm = sender.hasPermission("ranks.list") || - sender.isOp() || !sender.isPlayer(); - + public void listRanks(CommandSender sender, + @Arg(name = "ladderName", def = "default", + description = "A ladder name, or 'all' to list all ranks by ladder.") String ladderName) { + + boolean hasPerm = sender.hasPermission("ranks.list") || + sender.isOp() || !sender.isPlayer(); + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(ladderName); if ( ladder == null && !"all".equalsIgnoreCase( ladderName ) ) { - ladderDoesNotExistMsg( sender, ladderName ); + ladderDoesNotExistMsg( sender, ladderName ); return; } if ( ladder != null && ladder.getRanks().size() == 0 ) { - ladderHasNoRanksMsg( sender, ladderName ); + ladderHasNoRanksMsg( sender, ladderName ); } -// Rank rank = null; -// for (Rank pRank : ladder.getPositionRanks()) { -// Optional rankOptional = ladder.getByPosition(pRank.getPosition()); -// if (rankOptional.isPresent()) { -// rank = rankOptional.get(); -// break; -// } -// } RankPlayer rPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer( sender.getPlatformPlayer() ); @@ -773,14 +691,14 @@ public void listRanks(CommandSender sender, ChatDisplay display = null; if ( ladder != null ) { - display = listRanksOnLadder( ladder, hasPerm, rPlayer ); + display = listRanksOnLadder( ladder, hasPerm, rPlayer ); } else { - display = new ChatDisplay( "List ALL Ranks" ); + display = new ChatDisplay( "List ALL Ranks" ); display.addSupportHyperLinkData( "Rank List" ); - listAllRanksByLadders( display, hasPerm, rPlayer ); + listAllRanksByLadders( display, hasPerm, rPlayer ); } @@ -823,65 +741,50 @@ public void listRanks(CommandSender sender, public void listAllRanksByLadders( ChatDisplay display, boolean hasPerm, RankPlayer rPlayer ) { -// List ladders = PrisonRanks.getInstance().getLadderManager().getLadders(); - -// for ( RankLadder rLadder : ladders ) { -// ChatDisplay cDisp = listRanksOnLadder( rLadder, hasPerm ); -// -// if ( display == null ) { -// display = cDisp; -// } -// else { -// display.addEmptyLine(); -// -// display.addChatDisplay( cDisp ); -// } -// -// } - - // Track which ranks were included in the ladders listed: - List ranksIncluded = new ArrayList<>(); - - for ( RankLadder ladder : PrisonRanks.getInstance().getLadderManager().getLadders() ) { - List ladderRanks = ladder.getRanks(); - ranksIncluded.addAll( ladderRanks ); - - ChatDisplay cDisp = listRanksOnLadder( ladder, hasPerm, rPlayer ); - - if ( display == null ) { - display = cDisp; - } - else { - display.addEmptyLine(); + + // Track which ranks were included in the ladders listed: + List ranksIncluded = new ArrayList<>(); + + for ( RankLadder ladder : PrisonRanks.getInstance().getLadderManager().getLadders() ) { + List ladderRanks = ladder.getRanks(); + ranksIncluded.addAll( ladderRanks ); + + ChatDisplay cDisp = listRanksOnLadder( ladder, hasPerm, rPlayer ); - display.addChatDisplay( cDisp ); - } - - } - - // Next we need to get a list of all ranks that were not included. Create a temp ladder so they - // can be printed out with them: - List ranksExcluded = new ArrayList<>( PrisonRanks.getInstance().getRankManager().getRanks() ); - ranksExcluded.removeAll( ranksIncluded ); + if ( display == null ) { + display = cDisp; + } + else { + display.addEmptyLine(); + + display.addChatDisplay( cDisp ); + } + + } - if ( ranksExcluded.size() > 0 ) { - RankLadder noLadder = new RankLadder( -1, "No Ladder" ); - - for ( Rank rank : ranksExcluded ) { - noLadder.addRank( rank ); - } - - ChatDisplay cDisp = listRanksOnLadder( noLadder, hasPerm, rPlayer ); - - if ( display == null ) { - display = cDisp; - } - else { - display.addEmptyLine(); + // Next we need to get a list of all ranks that were not included. Create a temp ladder so they + // can be printed out with them: + List ranksExcluded = new ArrayList<>( PrisonRanks.getInstance().getRankManager().getRanks() ); + ranksExcluded.removeAll( ranksIncluded ); + + if ( ranksExcluded.size() > 0 ) { + RankLadder noLadder = new RankLadder( -1, "No Ladder" ); + + for ( Rank rank : ranksExcluded ) { + noLadder.addRank( rank ); + } + + ChatDisplay cDisp = listRanksOnLadder( noLadder, hasPerm, rPlayer ); - display.addChatDisplay( cDisp ); - } - } + if ( display == null ) { + display = cDisp; + } + else { + display.addEmptyLine(); + + display.addChatDisplay( cDisp ); + } + } } @@ -953,12 +856,12 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP if ( hasPerm ) { - display.addText( ranksListClickToEditMsg() ); + display.addText( ranksListClickToEditMsg() ); } if ( ladder.getRanks().size() == 0 ) { - display.addText( ladderHasNoRanksTextMsg() ); + display.addText( ladderHasNoRanksTextMsg() ); } BulletedListComponent.BulletedListBuilder builder = @@ -970,25 +873,27 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP // 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; + // Note: Use a value of 1 as a default since '%-0s' would be a failure. This could happen + // if not tags are defined for any ranks. + int maxRankNameSize = 1; + int maxRankTagNoColorSize = 1; + int maxRankCostSize = 1; for (Rank rank : ladder.getRanks()) { - 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; - } + 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++; @@ -1000,145 +905,124 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP boolean first = true; for (Rank rank : ladder.getRanks()) { - 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 ); - -// // 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 -// // formatted text with tagNoColor, then replace the no color tag with the -// // normal tag. -// // If tag is null, show it as an empty String. Normally rank name will -// // be used, but at least this show's it is not set. -// String tag = rank.getTag() == null ? "" : rank.getTag(); -// String tagNoColor = Text.stripColor( tag ); - - - - // If rank list is being generated for a console or op'd player, then show the ladder's rank multiplier, - // but if generating for a player, then show total multiplier accross all ladders. - PlayerRank pRank = null; - double rankCost = 0; - double rMulti = 0; - - if ( hasPerm || rPlayer == null ) { - - rankCost = rank.getRawRankCost(); - - pRank = rankPlayerFactory.createPlayerRank( rank ); -// pRank = rankPlayerFactory.createPlayerRank( rank ); - - rMulti = pRank.getLadderBasedRankMultiplier(); - - } - else { - - pRank = rPlayer.calculateTargetPlayerRank( rank ); - -// pRank = rankPlayerFactory.createPlayerRank( rank ); -// -// -// pRank = pRank.getTargetPlayerRankForPlayer( pRank, rPlayer, rank ); - rankCost = pRank.getRankCost(); - - rMulti = pRank.getRankMultiplier(); - } - - - - String textCmdCount = ( hasPerm ? - ranksListCommandCountMsg(rank.getRankUpCommands().size()) - : "" ); - String textCurrency = (rank.getCurrency() == null ? "" : - ranksListCurrencyMsg( rank.getCurrency() )); - - String rankMultiplier = rMulti == 0d ? "" : fFmt.format( rMulti ); - - 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 ? "" : " +") ) -// : ""); + 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 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 ); + + // // 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 + // // formatted text with tagNoColor, then replace the no color tag with the + // // normal tag. + // // If tag is null, show it as an empty String. Normally rank name will + // // be used, but at least this show's it is not set. + // String tag = rank.getTag() == null ? "" : rank.getTag(); + // String tagNoColor = Text.stripColor( tag ); + + + + // If rank list is being generated for a console or op'd player, then show the ladder's rank multiplier, + // but if generating for a player, then show total multiplier accross all ladders. + PlayerRank pRank = null; + double rankCost = 0; + double rMulti = 0; + + if ( hasPerm || rPlayer == null ) { + + rankCost = rank.getRawRankCost(); + + pRank = rankPlayerFactory.createPlayerRank( rank ); + + rMulti = pRank.getLadderBasedRankMultiplier(); + + } + else { + + pRank = rPlayer.calculateTargetPlayerRank( rank ); + + rankCost = pRank.getRankCost(); + + rMulti = pRank.getRankMultiplier(); + } - StringBuilder minesSb = new StringBuilder(); - for ( ModuleElement mine : rank.getMines() ) { + + String textCmdCount = ( hasPerm ? + ranksListCommandCountMsg(rank.getRankUpCommands().size()) + : "" ); + String textCurrency = (rank.getCurrency() == null ? "" : + ranksListCurrencyMsg( rank.getCurrency() )); + + String rankMultiplier = rMulti == 0d ? "" : fFmt.format( rMulti ); + + String players = rank.getPlayers().size() == 0 ? "" : + " &dPlayers: &3" + rank.getPlayers().size(); + + + 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 %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, - - textCurrency, - textCmdCount, - players, - minesSb.toString() - ); - -// // Swap the color tag back in: -// text = text.replace( tagNoColor, tag ); - - if ( defaultRank ) { - // Swap out the default placeholder for the actual content: - text = text.replace( "{def}", "&c(&r&9Default&r&c)" ); - } - - String rankName = rank.getName(); - if ( rankName.contains( "&" ) ) { - rankName = rankName.replace( "&", "-" ); - } - FancyMessage msg = null; - if ( hasPerm ) { - msg = new FancyMessage(text).command("/ranks info " + rankName) - .tooltip( ranksListClickToViewMsg() ); - } - else { - msg = new FancyMessage(text); - } + if ( minesSb.length() > 0 ) { + minesSb.insert( 0, " &6Mines: &7" ); + } - builder.add(msg); + String text = + String.format("&3%s %s &7%" + maxRankCostSize + "s &a%s &b%s %s&7 %s%s%s", + nameFormatted, + tagFormatted, + + iFmt.format( rankCost ), + (defaultRank ? "{def}" : ""), + + rankMultiplier, + + textCurrency, + textCmdCount, + players, + minesSb.toString() + ); -// rank = rank.getRankNext(); - first = false; + if ( defaultRank ) { + // Swap out the default placeholder for the actual content: + text = text.replace( "{def}", "&c(&r&9Default&r&c)" ); + } + + String rankName = rank.getName(); + if ( rankName.contains( "&" ) ) { + rankName = rankName.replace( "&", "-" ); + } + FancyMessage msg = null; + if ( hasPerm ) { + msg = new FancyMessage(text).command("/ranks info " + rankName) + .tooltip( ranksListClickToViewMsg() ); + } + else { + msg = new FancyMessage(text); + } + + builder.add(msg); + + first = false; } @@ -1175,77 +1059,69 @@ private ChatDisplay listRanksOnLadder( RankLadder ladder, boolean hasPerm, RankP if ( rPlayer != null && !"No Ladder".equals( ladder.getName() ) ) { -// RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - double ladderMultiplier = ladder.getRankCostMultiplierPerRank(); - - PlayerRank pRank = rankPlayerFactory.getRank( rPlayer, ladder ); - double playerMultiplier = pRank != null ? - pRank.getRankMultiplier() : 0; - - if ( playerMultiplier == 0 ) { - display.addText( "&3You have no Ladder Rank Multipliers enabled. The rank costs are not adjusted." ); - } - else { - display.addText( "&3Your current total Rank Multiplier: &7%s.", - fFmt.format( playerMultiplier ) ); - - if ( ladderMultiplier == 0 ) { - display.addText( "&3This ladder has no Rank Multiplier so all ranks on this ladder " + - "have the same multiplier." ); - } - else { - display.addText( "&3This ladder has a Rank Multiplier so each rank has " + - "a differnt multiplier." ); - } - - Set ladders = rPlayer.getLadderRanks().keySet(); - for ( RankLadder rLadder : ladders ) { - if ( rLadder.getRankCostMultiplierPerRank() != 0d ) { - - Rank r = rPlayer.getLadderRanks().get( rLadder ).getRank(); - - PlayerRank rpRank = rPlayer.calculateTargetPlayerRank( r ); -// PlayerRank rpRank = rankPlayerFactory.createPlayerRank( r ); - - display.addText( "&3 BaseMult: &7%7s &3CurrMult: &7%7s &7%s &7%s ", - fFmt.format( rLadder.getRankCostMultiplierPerRank() ), - fFmt.format( rpRank.getLadderBasedRankMultiplier() ), - rLadder.getName(), - (r.getTag() == null ? r.getName() : r.getTag()) - ); - -// display.addText( "&3 Ladder: &7%-9s &3Rank: &7%-8s &3Base Mult: %7s", -// rLadder.getName(), -// rPlayer.getLadderRanks().get( rLadder ).getRank().getTag(), -// fFmt.format( rLadder.getRankCostMultiplierPerRank() ) ); + double ladderMultiplier = ladder.getRankCostMultiplierPerRank(); + + PlayerRank pRank = rankPlayerFactory.getRank( rPlayer, ladder ); + double playerMultiplier = pRank != null ? + pRank.getRankMultiplier() : 0; + + if ( playerMultiplier == 0 ) { + display.addText( "&3You have no Ladder Rank Multipliers enabled. The rank costs are not adjusted." ); + } + else { + display.addText( "&3Your current total Rank Multiplier: &7%s.", + fFmt.format( playerMultiplier ) ); + + if ( ladderMultiplier == 0 ) { + display.addText( "&3This ladder has no Rank Multiplier so all ranks on this ladder " + + "have the same multiplier." ); + } + else { + display.addText( "&3This ladder has a Rank Multiplier so each rank has " + + "a differnt multiplier." ); + } + + Set ladders = rPlayer.getLadderRanks().keySet(); + for ( RankLadder rLadder : ladders ) { + if ( rLadder.getRankCostMultiplierPerRank() != 0d ) { + + Rank r = rPlayer.getLadderRanks().get( rLadder ).getRank(); + + PlayerRank rpRank = rPlayer.calculateTargetPlayerRank( r ); + + display.addText( "&3 BaseMult: &7%7s &3CurrMult: &7%7s &7%s &7%s ", + fFmt.format( rLadder.getRankCostMultiplierPerRank() ), + fFmt.format( rpRank.getLadderBasedRankMultiplier() ), + rLadder.getName(), + (r.getTag() == null ? r.getName() : r.getTag()) + ); + + } } - } - } + } } return display; } -// private String padRankName( Rank rank, int maxRankNameSize, int maxRankTagNoColorSize, boolean hasPerm ) { -// return padRankName( rank.getName(), rank.getTag(), maxRankNameSize, maxRankTagNoColorSize, hasPerm ); -// } + protected String padRankName( String rankName, String rankTag, int maxRankNameSize, int maxRankTagNoColorSize, boolean hasPerm ) { - StringBuilder sb = new StringBuilder(); - - int tLen = (hasPerm ? maxRankNameSize + 1 : 0) + maxRankTagNoColorSize; - String name = hasPerm ? rankName + " " : ""; - String tag = rankTag == null ? "" : rankTag; - String tagNoColor = Text.stripColor( tag ); - - sb.append( name ).append( tag ).append( "&8" ); - - int length = name.length() + tagNoColor.length(); - while ( length++ < tLen ) { - sb.append( "." ); - } + StringBuilder sb = new StringBuilder(); + + int tLen = (hasPerm ? maxRankNameSize + 1 : 0) + maxRankTagNoColorSize; + String name = hasPerm ? rankName + " " : ""; + String tag = rankTag == null ? "" : rankTag; + String tagNoColor = Text.stripColor( tag ); + + sb.append( name ).append( tag ).append( "&8" ); + + int length = name.length() + tagNoColor.length(); + while ( length++ < tLen ) { + sb.append( "." ); + } return sb.toString(); } @@ -1260,45 +1136,35 @@ public void infoCmd(CommandSender sender, Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); if ( rank == null ) { -// rankOpt = PrisonRanks.getInstance().getRankManager().getRankEscaped(rankName); -// if (!rankOpt.isPresent()) { rankDoesNotExistMsg( sender, rankName ); return; -// } } - ChatDisplay display = rankInfoDetails( sender, rank, options ); display.send(sender); -// if ( options != null && "all".equalsIgnoreCase( options )) { - - //getRankCommandCommands().commandLadderList( sender, rank.getLadder().getName(), "noRemoves" ); - -// getRankCommandCommands().commandList( sender, rankName, "noRemoves" ); -// } } public void allRanksInfoDetails( StringBuilder sb ) { - PrisonRanks pRanks = PrisonRanks.getInstance(); - RankManager rMan = pRanks.getRankManager(); - - for ( Rank rank : rMan.getRanks() ) { - - Prison.get().getPrisonStatsUtil().printFooter( sb ); - - JumboTextFont.makeJumboFontText( rank.getName(), sb ); - sb.append( "\n" ); - - ChatDisplay chatDisplay = rankInfoDetails( null, rank, "all" ); - - sb.append( chatDisplay.toStringBuilder() ); + PrisonRanks pRanks = PrisonRanks.getInstance(); + RankManager rMan = pRanks.getRankManager(); + + for ( Rank rank : rMan.getRanks() ) { + + Prison.get().getPrisonStatsUtil().printFooter( sb ); + + JumboTextFont.makeJumboFontText( rank.getName(), sb ); + sb.append( "\n" ); + + ChatDisplay chatDisplay = rankInfoDetails( null, rank, "all" ); + + sb.append( chatDisplay.toStringBuilder() ); } - - Prison.get().getPrisonStatsUtil().printFooter( sb ); + + Prison.get().getPrisonStatsUtil().printFooter( sb ); } @@ -1325,29 +1191,29 @@ private ChatDisplay rankInfoDetails( CommandSender sender, Rank rank, String opt if ( rank.getLadder() != null ) { - row.addTextComponent( " " ); - - row.addTextComponent( "&3Ladder Position: &7%d", rank.getPosition() ); + row.addTextComponent( " " ); + + row.addTextComponent( "&3Ladder Position: &7%d", rank.getPosition() ); } display.addComponent( row ); if ( rank.getMines().size() == 0 ) { - display.addText( ranksInfoNotLinkedToMinesMsg() ); + display.addText( ranksInfoNotLinkedToMinesMsg() ); } else { - StringBuilder sb = new StringBuilder(); - - for ( ModuleElement mine : rank.getMines() ) { - if ( sb.length() > 0 ) { - sb.append( "&3, " ); - } - sb.append( "&7" ); - sb.append( mine.getName() ); + StringBuilder sb = new StringBuilder(); + + for ( ModuleElement mine : rank.getMines() ) { + if ( sb.length() > 0 ) { + sb.append( "&3, " ); + } + sb.append( "&7" ); + sb.append( mine.getName() ); } - display.addText( ranksInfoLinkedMinesMsg( sb.toString() )); + display.addText( ranksInfoLinkedMinesMsg( sb.toString() )); } @@ -1366,9 +1232,6 @@ private ChatDisplay rankInfoDetails( CommandSender sender, Rank rank, String opt // The following is the rank adjusted rank multiplier -// PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); -// RankPlayer rPlayer = pm.getPlayer(player.getUUID(), player.getName()); - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); PlayerRank pRank = rankPlayerFactory.createPlayerRank( rank ); @@ -1395,25 +1258,20 @@ private ChatDisplay rankInfoDetails( CommandSender sender, Rank rank, String opt if ( isOp || isConsole || sender.hasPermission("ranks.admin")) { // This is admin-exclusive content -// display.addText("&8[Admin Only]"); display.addText( ranksInfoRankIdMsg( rank.getId() )); -// FancyMessage del = -// new FancyMessage( ranksInfoRankDeleteMessageMsg() ).command("/ranks delete " + rank.getName()) -// .tooltip( ranksInfoRankDeleteToolTipMsg() ); -// display.addComponent(new FancyMessageComponent(del)); } if ( (isOp || isConsole) && options != null && "all".equalsIgnoreCase( options )) { - - if ( rank.getLadder() != null ) { - - ChatDisplay cmdLadderDisplays = getRankCommandCommands().commandLadderListDetail( rank.getLadder(), true ); - display.addChatDisplay( cmdLadderDisplays ); - } - - ChatDisplay cmdLadderCmdsDisplays = getRankCommandCommands().commandListDetails( rank, true ); - display.addChatDisplay( cmdLadderCmdsDisplays ); + + if ( rank.getLadder() != null ) { + + ChatDisplay cmdLadderDisplays = getRankCommandCommands().commandLadderListDetail( rank.getLadder(), true ); + display.addChatDisplay( cmdLadderDisplays ); + } + + ChatDisplay cmdLadderCmdsDisplays = getRankCommandCommands().commandListDetails( rank, true ); + display.addChatDisplay( cmdLadderCmdsDisplays ); } return display; @@ -1432,13 +1290,11 @@ public void setCost(CommandSender sender, Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); if ( rank == null ) { - rankDoesNotExistMsg( sender, rankName ); + rankDoesNotExistMsg( sender, rankName ); return; } - rank.setRawRankCost( rawCost ); -// PlayerRank.setRawRankCost( rank, rawCost ); PrisonRanks.getInstance().getRankManager().saveRank(rank); @@ -1459,47 +1315,47 @@ public void setCurrency(CommandSender sender, description = "The custom currency to use with this rank, " + "or 'none' to remove a custom currency.") String currency){ - Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); - if ( rank == null ) { - rankDoesNotExistMsg( sender, rankName ); - return; - } - - - if ( currency == null || currency.trim().length() == 0 ) { - rankSetCurrencyNotSpecifiedMsg( sender, currency ); - return; - } - - if ( "none".equalsIgnoreCase( currency ) && rank.getCurrency() == null ) { - - rankSetCurrencyNoCurrencyToClearMsg( sender, rankName ); - - } - else if ( "none".equalsIgnoreCase( currency ) ) { - rank.setCurrency( null ); - - PrisonRanks.getInstance().getRankManager().saveRank(rank); - - rankSetCurrencyClearedMsg( sender, rankName ); - - } - else { - - EconomyCurrencyIntegration currencyEcon = PrisonAPI.getIntegrationManager() - .getEconomyForCurrency( currency ); - if ( currencyEcon == null ) { - - rankSetCurrencyNoActiveSupportMsg( sender, currency ); - return; - } - - rank.setCurrency( currency ); - - PrisonRanks.getInstance().getRankManager().saveRank(rank); - - rankSetCurrencySuccessfulMsg( sender, rankName, currency ); - } + Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); + if ( rank == null ) { + rankDoesNotExistMsg( sender, rankName ); + return; + } + + + if ( currency == null || currency.trim().length() == 0 ) { + rankSetCurrencyNotSpecifiedMsg( sender, currency ); + return; + } + + if ( "none".equalsIgnoreCase( currency ) && rank.getCurrency() == null ) { + + rankSetCurrencyNoCurrencyToClearMsg( sender, rankName ); + + } + else if ( "none".equalsIgnoreCase( currency ) ) { + rank.setCurrency( null ); + + PrisonRanks.getInstance().getRankManager().saveRank(rank); + + rankSetCurrencyClearedMsg( sender, rankName ); + + } + else { + + EconomyCurrencyIntegration currencyEcon = PrisonAPI.getIntegrationManager() + .getEconomyForCurrency( currency ); + if ( currencyEcon == null ) { + + rankSetCurrencyNoActiveSupportMsg( sender, currency ); + return; + } + + rank.setCurrency( currency ); + + PrisonRanks.getInstance().getRankManager().saveRank(rank); + + rankSetCurrencySuccessfulMsg( sender, rankName, currency ); + } } @@ -1513,18 +1369,18 @@ public void setTag(CommandSender sender, Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); if ( rank == null ) { - rankDoesNotExistMsg( sender, rankName ); + rankDoesNotExistMsg( sender, rankName ); return; } if ( tag == null || tag.trim().length() == 0 ) { - rankSetTagInvalidMsg( sender ); - return; + rankSetTagInvalidMsg( sender ); + return; } if ( tag.equalsIgnoreCase( "none" ) ) { - tag = null; + tag = null; } @@ -1532,8 +1388,8 @@ public void setTag(CommandSender sender, rank.getTag() != null && rank.getTag().equalsIgnoreCase( tag )) { - rankSetTagNoChangeMsg( sender ); - return; + rankSetTagNoChangeMsg( sender ); + return; } rank.setTag( tag ); @@ -1541,10 +1397,10 @@ public void setTag(CommandSender sender, PrisonRanks.getInstance().getRankManager().saveRank(rank); if ( tag == null ) { - rankSetTagClearedMsg( sender, rank.getName() ); + rankSetTagClearedMsg( sender, rank.getName() ); } else { - rankSetTagSucessMsg( sender, tag, rank.getName() ); + rankSetTagSucessMsg( sender, tag, rank.getName() ); } } @@ -1572,34 +1428,12 @@ public void ranksImportByPermissions(CommandSender sender, "[]") String options){ - if ( !ladderName.equalsIgnoreCase( "all" ) && - PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ) == null ) { - ranksPlayersInvalidLadderMsg( sender, ladderName ); - return; - } - - -// RanksByLadderOptions option = RanksByLadderOptions.fromString( action ); -// if ( option == null ) { -// ranksPlayersInvalidActionMsg( sender, action ); -// return; -// } + if ( !ladderName.equalsIgnoreCase( "all" ) && + PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ) == null ) { + ranksPlayersInvalidLadderMsg( sender, ladderName ); + return; + } -// boolean includeAll = action.equalsIgnoreCase( "all" ); -// PrisonRanks.getInstance().getRankManager().ranksByLadders( sender, ladderName, option ); - -// Output.get().logInfo( "Ranks by ladders:" ); -// -// for ( RankLadder ladder : PrisonRanks.getInstance().getLadderManager().getLadders() ) { -// if ( ladderName.equalsIgnoreCase( "all" ) || ladderName.equalsIgnoreCase( ladder.name ) ) { -// -// boolean includeAll = action.equalsIgnoreCase( "all" ); -// String ladderRanks = ladder.listAllRanks( includeAll ); -// -// sender.sendMessage( ladderRanks ); -// } -// -// } } @@ -1613,27 +1447,30 @@ public void rankPlayer(CommandSender sender, @Arg(name = "options", def = "", description = "Options [perms]") String options ){ - Player player = getPlayer( sender, playerName ); + RankPlayer rankPlayer = getRankPlayer(sender, null, playerName ); + + if ( rankPlayer == null ) { + rankupInvalidPlayerNameMsg( sender, playerName ); + return; + } + + + // This is a SpigotPlayer object, with the bukkit player attached: + Player sPlayer = rankPlayer.getPlatformPlayer(); - if (player == null) { - ranksPlayerOnlineMsg( sender ); - return; - } - - List msgs = new ArrayList<>(); - DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); - DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); - DecimalFormat fFmt = Prison.get().getDecimalFormat("0.0000"); - DecimalFormat pFmt = Prison.get().getDecimalFormat("#,##0.0000"); + List msgs = new ArrayList<>(); + + DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); + DecimalFormat fFmt = Prison.get().getDecimalFormat("0.0000"); + DecimalFormat pFmt = Prison.get().getDecimalFormat("#,##0.0000"); SimpleDateFormat sdFmt = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ); - - PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); - RankPlayer rankPlayer = pm.getPlayer(player.getUUID(), player.getName()); + // Get the cachedPlayer: - PlayerCachePlayerData cPlayer = PlayerCache.getInstance().getOnlinePlayer( rankPlayer ); + PlayerCachePlayerData cPlayer = rankPlayer.getPlayerCachePlayerData(); @@ -1641,6 +1478,18 @@ public void rankPlayer(CommandSender sender, rankPlayer.getName() ); msgs.add( msg1 ); + + if ( sPlayer != null && cPlayer != null ) { + if ( cPlayer.getLastSeenDate() < sPlayer.getLastSeenDate() ) { + cPlayer.setLastSeenDate( sPlayer.getLastSeenDate() ); + cPlayer.setDirty( true ); + } + + if ( rankPlayer.getLastSeenDate() < sPlayer.getLastSeenDate() ) { + rankPlayer.setLastSeenDateTemp( sPlayer.getLastSeenDate() ); + rankPlayer.setDirty( true ); + } + } String lastSeen = cPlayer == null || cPlayer.getLastSeenDate() == 0 ? @@ -1659,18 +1508,11 @@ public void rankPlayer(CommandSender sender, msgs.add( msgLs ); - - - String msg2 = String.format( " &7Rank Cost Multiplier: &f", - fFmt.format( rankPlayer.getSellAllMultiplier() )); + String msg2 = String.format( " &7Ranks with (Rank Cost Multiplier):"); msgs.add( msg2 ); - if ( rankPlayer != null ) { -// DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); -// -// SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); // Collect all currencies in the default ladder: Set currencies = new LinkedHashSet<>(); @@ -1683,8 +1525,6 @@ public void rankPlayer(CommandSender sender, } -// RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - Map rankLadders = rankPlayer.getLadderRanks(); @@ -1697,15 +1537,15 @@ public void rankPlayer(CommandSender sender, // This calculates the target rank, and takes in to consideration the player's existing rank: PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); - // PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); -// PlayerRank nextPRank = PlayerRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); - -// PlayerRank nextPRank = nextRank == null ? null : -// new PlayerRank( nextRank, pRank.getRankMultiplier() ); + + double rankCostMultiplier = pRank.getRankMultiplier(); String messageRank = ranksPlayerLadderInfoMsg( rankLadder.getName(), rank.getName() ); + + messageRank += " (" + fFmt.format( rankCostMultiplier ) + ") "; + if ( nextRank == null ) { messageRank += ranksPlayerLadderHighestRankMsg(); @@ -1713,7 +1553,6 @@ public void rankPlayer(CommandSender sender, messageRank += ranksPlayerLadderNextRankMsg( nextRank.getName(), ( nextRank == null ? "0" : dFmt.format( nextPRank.getRankCost()) ) ); -// dFmt.format( nextRank.getCost() ) ); if ( nextRank.getCurrency() != null ) { messageRank += ranksPlayerLadderNextRankCurrencyMsg( nextRank.getCurrency() ); @@ -1721,51 +1560,56 @@ public void rankPlayer(CommandSender sender, } msgs.add( messageRank ); -// sendToPlayerAndConsole( sender, messageRank ); } // Print out the player's balances: // The default currency first: double balance = rankPlayer.getBalance(); - String message = ranksPlayerBalanceDefaultMsg( player.getName(), dFmt.format( balance ) ); + String message = ranksPlayerBalanceDefaultMsg( rankPlayer.getName(), dFmt.format( balance ) ); msgs.add( message ); -// sendToPlayerAndConsole( sender, message ); for ( String currency : currencies ) { double balanceCurrency = rankPlayer.getBalance( currency ); String messageCurrency = ranksPlayerBalanceOthersMsg( - player.getName(), dFmt.format( balanceCurrency ), currency ); + rankPlayer.getName(), dFmt.format( balanceCurrency ), currency ); msgs.add( messageCurrency ); -// sendToPlayerAndConsole( sender, messageCurrency ); } - boolean isOp = player.isOp(); - boolean isPlayer = player.isPlayer(); - boolean isOnline = player.isOnline(); + boolean isOp = sPlayer != null ? sPlayer.isOp() : rankPlayer.isOp(); + boolean isPlayer = sPlayer != null ? sPlayer.isPlayer() : rankPlayer.isPlayer(); + boolean isOnline = sPlayer != null ? sPlayer.isOnline() : rankPlayer.isOnline(); - boolean isPrisonPlayer = (player instanceof Player); - boolean isPrisonOfflineMcPlayer = (player instanceof OfflineMcPlayer); if ( !isOnline ) { String msgOffline = ranksPlayerPermsOfflineMsg(); msgs.add( msgOffline ); -// sendToPlayerAndConsole( sender, msgOffline ); } - double sellallMultiplier = player.getSellAllMultiplier(); + + double sellallMultiplier = rankPlayer.getSellAllMultiplierDebug(); + String messageNotAccurrate = ranksPlayerNotAccurateMsg(); String messageSellallMultiplier = ranksPlayerSellallMultiplierMsg( pFmt.format( sellallMultiplier ), (!isOnline ? " " + messageNotAccurrate : "") ); msgs.add( messageSellallMultiplier ); -// sendToPlayerAndConsole( sender, messageSellallMultiplier ); - List sellallDetails = player.getSellAllMultiplierListings(); + + // Warning, if the player is offline, then the list of multiplier details + // will come from their saved listings from when they were last + // on the server, and they may not be their current listings. + List sellallDetails = + isOnline ? + rankPlayer.getSellAllMultiplierListings() : + rankPlayer.getSellallMultipliers(); + + for (String sellallDetail : sellallDetails) { - msgs.add( " " + sellallDetail ); + msgs.add( " " + sellallDetail + (!isOnline ? " " + + messageNotAccurrate : "") ); } @@ -1831,51 +1675,12 @@ public void rankPlayer(CommandSender sender, msgs.add( " &7Blocks By Type&8:" ); msgs.addAll( Text.formatTreeMapStats(cPlayer.getBlocksByType(), 3 ) ); - - -// Set keysEarnings = cPlayer.getEarningsByMine().keySet(); -// -// int count = 0; -// StringBuilder sbErn = new StringBuilder(); -// for ( String earningKey : keysEarnings ) -// { -// Double mineEarnings = cPlayer.getEarningsByMine().get( earningKey ); -// -// String earnings = PlaceholdersUtil.formattedKmbtSISize( mineEarnings, dFmt, " " ); -// -// sbErn.append( String.format( "%s %s ", earningKey, earnings ) ); -// -// if ( count++ % 5 == 0 ) { -// msgs.add( String.format( -// " " + sbErn.toString() ) ); -// sbErn.setLength( 0 ); -// -// } -// } -// -// if ( sbErn.length() > 0 ) { -// -// msgs.add( String.format( -// " " + sbErn.toString() ) ); -// } - - - -// msgs.add( String.format( -// " " ) ); -// -// cPlayer.getEarningsByMine() - } - - - sendToPlayerAndConsole( sender, msgs ); - if ( sender.hasPermission("ranks.admin") ) { // This is admin-exclusive content @@ -1901,33 +1706,29 @@ public void rankPlayer(CommandSender sender, msgPlayerPerms, (isOp ? " " + ranksPlayerOpMsg() : ""), (isPlayer ? " " + ranksPlayerPlayerMsg() : ""), - (isOnline ? " " + ranksPlayerOnlineMsg() : " " + ranksPlayerOfflineMsg()), - (isPrisonOfflineMcPlayer ? " " + ranksPlayerPrisonOfflinePlayerMsg() : - (isPrisonPlayer ? " " + ranksPlayerPrisonPlayerMsg() : "")) + (isOnline ? " " + ranksPlayerOnlineMsg() : " " + ranksPlayerOfflineMsg()) ) ); if ( !isOnline ) { sendToPlayerAndConsole( sender, ranksPlayerPermsOfflineMsg() ); } - player.recalculatePermissions(); + rankPlayer.recalculatePermissions(); - List perms = player.getPermissions(); + List perms = rankPlayer.getPermissions(); listPermissions( sender, "bukkit", perms ); -// sendToPlayerAndConsole( sender, "### has perm prison.mines.a: " + -// player.hasPermission( "prison.mines.a" ) ); - - List permissionIntegrations = PrisonAPI.getIntegrationManager().getAllForType( IntegrationType.PERMISSION ); + List permissionIntegrations = + PrisonAPI.getIntegrationManager().getAllForType( IntegrationType.PERMISSION ); for ( Integration pIntegration : permissionIntegrations ) { if ( pIntegration instanceof PermissionIntegration ) { PermissionIntegration integrationPerms = (PermissionIntegration) pIntegration; - List iPerms = integrationPerms.getPermissions( player, true ); + List iPerms = integrationPerms.getPermissions( rankPlayer, true ); String permSource = integrationPerms.getDisplayName(); listPermissions( sender, permSource, iPerms ); @@ -1937,179 +1738,10 @@ public void rankPlayer(CommandSender sender, } } -// String nextRank = pm.getPlayerNextRankName( rankPlayer ); -// String nextRankCost = pm.getPlayerNextRankCost( rankPlayer ); -// -// String message = String.format("&c%s&7: Current Rank: &b%s&7", -// player.getDisplayName(), pm.getPlayerRankName( rankPlayer )); -// -// if ( nextRank.trim().length() == 0 ) { -// message += " It's the highest rank!"; -// } else { -// message += String.format(" Next rank: &b%s&7 &c$&b%s &7s%", -// nextRank, nextRankCost, currency ); -// } -// sender.sendMessage( message ); } -// else { -// ranksPlayerNoRanksFoundMsg( sender, player.getDisplayName() ); -// } } -// private String formatTimeMs( long timeMs ) { -// -// DecimalFormat iFmt = Prison.get().getDecimalFormatInt(); -// DecimalFormat tFmt = Prison.get().getDecimalFormat("00"); -//// SimpleDateFormat sdFmt = new SimpleDateFormat( "HH:mm:ss" ); -// -// long _sec = 1000; -// long _min = _sec * 60; -// long _hour = _min * 60; -// long _day = _hour * 24; -// -// long ms = timeMs; -// long days = _day < ms ? ms / _day : 0; -// -// ms -= (days * _day); -// long hours = _hour < ms ? ms / _hour : 0; -// -// ms -= (hours * _hour); -// long mins = _min < ms ? ms / _min : 0; -// -// ms -= (mins * _min); -// long secs = _sec < ms ? ms / _sec : 0; -// -// -// String results = -// (days == 0 ? "" : iFmt.format( days ) + "d ") + -// tFmt.format( hours ) + ":" + -// tFmt.format( mins ) + ":" + -// tFmt.format( secs ) -// ; -// -// return results; -// } - -// private void formatTreeMapStats( TreeMap statMap, List msgs, -// DecimalFormat dFmt, DecimalFormat iFmt, -// int columns ) { -// -// Set keysEarnings = statMap.keySet(); -// -// -// List values = new ArrayList<>(); -// List valueMaxLen = new ArrayList<>(); -// -// -// int count = 0; -// StringBuilder sb = new StringBuilder(); -// for ( String earningKey : keysEarnings ) -// { -// String value = null; -// Object valueObj = statMap.get( earningKey ); -// -// if ( valueObj instanceof Double ) { -// -// value = PlaceholdersUtil.formattedKmbtSISize( (Double) valueObj, dFmt, " &9" ); -// } -// else if ( valueObj instanceof Integer ) { -// int intVal = (Integer) valueObj; -// value = PlaceholdersUtil.formattedKmbtSISize( intVal, -// ( intVal < 1000 ? iFmt : dFmt ), " &9" ); -// } -// else if ( valueObj instanceof Long ) { -// -// value = Text.formatTimeDaysHhMmSs( (Long) valueObj ); -// } -// -// String msg = String.format( "&3%s&8: &b%s", earningKey, value ).trim(); -// -// String msgNoColor = Text.stripColor( msg ); -// int lenMNC = msgNoColor.length(); -// -// -// int col = values.size() % columns; -// values.add( msg ); -// -// if ( col >= valueMaxLen.size() || lenMNC > valueMaxLen.get( col ) ) { -// -// if ( col > valueMaxLen.size() - 1 ) { -// valueMaxLen.add( lenMNC ); -// } -// else { -// -// valueMaxLen.set( col, lenMNC ); -// } -// } -// } -// -// -// for ( int j = 0; j < values.size(); j++ ) -// { -// String msg = values.get( j ); -// -// int col = j % columns; -// -// int maxColumnWidth = col > valueMaxLen.size() - 1 ? -// msg.length() : -// valueMaxLen.get( col ); -// -// sb.append( msg ); -// -// // Pad the right of all content with spaces to align columns, up to a -// // given maxLength: -// String msgNoColor = Text.stripColor( msg ); -// int lenMNC = msgNoColor.length(); -// for( int i = lenMNC; i < maxColumnWidth; i++ ) { -// sb.append( " " ); -// } -// -// // The spacer: -// sb.append( " " ); -// -// if ( ++count % columns == 0 ) { -// msgs.add( String.format( -// " " + sb.toString() ) ); -// sb.setLength( 0 ); -// -// } -// } -// -// if ( sb.length() > 0 ) { -// -// msgs.add( String.format( -// " " + sb.toString() ) ); -// } -// -// -// } - - -//// @Command(identifier = "ranks playerInventory", permissions = "mines.set", -//// description = "For listing what's in a player's inventory by dumping it to console.", -//// onlyPlayers = false ) -// public void ranksPlayerInventoryCommand(CommandSender sender, -// @Arg(name = "player", def = "", description = "Player name") String playerName -// ) { -// -// Player player = getPlayer( sender, playerName ); -// -// if (player == null) { -// sender.sendMessage( "&3You must be a player in the game to run this command, and/or the player must be online." ); -// return; -// } -// -//// Player player = getPlayer( sender ); -//// -//// if (player == null || !player.isOnline()) { -//// sender.sendMessage( "&3You must be a player in the game to run this command." ); -//// return; -//// } -// -// player.printDebugInventoryInformationToConsole(); -// } -// private void listPermissions( CommandSender sender, String prefix, List perms ) { @@ -2175,35 +1807,21 @@ public void rankPlayers(CommandSender sender, "'All' includes all ranks including ones without players. " + "'Full includes player names if prison is tracking them. [players, all, full]") String action){ + + if ( !ladderName.equalsIgnoreCase( "all" ) && + PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ) == null ) { + ranksPlayersInvalidLadderMsg( sender, ladderName ); + return; + } + + + RanksByLadderOptions option = RanksByLadderOptions.fromString( action ); + if ( option == null ) { + ranksPlayersInvalidActionMsg( sender, action ); + return; + } - if ( !ladderName.equalsIgnoreCase( "all" ) && - PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ) == null ) { - ranksPlayersInvalidLadderMsg( sender, ladderName ); - return; - } - - - RanksByLadderOptions option = RanksByLadderOptions.fromString( action ); - if ( option == null ) { - ranksPlayersInvalidActionMsg( sender, action ); - return; - } - -// boolean includeAll = action.equalsIgnoreCase( "all" ); - PrisonRanks.getInstance().getRankManager().ranksByLadders( sender, ladderName, option ); - -// Output.get().logInfo( "Ranks by ladders:" ); -// -// for ( RankLadder ladder : PrisonRanks.getInstance().getLadderManager().getLadders() ) { -// if ( ladderName.equalsIgnoreCase( "all" ) || ladderName.equalsIgnoreCase( ladder.name ) ) { -// -// boolean includeAll = action.equalsIgnoreCase( "all" ); -// String ladderRanks = ladder.listAllRanks( includeAll ); -// -// sender.sendMessage( ladderRanks ); -// } -// -// } + PrisonRanks.getInstance().getRankManager().ranksByLadders( sender, ladderName, option ); } @@ -2230,236 +1848,282 @@ public void rankTopN(CommandSender sender, "Can use multiple options. " + "[alt archived forceReload stats debugSave]") String options ){ - int page = 1; - int pageSize = 10; - - if ( contains( "forceReload", pageNumber, pageSizeNumber, options ) ) { - - if ( sender.isOp() ) { - TopNPlayers.getInstance().forceReloadAllPlayers(); - ranksTopNPlayerForcedReloadSuccess( sender ); - } - else { - - ranksTopNPlayerForcedReloadFailure( sender ); - } - - } - - if ( contains( "debugSave", pageNumber, pageSizeNumber, options ) ) { - - if ( sender.isOp() ) { - TopNPlayers.getInstance().saveToJson(); - TopNPlayers.getInstance().loadSaveFile(); - ranksTopNPlayerDebugSaved( sender ); - } - } - - boolean alt = contains( "alt", pageNumber, pageSizeNumber, options ); -// if ( pageNumber.toLowerCase().contains("alt") || -// pageSizeNumber.toLowerCase().contains("alt") || -// options.toLowerCase().contains("alt") ) { -// alt = true; -// } - - // Since it's contains, "archive" will hit on archived, archives, etc... - boolean archived = contains( "archive", pageNumber, pageSizeNumber, options ); - -// boolean sort = contains( "sort", pageNumber, pageSizeNumber, options ); - - int topNSize = TopNPlayers.getInstance().getTopNSize(); - boolean loading = TopNPlayers.getInstance().isLoading(); - int archivedSize = TopNPlayers.getInstance().getArchivedSize(); - - - if ( contains( "stats", pageNumber, pageSizeNumber, options ) ) { - - sender.sendMessage( TopNPlayers.getInstance().getTopNStats() ); - } - - - try { - page = Integer.parseInt(pageNumber); - } - catch (NumberFormatException e ) { - // Ignore: will use defaults - } - try { - pageSize = Integer.parseInt(pageSizeNumber); - } - catch (NumberFormatException e ) { - // Ignore: will use defaults - } - - if ( page <= 0 ) { - page = 1; - } - if ( pageSize <= 0 ) { - pageSize = 10; - } - - int totalPlayers = - archived ? - archivedSize : - topNSize; - -// int totalPlayers = PrisonRanks.getInstance().getPlayerManager().getPlayers().size(); - int totalPages = (totalPlayers / pageSize) + (totalPlayers % pageSize == 0 ? 0 : 1); + int page = 1; + int pageSize = 10; + + if ( contains( "forceReload", pageNumber, pageSizeNumber, options ) ) { + + if ( sender.isOp() ) { + TopNPlayers.getInstance().forceReloadAllPlayers(); + ranksTopNPlayerForcedReloadSuccess( sender ); + } + else { + + ranksTopNPlayerForcedReloadFailure( sender ); + } + + } - if ( page > 1 && totalPages > 1 && page > totalPages ) { - page = totalPages; - } + if ( contains( "debugSave", pageNumber, pageSizeNumber, options ) ) { + + if ( sender.isOp() ) { + TopNPlayers.getInstance().saveToJson(); + TopNPlayers.getInstance().loadSaveFile(); + ranksTopNPlayerDebugSaved( sender ); + } + } + + boolean alt = contains( "alt", pageNumber, pageSizeNumber, options ); + + // Since it's contains, "archive" will hit on archived, archives, etc... + boolean archived = contains( "archive", pageNumber, pageSizeNumber, options ); + + + int topNSize = TopNPlayers.getInstance().getTopNSize(); + boolean loading = TopNPlayers.getInstance().isLoading(); + int archivedSize = TopNPlayers.getInstance().getArchivedSize(); + + + if ( contains( "stats", pageNumber, pageSizeNumber, options ) ) { + + sender.sendMessage( TopNPlayers.getInstance().getTopNStats() ); + } + + + try { + page = Integer.parseInt(pageNumber); + } + catch (NumberFormatException e ) { + // Ignore: will use defaults + } + try { + pageSize = Integer.parseInt(pageSizeNumber); + } + catch (NumberFormatException e ) { + // Ignore: will use defaults + } + + if ( page <= 0 ) { + page = 1; + } + if ( pageSize <= 0 ) { + pageSize = 10; + } + + int totalPlayers = + archived ? + archivedSize : + topNSize; + + int totalPages = (totalPlayers / pageSize) + (totalPlayers % pageSize == 0 ? 0 : 1); + + if ( page > 1 && totalPages > 1 && page > totalPages ) { + page = totalPages; + } + + int posStart = (page - 1) * pageSize; + int posEnd = posStart + pageSize; + + + String header = alt ? + RankPlayer.printRankScoreLine2Header() : + RankPlayer.printRankScoreLine1Header(); + sender.sendMessage( header ); + + if ( loading ) { + sender.sendMessage( "&3(Loading TopN List - Please Wait)" ); + } + + + for ( int i = posStart; i < posEnd; i++ ) { + + RankPlayer rPlayer = + archived ? + TopNPlayers.getInstance().getTopNRankArchivedPlayer( i ) : + TopNPlayers.getInstance().getTopNRankPlayer( i ); + + + if ( rPlayer != null ) { + + String message = alt ? + rPlayer.printRankScoreLine2( i + 1 ) : + rPlayer.printRankScoreLine1( i + 1 ); + + sender.sendMessage(message); + } + } - int posStart = (page - 1) * pageSize; - int posEnd = posStart + pageSize; - -// DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); - -// if ( sort ) { -// -// if ( sender.isOp() || !sender.isPlayer() ) { -// -//// PrisonRanks.getInstance().getPlayerManager().sortPlayerByTopRanked(); -//// PrisonRanks.getInstance().getPlayerManager().sortPlayerByTopRankedNoRankScoreUpdate(); -// sender.sendMessage( "&3Sorting has been submitted." ); -// } -// else { -// sender.sendMessage( "&3Only admins can force a sorting of the topn players." ); -// -// } -// -// } + } + + + + + @Command(identifier = "prison support fileNameReports", + description = "&3This command will run one of two reports that will show " + + "the old file format on the left, and the new format on the " + + "right. This can be useful to lookup players under the old " + + "file name format. The new report is based upon the user's name " + + "so as to be visually identifiable to a specific player. " + +// description = "&3This command will run a task that will check both the " + +// "Player Rank files and the Player Cache files to see if " + +// "they are using an old naming format. If they are, then the " + +// "files are renamed to the new format. This command can be " + +// "ran multiple times, since nothing will be changed if the " + +// "file names have already been converted." + +// "{br}" + +// "&3Inorder to use the new naming formats, the 'config.yml' must " + +// "contain the boolean property " + +// "'prison-ranks.use-friendly-user-file-name' with a value of " + +// "true. Failure to both set that to a value of true, and " + +// "to run this updater may lead to possible player data corruption." + + "" + + "" + + "{br}" + + "&3The new format for player-based file names includes the " + + "player's name, and uses a UUID fragment that is actually " + + "bedrock friendly. The UUID parts that are used, are the " + + "first eight digits of the UUID, plus the last 12. Bedrock " + + "UUIDs can have first 16 to 20 digits being all zeros, which " + + "could result in ambiguous file names where all bedrock players " + + "would have the same prefix. The whole point of only using the " + + "first eight hex digits was that they would have still be all " + + "unique.{br} " + + "Note: This command was intended originally to provide the conversion " + + "to the newer file names, but prison was modified to be more intelligent " + + "in being able to identify which format is being used, and then also " + + "automatically update each file when saved again. Both old nad new file " + + "name formats can exist at the same time, especially for players, but " + + "when their status updates, then the file will be upgraded. If the player " + + "never logs back on to the system, it will never trigger an update. So " + + "use this report to identify players that may not be converted.", + onlyPlayers = false, permissions = "prison.debug" ) + public void supportPlayerFileNameUpdateCmd(CommandSender sender, + @Arg(name = "action", def = "player", + description = "Run the player report. Default: 'player'. [cache, player]") +// description = "Only shows the PrisonSystemStatus for the " +// + "'PlayerFileNameUpdate' and will not try to run the " +// + "update. Default: 'status'. [status, run, cache, player]") + String action, + @Arg(name = "page", def = "1", + description = "If a report of 'cache' or 'player', then page is used if there " + + "are more than 25 players. Default = 1. Valid values 1 and higher. [ >= 1]" ) + int page + ) { + ReportMode reportMode = ReportMode.fromString( action ); + // Get the PrisonSystemSettings for the PlayerFileNameUpdate and format the results: + PlayerNewFileNameCheckAsyncTask task = new PlayerNewFileNameCheckAsyncTask(); + + if ( reportMode == ReportMode.cache || reportMode == ReportMode.players ) { + + task.playerConverterReport( reportMode, page ); + } - -// List topN = PrisonRanks.getInstance().getPlayerManager().getTopNPlayers().getTopNList(); + } + + - String header = alt ? - RankPlayer.printRankScoreLine2Header() : - RankPlayer.printRankScoreLine1Header(); - sender.sendMessage( header ); - - if ( loading ) { - sender.sendMessage( "&3(Loading TopN List - Please Wait)" ); - } - + @Command(identifier = "ranks reload players", + description = "Reloads all players. Use at your own risk. Prison is not responsible " + + "if player save files are manually changed, replaced, modified in anyway. " + + "Actual impact of reloading players is not 100% predictable, but " + + "should be safe under most conditions. Before making any manual changes to " + + "any prison file, please run `/prison support backup save help` and make a backup " + + "copy of prison's settings.", + aliases = "prison reload players", + onlyPlayers = false, permissions = "ranks.set") + public void reloadPlayersCmd(CommandSender sender ){ + + + try { + PrisonRanks.getInstance().getPlayerManager().reloadAllPlayers(); + + String msg = String.format( + "&3Reload Players: Successful. Maybe..." ); + + sender.sendMessage(msg); + + } + catch (IOException e) { + String msg = String.format( + "&cReload Players: Failed. [%s]", + e.getMessage() ); + + sender.sendMessage(msg); + } + } + + + @Command(identifier = "ranks reload ranksLaddersAndPlayers", + description = "Reloads all Ranks and then Ladders. Also reloads players too so they are " + + "properly hooked in to the newly loaded ranks and ladders. " + + "Use at your own risk. Prison is not responsible " + + "if rank and ladder save files are manually changed, replaced, modified in anyway. " + + "Actual impact of reloading ladders and ranks are not 100% predictable, but " + + "should be safe under most conditions. Before making any manual changes to " + + "any prison file, please run `/prison support backup save help` and make a backup " + + "copy of prison's settings.", + aliases = "prison reload ranksLaddersAndPlayers", + onlyPlayers = false, permissions = "ranks.set") + public void reloadLaddersAndRanksCmd(CommandSender sender ){ - for ( int i = posStart; i < posEnd; i++ ) { - - RankPlayer rPlayer = - archived ? - TopNPlayers.getInstance().getTopNRankArchivedPlayer( i ) : - TopNPlayers.getInstance().getTopNRankPlayer( i ); - - -// PrisonRanks.getInstance().getPlayerManager().getTopNRankPlayer( i ); - - if ( rPlayer != null ) { - - String message = alt ? - rPlayer.printRankScoreLine2( i + 1 ) : - rPlayer.printRankScoreLine1( i + 1 ); - - sender.sendMessage(message); - } - } - + PrisonRanks.getInstance().reloadRanksAndLadders(); + + String msg = String.format( + "&3Reload ranks, ladders and players: Successful. Maybe..." ); + + sender.sendMessage(msg); } - private boolean contains( String search, String... values ) { - boolean results = false; - - if ( search != null && values != null ) { - - search = search.trim().toLowerCase(); - - for (String val : values) { + boolean results = false; + + if ( search != null && values != null ) { + + search = search.trim().toLowerCase(); + + for (String val : values) { if ( val.toLowerCase().contains(search) ) { results = true; break; } - } - } - - return results; + } + } + + return results; } -// /** -// * This function is just an arbitrary test to access the various components. -// * -// * @param sender -// * @param playerName -// */ -// @Command( identifier = "ranks test", onlyPlayers = false, permissions = "prison.admin" ) -// public void prisonModuleTest(CommandSender sender, -// @Arg(name = "player", def = "", description = "Player name") String playerName){ -// -// ModuleManager modMan = Prison.get().getModuleManager(); -// Module module = modMan == null ? null : modMan.getModule( PrisonRanks.MODULE_NAME ).orElse( null ); -// -// int moduleCount = (modMan == null ? 0 : modMan.getModules().size()); -// sender.sendMessage(String.format( "prisonModuleTest: prison=%s moduleManager=%s " + -// "registeredModules=%s PrisonRanks=%s", -// (Prison.get() == null ? "null" : "active"), -// (Prison.get().getModuleManager() == null ? "null" : "active"), -// Integer.toString( moduleCount ), -// (modMan.getModule( PrisonRanks.MODULE_NAME ) == null ? "null" : "active") -// ) ); -// -// if ( module == null || !(module instanceof PrisonRanks) ) { -// -// sender.sendMessage( "prisonModuleTest: Cannot get PrisonRanks. Terminating" ); -// return; -// } -// -// -// PrisonRanks rankPlugin = (PrisonRanks) module; -// -// if ( rankPlugin == null || rankPlugin.getPlayerManager() == null ) { -// sender.sendMessage( "prisonModuleTest: PrisonRanks could not be created. Terminating" ); -// return; -// } -// -// -// PlayerManager playerManager = rankPlugin.getPlayerManager(); -// Player player = getPlayer( sender, playerName ); -// -// sender.sendMessage( String.format( "prisonModuleTest: PlayerManager=%s player=%s sender=%s playerName=%s", -// (playerManager == null ? "null" : "active"), (player == null ? "null" : player.getName()), -// (sender == null ? "null" : sender.getName()), (playerName == null ? "null" : playerName) -// )); -// -// -// if ( player == null ) { -// sender.sendMessage( "prisonModuleTest: Cannot get a valid player. " + -// "If console, must supply a valid name. Terminating" ); -// return; -// } -// -// RankPlayer rPlayer = playerManager.getPlayer( player.getUUID() ).orElse( null ); -// LadderManager lm = rankPlugin.getLadderManager(); -// -// for ( RankLadder ladderData : lm.getLadders() ) { -// Rank playerRank = rPlayer == null ? null : rPlayer.getRank( ladderData ).orElse( null ); -// Rank rank = ladderData.getLowestRank().orElse( null ); -// -// while ( rank != null ) { -// boolean playerHasThisRank = playerRank != null && playerRank.equals( rank ); -// -// sender.sendMessage(String.format( "prisonModuleTest: ladder=%s rank=%s playerRank=%s hasRank=%s", -// ladderData.name, rank.name, (playerRank == null ? "null" : playerRank.name ), -// Boolean.valueOf( playerHasThisRank ).toString() -// )); -// -// rank = rank.rankNext; -// } -// } -// } + /** + *

    This gets the RankPlayer for the given UUID or playerName. The 'sender' generally is the + * console, or an admin that is trying to run the command for a player. + * So although the sender has a 'getRankPlayer()' function, it may be for the wrong player. + *

    + * + *

    If both the uuid and playerName are either null or empty, then if the sender + * is a player, then get the RankPlayer from the sender. + *

    + * + * @param sender The one who should get an messages, but is not the one for RankPlayer. + * @param playerUuid + * @param playerName + * @return + */ + public RankPlayer getRankPlayer( CommandSender sender, UUID playerUuid, String playerName ) { + + // If player name and uuid are both empty or null, and if sender is a player, + // then get the RankPlayer from the sender: + if ( (playerName == null || playerName.trim().length() == 0) && + playerUuid == null && sender.isPlayer() ) { + return sender.getRankPlayer(); + } + + RankPlayer player = PrisonRanks.getInstance().getPlayerManager().getPlayer(playerUuid, playerName); + return player; + } } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommandsMessages.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommandsMessages.java index 67fbf342f..87b3a9d85 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommandsMessages.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommandsMessages.java @@ -142,16 +142,16 @@ protected void autoConfigLadderRankCostMultiplierInfoMsg( CommandSender sender, DecimalFormat dFmt = Prison.get().getDecimalFormat("0.0000"); PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankCommands__auto_config_ladder_rank_cost_multiplier_info" ) - .withReplacements( - dFmt.format( rankCostMultiplier ) ) - .sendTo( sender ); + .getLocalizable( "ranks_rankCommands__auto_config_ladder_rank_cost_multiplier_info" ) + .withReplacements( + dFmt.format( rankCostMultiplier ) ) + .sendTo( sender ); } protected void autoConfigLadderRankCostMultiplierCmdMsg( CommandSender sender ) { PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankCommands__auto_config_ladder_rank_cost_multiplier_command_example" ) - .sendTo( sender ); + .getLocalizable( "ranks_rankCommands__auto_config_ladder_rank_cost_multiplier_command_example" ) + .sendTo( sender ); } protected void autoConfigRanksCreatedMsg( CommandSender sender, @@ -682,4 +682,18 @@ protected void ranksTopNPlayerDebugSaved( CommandSender sender ) { } + + protected void ranksRankupFailureToGetRankPlayerMsg( CommandSender sender ) { + PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankup__rankup_failure_to_get_rankplayer" ) + .sendTo( sender ); + } + + + protected void rankupInvalidPlayerNameMsg(CommandSender sender, String playerName) { + PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankup__invalid_player_name" ) + .withReplacements( playerName ) + .sendTo(sender); + } } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommandsPerms.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommandsPerms.java index 68cff60fe..00d8cfa21 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommandsPerms.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/commands/RanksCommandsPerms.java @@ -17,315 +17,7 @@ public RanksCommandsPerms( String cmdGroup ) { } -// @Command(identifier = "ranks perms list", description = "Lists rank permissions", -// onlyPlayers = false, permissions = "ranks.set") -// public void rankPermsList(CommandSender sender, -// @Arg(name = "rankName") String rankName -// ){ -// sender.sendMessage( "&cWarning: &3This feature is not yet functional." ); -// -// Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); -// if ( rank == null ) { -// rankDoesNotExistMsg( sender, rankName ); -// return; -// } -// -// -// if ( rank.getPermissions() == null ||rank.getPermissions().size() == 0 && -// rank.getPermissionGroups() == null && rank.getPermissionGroups().size() == 0 ) { -// -// Output.get().sendInfo(sender, "The Rank '%s' contains no permissions or " + -// "permission groups.", rank.getName()); -// return; -// } -// -// RankLadder ladder = rank.getLadder(); -// -// ChatDisplay display = new ChatDisplay("Rank Permissions and Groups for " + rank.getName()); -// display.addText("&8Click a Permission to remove it."); -// BulletedListComponent.BulletedListBuilder builder = -// new BulletedListComponent.BulletedListBuilder(); -// -// listLadderPerms( ladder, builder ); -// -// int rowNumber = 1; -// -// if ( rank.getPermissions().size() > 0 ) { -// builder.add( "&7Permissions:" ); -// } -// for (String perm : rank.getPermissions() ) { -// -// RowComponent row = new RowComponent(); -// -// row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); -// -// FancyMessage msgPermission = new FancyMessage( String.format( "&7%s ", perm ) ) -// .command( "/ranks perms edit " + rank.getName() + " " + rowNumber + " " ) -// .tooltip("Permission - Click to Edit"); -// row.addFancy( msgPermission ); -// -// -// FancyMessage msgRemove = new FancyMessage( String.format( " &cRemove " ) ) -// .command( "/ranks perms remove " + rank.getName() + " " + rowNumber + " " ) -// .tooltip("Remove Permission - Click to Delete"); -// row.addFancy( msgRemove ); -// -// builder.add( row ); -// } -// -// if ( rank.getPermissionGroups().size() > 0 ) { -// builder.add( "&7Permission Groups:" ); -// } -// for (String permGroup : rank.getPermissionGroups() ) { -// -// RowComponent row = new RowComponent(); -// -// row.addTextComponent( " &3Row: &d%d ", rowNumber++ ); -// -// FancyMessage msgPermission = new FancyMessage( String.format( "&7%s ", permGroup ) ) -// .command( "/ranks perms edit " + rank.getName() + " " + rowNumber + " " ) -// .tooltip("Permission Group - Click to Edit"); -// row.addFancy( msgPermission ); -// -// -// FancyMessage msgRemove = new FancyMessage( String.format( " &cRemove " ) ) -// .command( "/ranks perms remove " + rank.getName() + " " + rowNumber + " " ) -// .tooltip("Remove Permission Group - Click to Delete"); -// row.addFancy( msgRemove ); -// -// builder.add( row ); -// } -// -// -// display.addComponent(builder.build()); -// display.addComponent(new FancyMessageComponent( -// new FancyMessage("&7[&a+&7] Add Permission") -// .suggest("/ranks perms addPerm " + rank.getName() + " [perm] /") -// .tooltip("&7Add a new Permission."))); -// display.addComponent(new FancyMessageComponent( -// new FancyMessage("&7[&a+&7] Add Permission Group") -// .suggest("/ranks perms addPermGroup " + rank.getName() + " [permGroup] /") -// .tooltip("&7Add a new Permission Group."))); -// -// display.send(sender); -// -// } - -// private void listLadderPerms( RankLadder ladder, -// BulletedListComponent.BulletedListBuilder builder ) { -// -// if ( ladder.getPermissions().size() > 0 ) { -// builder.add( "&3Ladder &7%s &3Permissions:", ladder.getName() ); -// } -// for (String perm : ladder.getPermissions() ) { -// -// RowComponent row = new RowComponent(); -// -// row.addTextComponent( " " ); -// -// FancyMessage msgPermission = new FancyMessage( String.format( "&7%s ", perm ) ) -// .command( "/ranks ladder perms list " + ladder.getName() ) -// .tooltip("Ladder Permission - Click to List Ladder"); -// row.addFancy( msgPermission ); -// -// builder.add( row ); -// } -// -// if ( ladder.getPermissionGroups().size() > 0 ) { -// builder.add( "&3Ladder &7%s &3Permission Groups:", ladder.getName() ); -// } -// for (String permGroup : ladder.getPermissionGroups() ) { -// -// RowComponent row = new RowComponent(); -// -// row.addTextComponent( " " ); -// -// FancyMessage msgPermission = new FancyMessage( String.format( "&7%s ", permGroup ) ) -// .command( "/ranks ladder perms list " + ladder.getName() ) -// .tooltip("Ladder Permission Group - Click to List Ladder"); -// row.addFancy( msgPermission ); -// -// builder.add( row ); -// } -// -// } - - -// @Command(identifier = "ranks perms addPerm", -// description = "Add a ladder permission. Valid placeholder: {rank}.", -// onlyPlayers = false, permissions = "ranks.set") -// public void rankPermsAddPerm(CommandSender sender, -// @Arg(name = "rankName", -// description = "Rank name to add the permission to.") String rankName, -// @Arg(name = "permission", description = "Permission") String permission -// ){ -// -// sender.sendMessage( "&cWarning: &3This feature is not yet functional." ); -// -// Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); -// if ( rank == null ) { -// rankDoesNotExistMsg( sender, rankName ); -// return; -// } -// -// -// if ( permission == null || permission.trim().isEmpty() ) { -// -// Output.get().sendInfo(sender, "&3The &7permission &3parameter is required." ); -// return; -// } -// -// -// if ( rank.hasPermission( permission ) ) { -// -// Output.get().sendInfo(sender, "&3The permission &7%s &3already exists.", permission ); -// return; -// } -// -// rank.getPermissions().add( permission ); -// -// -// PrisonRanks.getInstance().getRankManager().saveRank(rank); -// -// Output.get().sendInfo(sender, "&3The permission &7%s &3was successfully added " + -// "to the rank &7%s&3.", permission, rank.getName() ); -// -// rankPermsList( sender, rank.getName() ); -// } - - -// @Command(identifier = "ranks perms addGroup", -// description = "Add a ladder permission. Valid placeholder: {rank}.", -// onlyPlayers = false, permissions = "ranks.set") -// public void rankPermsAddPermGroup(CommandSender sender, -// @Arg(name = "rankName", -// description = "Rank name to add the permission to.") String rankName, -// @Arg(name = "permissionGroup", description = "Permission Group") String permissionGroup -// ){ -// -// sender.sendMessage( "&cWarning: &3This feature is not yet functional." ); -// -// Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); -// if ( rank == null ) { -// rankDoesNotExistMsg( sender, rankName ); -// return; -// } -// -// -// if ( permissionGroup == null || permissionGroup.trim().isEmpty() ) { -// -// Output.get().sendInfo(sender, "&3The &7permission group &3parameter is required." ); -// return; -// } -// -// -// if ( rank.hasPermissionGroup( permissionGroup ) ) { -// -// Output.get().sendInfo(sender, "&3The permission Group &7%s &3already exists.", permissionGroup ); -// return; -// } -// -// rank.getPermissionGroups().add( permissionGroup ); -// -// -// PrisonRanks.getInstance().getRankManager().saveRank(rank); -// -// Output.get().sendInfo(sender, "&3The permission group &7%s &3was successfully added " + -// "to the rank &7%s&3.", permissionGroup, rank.getName() ); -// -// rankPermsList( sender, rank.getName() ); -// } - - - -// @Command(identifier = "ranks perms remove", description = "Remove rank permissions", -// onlyPlayers = false, permissions = "ranks.set") -// public void rankPermsRemove(CommandSender sender, -// @Arg(name = "rankName", def = "default", -// description = "Rank name to list the permissions.") String rankName, -// @Arg(name = "row") Integer row -// ){ -// sender.sendMessage( "&cWarning: &3This feature is not yet functional." ); -// -// -// Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); -// if ( rank == null ) { -// rankDoesNotExistMsg( sender, rankName ); -// return; -// } -// -// -// boolean dirty = false; -// String removedPerm = ""; -// boolean permGroup = false; -// -// if ( row == null || row <= 0 ) { -// sender.sendMessage( -// String.format("&7Please provide a valid row number greater than zero. " + -// "Was row=[&b%d&7]", -// (row == null ? "null" : row) )); -// return; -// } -// -// if ( row <= rank.getPermissions().size() ) { -// removedPerm = rank.getPermissions().remove( row - 1 ); -// dirty = true; -// } -// else { -// // Remove from row the size of permissions so the row will align to the permissionGroups. -// row -= rank.getPermissions().size(); -// -// if ( row <= rank.getPermissionGroups().size() ) { -// -// removedPerm = rank.getPermissions().remove( row - 1 ); -// dirty = true; -// permGroup = true; -// } -// } -// -// if ( dirty ) { -// PrisonRanks.getInstance().getRankManager().saveRank(rank); -// -// Output.get().sendInfo(sender, "&3The permission%s &7%s &3was successfully removed " + -// "to the rank &7%s&3.", -// ( permGroup ? " group" : "" ), -// removedPerm, rank.getName() ); -// -// } -// else { -// Output.get().sendInfo(sender, "&3The permission on row &7%s &3was unable to be removed " + -// "from the &7%s &3rank. " + -// "Is that a valid row number?", -// Integer.toString( row ), rank.getName() ); -// } -// } - - // @Command(identifier = "ranks playerInventory", permissions = "mines.set", - // description = "For listing what's in a player's inventory by dumping it - // to console.", - // onlyPlayers = false ) -// public void ranksPlayerInventoryCommand( CommandSender sender, -// @Arg( name = "player", def = "", description = "Player name" ) String playerName ) -// { -// -// Player player = getPlayer( sender, playerName ); -// -// if ( player == null ) -// { -// sender.sendMessage( "&3You must be a player in the game to run this command, and/or the player must be online." ); -// return; -// } -// -// // Player player = getPlayer( sender ); -// // -// // if (player == null || !player.isOnline()) { -// // sender.sendMessage( "&3You must be a player in the game to run this -// // command." ); -// // return; -// // } -// -// player.printDebugInventoryInformationToConsole(); -// } - + // NOTE: All of the commented out code has been purged. + // Please see the history in github for what was removed. } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/PrisonSortableLaddersRanks.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/PrisonSortableLaddersRanks.java index 249b17093..14ba051f9 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/PrisonSortableLaddersRanks.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/PrisonSortableLaddersRanks.java @@ -11,7 +11,6 @@ public class PrisonSortableLaddersRanks extends PrisonSorter { - @Override public Set getSortedSet() { @@ -39,16 +38,11 @@ public Set getSortedSet() for ( RankLadder rankLadder : ladders ) { List rankList = rankLadder.getRanks(); - // Perform the sort of the ranks: -// ranksSorted.addAll( rankList ); - // Add the ranks to the result set in sorted order: results.addAll( rankList ); -// results.addAll( ranksSorted ); // Remove from the unsortedRanks list, all ranks that were used: unsortedRanks.removeAll( rankList ); -// unsortedRanks.removeAll( ranksSorted ); } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankFactory.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankFactory.java index 127610aac..29ff4bbe0 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankFactory.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankFactory.java @@ -19,8 +19,6 @@ public Rank createRank( Document document ) try { - // Object pos = document.get("position"); - // this.position = RankUtil.doubleToInt( pos == null ? 0.0d : pos ); int id = ConversionUtil.doubleToInt( document.get( "id" ) ); String name = (String) document.get( "name" ); @@ -46,8 +44,6 @@ public Rank createRank( Document document ) } } - // This was allowing nulls to be added to the live commands... - // this.rankUpCommands = (List) cmds; } rank.getMines().clear(); @@ -59,33 +55,6 @@ public Rank createRank( Document document ) rank.setMineStrings( mineStrings ); } - // getPermissions().clear(); - // Object perms = document.get( "permissions" ); - // if ( perms != null ) { - // List permissions = (List) perms; - // for ( String permission : permissions ) { - // getPermissions().add( permission ); - // } - // } - // - // - // getPermissionGroups().clear(); - // Object permsGroups = document.get( "permissionGroups" ); - // if ( perms != null ) { - // List permissionGroups = (List) permsGroups; - // for ( String permissionGroup : permissionGroups ) { - // getPermissionGroups().add( permissionGroup ); - // } - // } - - -// // Hook up the ladder if it has not been setup yet: -// if ( rank.getLadder() == null ) { -// -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( rank ); -// -// rank.setLadder( ladder ); -// } } catch ( Exception e ) { @@ -102,8 +71,11 @@ public Rank createRank( Document document ) public Document toDocument( Rank rank ) { Document ret = new Document(); -// ret.put("position", this.position ); - ret.put("id", rank.getId()); + + if ( rank.getId() != -1 ) { + ret.put("id", rank.getId()); + } + ret.put("name", rank.getName() ); ret.put("tag", (rank.getTag() == null ? "none" : rank.getTag()) ); ret.put("cost", rank.getCost() ); @@ -128,12 +100,8 @@ public Document toDocument( Rank rank ) { } ret.put("mines", mineStrings); -// ret.put( "permissions", getPermissions() ); -// ret.put( "permissionGroups", getPermissionGroups() ); return ret; } - - } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadderFactory.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadderFactory.java index e3964f7cf..ce5e42c55 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadderFactory.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankLadderFactory.java @@ -4,27 +4,82 @@ import com.google.gson.internal.LinkedTreeMap; +import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.managers.RankManager; import tech.mcprison.prison.store.Document; import tech.mcprison.prison.util.ConversionUtil; + +/** + *

    Conversion of IDs: In general, IDs should not be used. The newer + * format of working with ranks and ladders, is that only the rank's name + * should be used to link ranks to ladders. It's a one way path, where only + * the ladders are saved with a group of ranks. A saved rank has no idea what + * ladder, if any, that it's tied to. + *

    + * + *

    The conversion process is simple and does not have to be concerned with + * reverting back to using IDs or adding an id when it has a value of -1. + * The only thing that will change is that new ranks and ladders will be given + * an id of -1. If upon saving an id is -1, then it will not be included in the + * save file. If a rank or ladder already has an id, it will not be changed and + * it will be continually saved with the rank and ladder. + *

    + * + *

    The only real "conversion" process is when ladders are loaded, and if a + * rank does not have a name, then it will be joined by the id, then when + * the ladder is fully loaded, it will be resaved, thus dropping the rank + * ids within the ladder's save file. + *

    + * + *

    Ranks are always loaded before ladders. + *

    + * + */ public class RankLadderFactory { + public RankLadderFactory() { + super(); + + } + + /** + *

    This function loads a ladder from a save file. + *

    + * + *

    For conversion to eliminating IDs, if a rank or a ladder has an + * id, then keep it for now. If a rank was saved in the ladder without a + * name, then the ladder needs to be resaved, after loading all ranks + * so the ids won't be saved with the new format. If a rank name is not + * loaded, then the ids will be used to connect the ranks to the ladder. + * Otherwise the name will be used. + *

    + * + *

    No special processing needs to be used in the loading of the ladder, + * except to track when a rank does not have a name to trigger a resave at + * the end of the loading process by setting 'isDirty' to true. + *

    + * + * + * @param document + * @param rankManager + * @return + */ @SuppressWarnings( "unchecked" ) - public RankLadder createRankLadder(Document document, PrisonRanks prisonRanks) { + public RankLadder createRankLadder(Document document, RankManager rankManager) { RankLadder rankLadder = null; boolean isDirty = false; + + // If an "id" field is not found, doubleToInt will now return a -1. int id = ConversionUtil.doubleToInt(document.get("id")); String name = (String) document.get("name"); rankLadder = new RankLadder( id, name ); - RankManager rankManager = prisonRanks.getRankManager(); - if ( rankManager == null ) { RankMessages rMessages = new RankMessages(); @@ -33,59 +88,98 @@ public RankLadder createRankLadder(Document document, PrisonRanks prisonRanks) { return null; } - List> ranksLocal = - (List>) document.get("ranks"); + List> ranksLocal = + (List>) document.get("ranks"); - rankLadder.getRankUpCommands().clear(); - Object cmds = document.get("commands"); - if ( cmds != null ) { + rankLadder.getRankUpCommands().clear(); + Object cmds = document.get("commands"); + if ( cmds != null ) { - List commands = (List) cmds; - for ( String cmd : commands ) { - if ( cmd != null ) { - rankLadder.getRankUpCommands().add( cmd ); - } + List commands = (List) cmds; + for ( String cmd : commands ) { + if ( cmd != null ) { + rankLadder.getRankUpCommands().add( cmd ); } - - // This was allowing nulls to be added to the live commands... -// this.rankUpCommands = (List) cmds; } + + } -// rankLadder.ranks = new ArrayList<>(); // already initialized - for (LinkedTreeMap rank : ranksLocal) { - - + for (LinkedTreeMap rank : ranksLocal) { + + if ( rank == null ) { + + // Force a resave to "fix" the problem? + isDirty = true; + + Output.get().logInfo( "RankLadderFactory.createRankLadder: " + + "A loaded rank was null, and is skipping it. Since it" + + "was null, there is no way to identify what it was. " + + "This notice is to inform you and to prevent Prison from " + + "failing to load."); + + continue; + } + // The only real field that is important here is rankId to tie the // rank back to this ladder. Name helps clarify the contents of the // Ladder file. int rRankId = ConversionUtil.doubleToInt((rank.get("rankId"))); String rRankName = (String) rank.get( "rankName" ); - Rank rankPrison = rankManager.getRank( rRankId ); + Rank rankPrison = null; + if ( rRankId != -1 ) { + // the file was saved with rankIds, so resave to remove them: + isDirty = true; + } + + if ( rRankName == null || rRankName.trim().length() == 0 ) { + + // NOTICE: Loading an older save file that has not been converted + // yet. No name was saved, so link with id and then set + // isDirty to true. + isDirty = true; + + rankPrison = rankManager.getRank( rRankId ); + + } + else { + // Load rank by name: + rankPrison = rankManager.getRank( rRankName ); + + } + + if ( rankPrison != null && rankPrison.getLadder() != null ) { - RankMessages rMessages = new RankMessages(); - rMessages.rankFailureLoadingDuplicateRankMsg( - rankPrison.getName(), rankPrison.getLadder().getName(), - rankLadder.getName() ); - + if ( rankPrison.getLadder().equals( rankLadder ) ) { + // ignore: The selected rank is already on this ladder. + } + else { + + String msg = String.format( + "&4Loading ladder: %s Rank %s is already assigned to the %s ladder. " + + "You may need to manually move the rank if this is incorrect. ", + rankLadder.getName(), + rankPrison.getName(), + rankPrison.getLadder().getName() + ); + Output.get().logInfo( msg ); + + } + + isDirty = true; } else if ( rankPrison != null) { - + rankLadder.addRank( rankPrison ); - -// Output.get().logInfo( "RankLadder load : " + getName() + -// " rank= " + rankPrison.getName() + " " + rankPrison.getId() + -// ); + + // Output.get().logInfo( "RankLadder load : " + getName() + + // " rank= " + rankPrison.getName() + " " + rankPrison.getId() + + // ); -// // if null look it up from loaded ranks: -// if ( rRankName == null ) { -// rRankName = rankPrison.getName(); -// dirty = true; -// } } else { // Rank not found. Try to create it? The name maybe wrong. @@ -99,58 +193,37 @@ else if ( rankPrison != null) { rankLadder.addRank( newRank ); -// String message = String.format( -// "Loading RankLadder Error: A rank for %s was not found so it was " + -// "fabricated: %s id=%d tag=%s cost=%d", getName(), newRank.getName(), newRank.getId(), -// newRank.getTag(), newRank.getCost() ); -// Output.get().logError( message ); + // String message = String.format( + // "Loading RankLadder Error: A rank for %s was not found so it was " + + // "fabricated: %s id=%d tag=%s cost=%d", getName(), newRank.getName(), newRank.getId(), + // newRank.getTag(), newRank.getCost() ); + // Output.get().logError( message ); } - - } - -// this.maxPrestige = RankUtil.doubleToInt(document.get("maxPrestige")); + + } - Double rankCostMultiplier = (Double) document.get( "rankCostMultiplierPerRank" ); - rankLadder.setRankCostMultiplierPerRank( rankCostMultiplier == null ? 0 : rankCostMultiplier ); - Boolean applyRankCostMultiplierToLadder = (Boolean) document.get( "applyRankCostMultiplierToLadder" ); - if ( applyRankCostMultiplierToLadder != null ) { - - rankLadder.setApplyRankCostMultiplierToLadder( applyRankCostMultiplierToLadder ); - } - else { - rankLadder.setApplyRankCostMultiplierToLadder( true ); - isDirty = true; - } + Double rankCostMultiplier = (Double) document.get( "rankCostMultiplierPerRank" ); + rankLadder.setRankCostMultiplierPerRank( rankCostMultiplier == null ? 0 : rankCostMultiplier ); + + Boolean applyRankCostMultiplierToLadder = (Boolean) document.get( "applyRankCostMultiplierToLadder" ); + if ( applyRankCostMultiplierToLadder != null ) { + rankLadder.setApplyRankCostMultiplierToLadder( applyRankCostMultiplierToLadder ); + } + else { + rankLadder.setApplyRankCostMultiplierToLadder( true ); + isDirty = true; + } -// getPermissions().clear(); -// Object perms = document.get( "permissions" ); -// if ( perms != null ) { -// List permissions = (List) perms; -// for ( String permission : permissions ) { -// getPermissions().add( permission ); -// } -// } -// -// -// getPermissionGroups().clear(); -// Object permsGroups = document.get( "permissionGroups" ); -// if ( perms != null ) { -// List permissionGroups = (List) permsGroups; -// for ( String permissionGroup : permissionGroups ) { -// getPermissionGroups().add( permissionGroup ); -// } -// } - - if ( isDirty ) { - PrisonRanks.getInstance().getLadderManager().save( rankLadder ); - } + if ( isDirty ) { + PrisonRanks.getInstance().getLadderManager().save( rankLadder ); + } - return rankLadder; - } + return rankLadder; + } } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java index 542c3e799..5d465c5c8 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactory.java @@ -1,14 +1,19 @@ package tech.mcprison.prison.ranks.data; import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.TreeMap; import java.util.UUID; import com.google.gson.internal.LinkedTreeMap; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.cache.PlayerCachePlayerData; +import tech.mcprison.prison.file.JsonFileIO; +import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.ranks.FirstJoinHandlerMessages; import tech.mcprison.prison.ranks.PrisonRanks; @@ -20,53 +25,114 @@ public class RankPlayerFactory { + JsonFileIO jfIO = new JsonFileIO(); - @SuppressWarnings( "unchecked" ) - public RankPlayer createRankPlayer(Document document) { - RankPlayer rankPlayer = null; - - - UUID uuid = UUID.fromString((String) document.get("uid")); - - rankPlayer = new RankPlayer( uuid ); - - LinkedTreeMap ranksLocal = - (LinkedTreeMap) document.get("ranks"); -// LinkedTreeMap prestigeLocal = -// (LinkedTreeMap) document.get("prestige"); - -// LinkedTreeMap blocksMinedLocal = -// (LinkedTreeMap) document.get("blocksMined"); - - Object namesListObject = document.get( "names" ); - + @SuppressWarnings( "unchecked" ) + public RankPlayer createRankPlayer(Document document) { + RankPlayer rankPlayer = null; + + + String uuidStr = document.containsKey("uid") ? + (String) document.get("uid") : + document.containsKey("uuid") ? + (String) document.get("uuid") : + null; + + UUID uuid = UUID.fromString( uuidStr ); + + rankPlayer = new RankPlayer( uuid ); + + LinkedTreeMap ranksLocal = + (LinkedTreeMap) document.get("ranks"); + + LadderManager ladderManager = PrisonRanks.getInstance().getLadderManager(); + - for (String key : ranksLocal.keySet()) { + for (String key : ranksLocal.keySet()) { - int rankId = ConversionUtil.doubleToInt(ranksLocal.get(key)); - rankPlayer.getRanksRefs().put(key, rankId ); + Object rankObj = ranksLocal.get(key); - } - - - // Sets up the Ladder and Rank objects: - setupLadderRanks( rankPlayer ); - - - + if ( rankObj instanceof Double ) { + + // Example of this kind of data: + // "ranks": { + // "default": 2 + // }, + + + int rankId = ConversionUtil.doubleToInt( rankObj ); + + RankLadder ladder = ladderManager.getLadder( key ); + Rank rank = ladder.getRank( rankId ); + + // Setups up the rank for the player and recalculates all of the rank multipliers: + rankPlayer.addRank( rank ); + + } + else { + + // Example of this newer format of data: + // Note; rankId should always be -1 when using this format so ignore it. + // "ranks": { + // "default": { + // "ladderName": "default", + // "rankId": -1, + // "rankName": "C" + // } + // }, + + + // It's a json object: + // RankID should be obsolete, so use ladderName and rankName. + String json = rankObj.toString(); + RankPlayerFactoryDataRank rData = jfIO.fromString( json, RankPlayerFactoryDataRank.class ); + if ( rData != null ) { + String ladderName = rData.getLadderName(); + String rankName = rData.getRankName(); + + // Use of rankId is obsolete so ignore it: + int rankId = rData.getRankId(); + + + RankLadder ladder = ladderManager.getLadder( ladderName ); + Rank rank = ladder.getRank( rankName ); + + if ( rank == null && rankId != -1 ) { + // Fall back to rankId since there was a short time when rankId was used in this + // json format without a valid rankName. + rank = ladder.getRank( rankId ); + } + + // Setups up the rank for the player and recalculates all of the rank multipliers: + if ( rank != null ) { + + rankPlayer.addRank( rank ); + } + else { + String msg = String.format( + "RankPlayerFactory.createRankPlayer: Failed to add a player rank. " + + "Player: %s json: %s", + rankPlayer.getName(), + json + ); + + Output.get().logWarn( msg ); + } + + } + } + + } -// for (String key : prestigeLocal.keySet()) { -// prestige.put(key, RankUtil.doubleToInt(prestigeLocal.get(key))); -// } + + // Sets up the Ladder and Rank objects: + setupLadderRanks( rankPlayer ); + -//// rankPlayer.setBlocksMined( new HashMap<>() ); -// if ( blocksMinedLocal != null ) { -// for (String key : blocksMinedLocal.keySet()) { -// rankPlayer.getBlocksMined().put(key, ConversionUtil.doubleToInt(blocksMinedLocal.get(key))); -// } -// } - if ( namesListObject != null ) { + Object namesListObject = document.get( "names" ); + + if ( namesListObject != null ) { for ( Object rankPlayerNameMap : (ArrayList) namesListObject ) { LinkedTreeMap rpnMap = (LinkedTreeMap) rankPlayerNameMap; @@ -81,22 +147,181 @@ public RankPlayer createRankPlayer(Document document) { } } - } + } + + + + if ( document.get("balance") != null ) { + + rankPlayer.setCurrentBalanceTemp( (Double) document.get("balance") ); + } + + if ( document.get("totalBlocks") != null ) { + + rankPlayer.setTotalBlocksTemp( getLong( rankPlayer.getName(), "totalBlocks", document ) ); + } + + if ( document.get("totalTokens") != null ) { + + rankPlayer.setTotalTokensTemp( getLong( rankPlayer.getName(), "totalTokens", document ) ); + } + + if ( document.get("lastSeenDate") != null ) { + + rankPlayer.setLastSeenDateTemp( getLong( rankPlayer.getName(), "lastSeenDate", document ) ); + } + + + if ( document.get("lastSaved") != null ) { + rankPlayer.setLastSaved( getLong( rankPlayer.getName(), "lastSaved", document ) ); + } + + + if ( document.get("lastRefreshed") != null ) { + rankPlayer.setLastRefreshed( getLong( rankPlayer.getName(), "lastRefreshed", document ) ); + } + + + + // The new field permsSnapShot will be a list of all of the player's perms, captured + // at major moments when they are online. Since perms are not available offline, + // this will provide a "rough" listing of what they maybe. Its beyond the scope of + // this snap shot to ensure these perms are "current"; if they change after this + // image is taken, then that's not our problem. + if ( document.get("permsSnapShot") != null ) { + List perms = (List) document.get("permsSnapShot"); + rankPlayer.setPermsSnapShot( perms ); + } + + + if ( document.get("sellallMultiplier") != null ) { + double multValue = (Double) document.get("sellallMultiplier"); + rankPlayer.setSellallMultiplierValue( multValue ); + } + + if ( document.get("sellallMultipliers") != null ) { + List mults = (List) document.get("sellallMultipliers"); + rankPlayer.setSellallMultipliers( mults ); + } + + + return rankPlayer; + } + + private long getLong( String playerName, String field, Document document ) { + long value = 0L; + + Object obj = document.get(field); + if ( obj == null ) { + } + if ( obj instanceof Long ) { + value = (Long) obj; + } + else if ( obj instanceof Double ) { + Double duble = (Double) obj; + value = duble.longValue(); + } + + return value; + } + + + public static Document toDocument( RankPlayer rankPlayer ) { + + // Update some stats from the playerCache: + PlayerCachePlayerData cacheData = rankPlayer.getPlayerCache().getOnlinePlayerCached(rankPlayer); + rankPlayer.updateTotalLastValues( cacheData , false); + + Document ret = new Document(); + ret.put("uid", rankPlayer.getUUID()); + + + + Set ladders = rankPlayer.getLadderRanks().keySet(); + TreeMap playerRanks = new TreeMap<>(); + for (RankLadder ladder : ladders) { + PlayerRank rank = rankPlayer.getLadderRanks().get(ladder); + + RankPlayerFactoryDataRank rData = new RankPlayerFactoryDataRank( + rank.getRank().getName(), ladder.getName(), rank.getRank().getId() ); + + playerRanks.put( rData.getLadderName(), rData.getJsonObject() ); + + } + + ret.put("ranks", playerRanks ); + + + ret.put("names", rankPlayer.getNames()); + + + ret.put("balance", Double.valueOf( rankPlayer.getCurrentBalanceTemp() )); + ret.put("totalBlocks", Long.valueOf( rankPlayer.getTotalBlocksTemp() )); + ret.put("totalTokens", Long.valueOf( rankPlayer.getTotalTokensTemp() )); + ret.put("lastSeenDate", Long.valueOf( rankPlayer.getLastSeenDateTemp() )); + + - return rankPlayer; - } + Player sPlayer = rankPlayer.getPlatformPlayer(); + + + + // create a timestamp: + ret.put( "lastSaved", Long.valueOf( System.currentTimeMillis() )); - public static Document toDocument( RankPlayer rankPlayer ) { - Document ret = new Document(); - ret.put("uid", rankPlayer.getUUID()); - ret.put("ranks", rankPlayer.getRanksRefs() ); -// ret.put("prestige", this.prestige); + + if ( sPlayer != null && sPlayer.isOnline() ) { + ret.put( "lastRefreshed", Long.valueOf( System.currentTimeMillis() )); + } + else { + ret.put( "lastRefreshed", rankPlayer.getLastRefreshed() ); + } - ret.put("names", rankPlayer.getNames()); -// ret.put("blocksMined", rankPlayer.getBlocksMined() ); - return ret; - } + // The new field permsSnapShot will be a list of all of the player's perms, captured + // at major moments when they are online. Since perms are not available offline, + // this will provide a "rough" listing of what they maybe. Its beyond the scope of + // this snap shot to ensure these perms are "current"; if they change after this + // image is taken, then that's not our problem. + List perms = new ArrayList<>(); + + + if ( sPlayer != null && sPlayer.isOnline() ) { + // If the player is online, get a fresh list of perms: + perms = sPlayer.getPermissions(); + rankPlayer.setPermsSnapShot(perms); + } + else { + // Otherwise since the player if offline, then save whatever permsSnapShot is already available: + perms = rankPlayer.getPermsSnapShot(); + } + ret.put( "permsSnapShot", perms ); + + + double multValue = 1d; + if ( sPlayer != null && sPlayer.isOnline() ) { + multValue = sPlayer.getSellAllMultiplier(); + } + else { + // Otherwise since offline, save the existing list of multipliers: + multValue = rankPlayer.getSellallMultiplierValue(); + } + ret.put( "sellallMultiplier", multValue ); + + List multipliers = new ArrayList<>(); + if ( sPlayer != null && sPlayer.isOnline() ) { + multipliers = sPlayer.getSellAllMultiplierListings(); + } + else { + // Otherwise since offline, save the existing list of multipliers: + multipliers = rankPlayer.getSellallMultipliers(); + } + ret.put("sellallMultipliers", multipliers); + + + + return ret; + } @@ -114,43 +339,42 @@ public static Document toDocument( RankPlayer rankPlayer ) { */ public void firstJoin( RankPlayer rankPlayer) { - RankLadder defaultLadder = PrisonRanks.getInstance().getDefaultLadder(); - - if ( defaultLadder == null ) { - - Output.get().logError( "RankPlayerFactory.firstJoin: No default ladder!!" ); - - } - else if ( !rankPlayer.getLadderRanks().containsKey( defaultLadder ) ) { - - Optional firstRank = defaultLadder.getLowestRank(); - - if ( firstRank.isPresent() ) { - Rank defaultRank = firstRank.get(); - - - RankUpCommand rankupCommands = PrisonRanks.getInstance().getRankManager().getRankupCommands(); - - rankupCommands.setPlayerRankFirstJoin( rankPlayer, defaultRank ); - rankPlayer.setDirty( true ); - - - // Saves the new player's rank: - PrisonRanks.getInstance().getPlayerManager().savePlayer(rankPlayer); - -// rankPlayer.addRank( defaultRank ); - - Prison.get().getEventBus().post(new FirstJoinEvent( rankPlayer )); - - FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); - Output.get().logWarn( messages.firstJoinSuccess( rankPlayer.getName() ) ); - - } else { - - FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); - Output.get().logWarn( messages.firstJoinWarningNoRanksOnServer() ); - } - } + RankLadder defaultLadder = PrisonRanks.getInstance().getDefaultLadder(); + + if ( defaultLadder == null ) { + + Output.get().logError( "RankPlayerFactory.firstJoin: No default ladder!!" ); + + } + else if ( !rankPlayer.getLadderRanks().containsKey( defaultLadder ) ) { + + Optional firstRank = defaultLadder.getLowestRank(); + + if ( firstRank.isPresent() ) { + Rank defaultRank = firstRank.get(); + + + RankUpCommand rankupCommands = PrisonRanks.getInstance().getRankManager().getRankupCommands(); + + rankupCommands.setPlayerRankFirstJoin( rankPlayer, defaultRank ); + rankPlayer.setDirty( true ); + + + // Saves the new player's rank: + PrisonRanks.getInstance().getPlayerManager().savePlayer(rankPlayer); + + + Prison.get().getEventBus().post(new FirstJoinEvent( rankPlayer )); + + FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); + Output.get().logWarn( messages.firstJoinSuccess( rankPlayer.getName() ) ); + + } else { + + FirstJoinHandlerMessages messages = new FirstJoinHandlerMessages(); + Output.get().logWarn( messages.firstJoinWarningNoRanksOnServer() ); + } + } } @@ -162,15 +386,16 @@ else if ( !rankPlayer.getLadderRanks().containsKey( defaultLadder ) ) { * @param ladderName The ladder's name. */ public boolean removeLadder( RankPlayer rankPlayer, String ladderName ) { - boolean results = false; + boolean results = false; + if ( !ladderName.equalsIgnoreCase(LadderManager.LADDER_DEFAULT) ) { - Integer id = rankPlayer.getRanksRefs().remove(ladderName); - results = (id != null); - - RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); - if ( ladder != null && !ladder.getName().equalsIgnoreCase( LadderManager.LADDER_DEFAULT ) ) { - rankPlayer.getLadderRanks().remove( ladder ); - } + Integer id = rankPlayer.getRanksRefs().remove(ladderName); + results = (id != null); + + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); + if ( ladder != null && !ladder.getName().equalsIgnoreCase( LadderManager.LADDER_DEFAULT ) ) { + rankPlayer.getLadderRanks().remove( ladder ); + } } return results; @@ -188,20 +413,20 @@ public boolean removeLadder( RankPlayer rankPlayer, String ladderName ) { * @return */ public PlayerRank getRank( RankPlayer rankPlayer, RankLadder ladder, boolean force ) { - PlayerRank results = getRank( rankPlayer, ladder ); - - if ( force && results == null ) { - Rank tempRank = ladder.getLowestRank().get(); - - if ( tempRank != null ) { - results = new PlayerRank( tempRank ); - - // force cost calculations with a zero multiplier: - results.applyMultiplier( 0 ); - } - } - - return results; + PlayerRank results = getRank( rankPlayer, ladder ); + + if ( force && results == null ) { + Rank tempRank = ladder.getLowestRank().get(); + + if ( tempRank != null ) { + results = new PlayerRank( tempRank ); + + // force cost calculations with a zero multiplier: + results.applyMultiplier( 0 ); + } + } + + return results; } /** @@ -211,63 +436,23 @@ public PlayerRank getRank( RankPlayer rankPlayer, RankLadder ladder, boolean for * @return An optional containing the {@link Rank} if found, or empty if there isn't a rank by that ladder for this player. */ public PlayerRank getRank( RankPlayer rankPlayer, RankLadder ladder ) { - PlayerRank results = null; - - if ( ladder != null ) { - - Set keys = rankPlayer.getLadderRanks().keySet(); - for ( RankLadder key : keys ) - { - if ( key != null && key.getName().equalsIgnoreCase( ladder.getName() ) ) { - results = rankPlayer.getLadderRanks().get( key ); - } - } - } + PlayerRank results = null; + + if ( ladder != null ) { + + Set keys = rankPlayer.getLadderRanks().keySet(); + for ( RankLadder key : keys ) + { + if ( key != null && key.getName().equalsIgnoreCase( ladder.getName() ) ) { + results = rankPlayer.getLadderRanks().get( key ); + break; + } + } + } - return results; - -// if (!ranksRefs.containsKey(ladder.getName())) { -// return null; -// } -// int id = ranksRefs.get(ladder.getName()); -// return PrisonRanks.getInstance().getRankManager().getRank(id); + return results; } - -// /** -// * Returns all ladders this player is a part of, along with each rank the player has in that ladder. -// * -// * @return The map containing this data. -// */ -// public Map getLadderRanksx( RankPlayer rankPlayer ) { -// -// if ( rankPlayer.getLadderRanks().isEmpty() && !rankPlayer.getRanksRefs().isEmpty() ) { -// -// //Map ret = new HashMap<>(); -// -// for (Map.Entry entry : rankPlayer.getRanksRefs().entrySet()) { -// RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder(entry.getKey()); -// -// if ( ladder == null ) { -// continue; // Skip it -// } -// -// Rank rank = PrisonRanks.getInstance().getRankManager().getRank(entry.getValue()); -// if ( rank == null ) { -// continue; // Skip it -// } -// -// PlayerRank pRank = new PlayerRank( rank ); -// -// rankPlayer.getLadderRanks().put(ladder, pRank); -// } -// -// // Need to recalculate all rank multipliers: -// rankPlayer.recalculateRankMultipliers(); -// } -// -// return rankPlayer.getLadderRanks(); -// } /** @@ -281,35 +466,31 @@ public PlayerRank getRank( RankPlayer rankPlayer, RankLadder ladder ) { */ public void setupLadderRanks( RankPlayer rankPlayer ) { - if ( rankPlayer.getLadderRanks().isEmpty() && !rankPlayer.getRanksRefs().isEmpty() ) { - - //Map ret = new HashMap<>(); - - for (Map.Entry entry : rankPlayer.getRanksRefs().entrySet()) { - String ladderName = entry.getKey(); - int rankId = entry.getValue(); - - RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); - - if ( ladder != null ) { - - for ( Rank rank : ladder.getRanks() ) { - if ( rank.getId() == rankId ) { - - PlayerRank pRank = rankPlayer.calculateTargetPlayerRank( rank ); -// PlayerRank pRank = createPlayerRank( rank ); - rankPlayer.getLadderRanks().put( ladder, pRank ); - - break; - } - } - } - } - - // Need to recalculate all rank multipliers: This may be redundant. - rankPlayer.recalculateRankMultipliers(); - } - + if ( rankPlayer.getLadderRanks().isEmpty() && !rankPlayer.getRanksRefs().isEmpty() ) { + + for (Map.Entry entry : rankPlayer.getRanksRefs().entrySet()) { + String ladderName = entry.getKey(); + int rankId = entry.getValue(); + + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); + + if ( ladder != null ) { + + for ( Rank rank : ladder.getRanks() ) { + if ( rank.getId() == rankId ) { + + PlayerRank pRank = rankPlayer.calculateTargetPlayerRank( rank ); + rankPlayer.getLadderRanks().put( ladder, pRank ); + + break; + } + } + } + } + + // Need to recalculate all rank multipliers: This may be redundant. + rankPlayer.recalculateRankMultipliers(); + } } @@ -322,15 +503,8 @@ public void setupLadderRanks( RankPlayer rankPlayer ) { */ public PlayerRank getRank( RankPlayer rankPlayer, String ladderName ) { - RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); - return getRank( rankPlayer, ladder ); - -// Rank results = null; -// if (ladder != null && ranksRefs.containsKey(ladder)) { -// int id = ranksRefs.get(ladder); -// results = PrisonRanks.getInstance().getRankManager().getRank(id); -// } -// return results; + RankLadder ladder = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); + return getRank( rankPlayer, ladder ); } @@ -348,46 +522,20 @@ public PlayerRank getRank( RankPlayer rankPlayer, String ladderName ) { * @return */ public PlayerRank createPlayerRank( Rank rank ) { - PlayerRank results = new PlayerRank( rank ); - - double rankMultiplier = results.getLadderBasedRankMultiplier( rank ); - - results.setRankCost( rankMultiplier ); - - return results; + PlayerRank results = new PlayerRank( rank ); + + double rankMultiplier = results.getLadderBasedRankMultiplier( rank ); + + results.setRankCost( rankMultiplier ); + + return results; } -// private PlayerRank createPlayerRank( Rank rank, double rankMultiplier ) { -// PlayerRank results = new PlayerRank( rank, rankMultiplier ); -// -// return results; -// } public PlayerRank getTargetPlayerRankForPlayer( PlayerRank playerRank, RankPlayer player, Rank targetRank ) { PlayerRank targetPlayerRank = player.calculateTargetPlayerRank( targetRank ); -// if ( targetRank != null ) { -// -// double targetRankMultiplier = playerRank.getLadderBasedRankMultiplier( targetRank ); -// -// PlayerRank pRankForPLayer = getRank( player, targetRank.getLadder() ); -// double existingRankMultiplier = pRankForPLayer == null ? 0 : -// playerRank.getLadderBasedRankMultiplier( pRankForPLayer.getRank() ); -// -// // Get the player's total rankMultiplier from the default ladder -// // because they will always have a rank there: -// PlayerRank pRank = getRank( player, LadderManager.LADDER_DEFAULT ); -// double playerMultipler = pRank == null ? 0 : pRank.getRankMultiplier(); -// -// // So the actual rank multiplier that needs to be used, is based upon the -// // Player's current multiplier PLUS the multiplier for the target rank -// // AND MINUS the multiplier for the current rank the player has within the -// // target rank's ladder. -// double rankMultiplier = playerMultipler + targetRankMultiplier - existingRankMultiplier; -// -// targetPlayerRank = createPlayerRank( targetRank, rankMultiplier ); -// } return targetPlayerRank; } @@ -399,6 +547,5 @@ public double getRawRankCost( Rank rank ) { public void setRawRankCost( Rank rank, double rawCost ) { rank.setCost( rawCost ); } - } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactoryDataRank.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactoryDataRank.java new file mode 100644 index 000000000..b3c6e1b4f --- /dev/null +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerFactoryDataRank.java @@ -0,0 +1,67 @@ +package tech.mcprison.prison.ranks.data; + +import java.util.TreeMap; + +public class RankPlayerFactoryDataRank { + + private String rankName; + private String ladderName; + private int rankId; + + public RankPlayerFactoryDataRank() { + super(); + } + public RankPlayerFactoryDataRank( String rankName, String ladderName, int rankId ) { + super(); + + this.rankName = rankName; + this.ladderName = ladderName; + this.rankId = rankId; + } + + public TreeMap getJsonObject(){ + TreeMap results = new TreeMap<>(); + + results.put("rankName", getRankName()); + results.put("ladderName", getLadderName()); + + results.put("rankId", Integer.valueOf(rankId)); + + return results; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("Rank: ") + .append(getRankName()) + .append(" ") + .append(getRankId()) + .append(" Ladder: ") + .append(getLadderName()); + + return sb.toString(); + } + + public String getRankName() { + return rankName; + } + public void setRankName(String rankName) { + this.rankName = rankName; + } + + public String getLadderName() { + return ladderName; + } + public void setLadderName(String ladderName) { + this.ladderName = ladderName; + } + + public int getRankId() { + return rankId; + } + public void setRankId(int rankId) { + this.rankId = rankId; + } + +} diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerSortableLadderRankBalance.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerSortableLadderRankBalance.java index 8a5185a09..00ebd8078 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerSortableLadderRankBalance.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/RankPlayerSortableLadderRankBalance.java @@ -162,15 +162,10 @@ private double calculateTopScore( RankPlayer rp1, Rank rank, double balance ) { Rank nextRank = rank.getRankNext(); PlayerRank pRank = rp1.getLadderRanks().get( rank.getLadder() ); -// PlayerRank pRank = rp1.getRank( rank.getLadder() ); // This calculates the target rank, and takes in to consideration the player's existing rank: PlayerRank pRankNext = rp1.calculateTargetPlayerRank( nextRank ); -// PlayerRank pRankNext = pRank.getTargetPlayerRankForPlayer( rp1, nextRank ); -// PlayerRank pRankNext = nextRank == null ? null : -// new PlayerRank( nextRank, pRank.getRankMultiplier() ); - double nextRankCost = nextRank == null ? pRank.getRankCost() : pRankNext.getRankCost(); topScore = nextRankCost / balance; 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 4c79e3cf6..214493e6d 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 @@ -93,8 +93,6 @@ public static TopNPlayers getInstance() { if ( instance == null ) { instance = new TopNPlayers(); -// instance.loadSaveFile(); - instance.launchTopNPlayerUpdateAsyncTask(); } } @@ -292,8 +290,6 @@ public void forceReloadAllPlayers() { setStatsBuildDataNanoSec( end - start ); -// saveToJson(); - } } @@ -440,7 +436,7 @@ public void refreshAndSort() { TopNPlayersData topN = null; - String key = player.getPlayerFileName(); + String key = player.getUUID().toString(); if ( getTopNMap().containsKey(key) ) { topN = getTopNMap().get(key); @@ -474,10 +470,6 @@ public void refreshAndSort() { addPlayerData( topN, PlayerState.online ); - // Add player will always set the PlayerState to offline, so need to set it to - // online after addPlayerData() is called; -// topN.setPlayerState( PlayerState.online ); - setDirty( true ); @@ -501,9 +493,6 @@ public void refreshAndSort() { setTopNList(newTopNList); setArchivedList(newArchivedList); -// // sort: -// sortTopN(); - // If there has been any changes since the last save, then // save it: if ( isDirty() ) { @@ -580,7 +569,7 @@ private TopNPlayersData getTopNPlayer(RankPlayer rPlayer) { TopNPlayersData topN = null; - String key = rPlayer.getPlayerFileName(); + String key = rPlayer.getUUID().toString(); if ( getTopNMap().containsKey( key ) ) { @@ -626,35 +615,35 @@ public void updatePlayerData( RankPlayer rPlayer ) { } public String getTopNStats() { - - int topNSize = getTopNSize(); - int archivedSize = getArchivedSize(); - - - DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.000"); - DecimalFormat iFmt = Prison.get().getDecimalFormat("#,##0"); - - String statsBuildMs = dFmt.format( - getStatsBuildDataNanoSec() / 1_000_000 ); - String statsRefreshMs = dFmt.format( - getStatsRefreshDataNanoSec() / 1_000_000 ); - String statsSaveMs = dFmt.format( - getStatsSaveDataNanoSec() / 1_000_000 ); - String statsLoadMs = dFmt.format( - getStatsLoadDataNanoSec() / 1_000_000 ); - - String msg = String.format( - "&7topNstats:&3 topNs: %s archives: %s buildMs: %s refreshMs: %s " + - "saveMs: %s loadMs: %s ", - iFmt.format(topNSize), - iFmt.format(archivedSize), - statsBuildMs, - statsRefreshMs, - statsSaveMs, - statsLoadMs - ); - - return msg; + + int topNSize = getTopNSize(); + int archivedSize = getArchivedSize(); + + + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.000"); + DecimalFormat iFmt = Prison.get().getDecimalFormat("#,##0"); + + String statsBuildMs = dFmt.format( + getStatsBuildDataNanoSec() / 1_000_000 ); + String statsRefreshMs = dFmt.format( + getStatsRefreshDataNanoSec() / 1_000_000 ); + String statsSaveMs = dFmt.format( + getStatsSaveDataNanoSec() / 1_000_000 ); + String statsLoadMs = dFmt.format( + getStatsLoadDataNanoSec() / 1_000_000 ); + + String msg = String.format( + "&7topNstats:&3 topNs: %s archives: %s buildMs: %s refreshMs: %s " + + "saveMs: %s loadMs: %s ", + iFmt.format(topNSize), + iFmt.format(archivedSize), + statsBuildMs, + statsRefreshMs, + statsSaveMs, + statsLoadMs + ); + + return msg; } public int getTopNSize() { @@ -687,44 +676,44 @@ public RankPlayer getTopNRankArchivedPlayer( int rankPosition ) { * @return */ private RankPlayer getTopNRankPlayer( int rankPosition, boolean archived ) { - RankPlayer rPlayer = null; - - if ( PrisonRanks.getInstance() != null && - PrisonRanks.getInstance().isEnabled() && - PrisonRanks.getInstance().getPlayerManager() != null ) { - - ArrayList tList = - archived ? - getArchivedList() : - getTopNList(); - - if ( rankPosition >= 0 && tList.size() > rankPosition ) { - - TopNPlayersData topN = tList.get( rankPosition ); - - rPlayer = topN.getrPlayer(); - - if ( rPlayer == null && PrisonRanks.getInstance().getPlayerManager() != null ) { - - UUID nullUuid = null; - rPlayer = PrisonRanks.getInstance().getPlayerManager() - .getPlayer( nullUuid, topN.getName() ); - } - - // The topN has the last extracted values, so copy them to the rPlayer if - // it has not been updated. This would be good for the archives. - if ( rPlayer != null && topN.getRankScore() != 0 && rPlayer.getRankScore() == 0 ) { - - rPlayer.setRankScore( topN.getRankScore() ); - rPlayer.setRankScorePenalty( topN.getRankScorePenalty() ); - - rPlayer.setRankScoreBalance( topN.getBalance() ); - rPlayer.setRankScoreCurrency( topN.getBalanceCurrency() ); - - } - - } - } + RankPlayer rPlayer = null; + + if ( PrisonRanks.getInstance() != null && + PrisonRanks.getInstance().isEnabled() && + PrisonRanks.getInstance().getPlayerManager() != null ) { + + ArrayList tList = + archived ? + getArchivedList() : + getTopNList(); + + if ( rankPosition >= 0 && tList.size() > rankPosition ) { + + TopNPlayersData topN = tList.get( rankPosition ); + + rPlayer = topN.getrPlayer(); + + if ( rPlayer == null && PrisonRanks.getInstance().getPlayerManager() != null ) { + + UUID nullUuid = null; + rPlayer = PrisonRanks.getInstance().getPlayerManager() + .getPlayer( nullUuid, topN.getName() ); + } + + // The topN has the last extracted values, so copy them to the rPlayer if + // it has not been updated. This would be good for the archives. + if ( rPlayer != null && topN.getRankScore() != 0 && rPlayer.getRankScore() == 0 ) { + + rPlayer.setRankScore( topN.getRankScore() ); + rPlayer.setRankScorePenalty( topN.getRankScorePenalty() ); + + rPlayer.setRankScoreBalance( topN.getBalance() ); + rPlayer.setRankScoreCurrency( topN.getBalanceCurrency() ); + + } + + } + } return rPlayer; diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/TopNPlayersData.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/TopNPlayersData.java index 10aa7d42e..9b1d1222f 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/TopNPlayersData.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/data/TopNPlayersData.java @@ -34,6 +34,8 @@ public class TopNPlayersData { private String name; + private String uuid; + private String playerFileName; private PlayerState playerState; @@ -53,12 +55,21 @@ public class TopNPlayersData private int rankPositionDefault; private int rankPositionPrestiges; + private long blocks; + private long timeMining; + private long timeOnline; + private long tokens; + + private static transient SimpleDateFormat sdFmt = new SimpleDateFormat( "yyyy-MM-dd kk:mm:ss" ); public TopNPlayersData() { super(); this.playerState = PlayerState.offline; + + this.rankPositionDefault = -1; + this.rankPositionPrestiges = -1; } public TopNPlayersData( RankPlayer rPlayer) { @@ -67,17 +78,10 @@ public TopNPlayersData( RankPlayer rPlayer) { this.rPlayer = rPlayer; this.name = rPlayer.getName(); - this.playerFileName = rPlayer.getPlayerFileName(); - -// // Note: the nextPlayer rank could be in either the default ladder, -// // or the next prestige rank if at end of default ladder. -// PlayerRank nextRank = rPlayer.getNextPlayerRank(); - + this.uuid = rPlayer.getUUID().toString(); // This may be expensive getting lastSeen from the player's cache data: - setLastSeen( rPlayer.getPlayerCachePlayerData().getLastSeenDate() ); - -// this.lastSeenFormatted = sdFmt.format( new Date( this.lastSeen ) ); + setLastSeen( rPlayer.getLastSeenDateTemp() ); updateRankPlayer( rPlayer ); @@ -93,6 +97,12 @@ public void updateRankPlayer( RankPlayer rPlayer ) { setRankPositionDefault( rPlayer.getRankPositonDefault() ); setRankPositionPrestiges( rPlayer.getRankPositonPrestiges() ); + + + setBlocks( rPlayer.getTotalBlocksTemp() ); + setTokens( rPlayer.getTotalTokensTemp() ); + + } @Override @@ -140,7 +150,8 @@ public int compare(TopNPlayersData o1, TopNPlayersData o2) { } public String getKey() { - return getPlayerFileName(); + + return getUuid() != null ? getUuid() : getPlayerFileName(); } public String getName() { @@ -150,6 +161,13 @@ public void setName(String name) { this.name = name; } + public String getUuid() { + return uuid; + } + public void setUuid(String uuid) { + this.uuid = uuid; + } + public String getPlayerFileName() { return playerFileName; } @@ -230,5 +248,32 @@ public void setRankPositionPrestiges(int rankPositionPrestiges) { this.rankPositionPrestiges = rankPositionPrestiges; } + public long getBlocks() { + return blocks; + } + public void setBlocks(long blocks) { + this.blocks = blocks; + } + + public long getTimeMining() { + return timeMining; + } + public void setTimeMining(long timeMining) { + this.timeMining = timeMining; + } + + public long getTimeOnline() { + return timeOnline; + } + public void setTimeOnline(long timeOnline) { + this.timeOnline = timeOnline; + } + + public long getTokens() { + return tokens; + } + public void setTokens(long tokens) { + this.tokens = tokens; + } } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/FirstJoinEvent.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/FirstJoinEvent.java index 67c9cff31..2aa3fab50 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/FirstJoinEvent.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/FirstJoinEvent.java @@ -27,24 +27,12 @@ */ public class FirstJoinEvent { - /* - * Fields & Constants - */ - private RankPlayer player; - /* - * Constructors - */ - public FirstJoinEvent(RankPlayer player) { this.player = player; } - /* - * Getters & Setters - */ - public RankPlayer getPlayer() { return player; } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/RankUpEvent.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/RankUpEvent.java index a5bcc0ef2..4ff87f54e 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/RankUpEvent.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/events/RankUpEvent.java @@ -12,10 +12,6 @@ */ public class RankUpEvent { - /* - * Fields & Constants - */ - private RankPlayer player; private Rank oldRank; private Rank newRank; @@ -27,9 +23,6 @@ public class RankUpEvent { private boolean canceled = false; private String cancelReason = null; - /* - * Constructor - */ public RankUpEvent(RankPlayer player, Rank oldRank, Rank newRank, double cost, @@ -45,9 +38,6 @@ public RankUpEvent(RankPlayer player, this.forceCharge = forceCharge; } - /* - * Getters & Setters - */ public RankPlayer getPlayer() { return player; 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 f9bd31eac..27959f796 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 @@ -45,19 +45,11 @@ public class LadderManager public static final String LADDER_DEFAULT = "default"; public static final String LADDER_PRESTIGES = "prestiges"; - /* - * Fields & Constants - */ - private Collection collection; private List loadedLadders; private PrisonRanks prisonRanks; - /* - * Constructor - */ - /** * Instantiate this {@link LadderManager}. * @param prisonRanks @@ -69,9 +61,6 @@ public LadderManager(Collection collection, PrisonRanks prisonRanks) { this.prisonRanks = prisonRanks; } - /* - * Methods & Getters & Setters - */ /** * Loads a ladder from a file into the loaded ladders list. @@ -80,18 +69,18 @@ public LadderManager(Collection collection, PrisonRanks prisonRanks) { * @param fileKey The key that this ladder is stored as. This is case-sensitive. * @throws IOException If the file could not be read or does not exist. */ - public void loadLadder(String fileKey) throws IOException { + public void loadLadder(String fileKey, RankManager rankManager) throws IOException { Document doc = collection.get(fileKey).orElseThrow(IOException::new); RankLadderFactory rlFactory = new RankLadderFactory(); - RankLadder ladder = rlFactory.createRankLadder(doc, prisonRanks); + RankLadder ladder = rlFactory.createRankLadder(doc, rankManager); loadedLadders.add(ladder); // Will be dirty if load a ladder and the rank name does not exist and it adds them: if ( ladder.isDirty() ) { - saveLadder(ladder); + saveLadder(ladder); } } @@ -100,31 +89,49 @@ public void loadLadder(String fileKey) throws IOException { * * @throws IOException If the folder could not be found, or if a file could not be read or does not exist. */ - public void loadLadders() throws IOException { + public void loadLadders( RankManager rankManager ) + throws IOException { List documents = collection.getAll(); final RankLadderFactory rlFactory = new RankLadderFactory(); documents.forEach(document -> loadedLadders.add( - rlFactory.createRankLadder(document, prisonRanks)) ); + rlFactory.createRankLadder(document, rankManager)) ); for ( RankLadder ladder : loadedLadders ) { - // Will be dirty if load a ladder and the rank name does not exist and it adds them: - if ( ladder.isDirty() ) { - saveLadder(ladder); - } + + // If old file exists, then set dirty so it can be saved and update the file name: + checkIfOldFileExists( ladder ); + + // Will be dirty if load a ladder and the rank name does not exist and it adds them: + if ( ladder.isDirty() ) { + saveLadder(ladder); + } } } /** + * If the old file name exists, then this ladder has not been upgraded + * yet. So set it to dirty so it can be saved and update the file name. + * + * @param ladder + */ + private void checkIfOldFileExists(RankLadder ladder) { + if ( collection.exists( getLadderNameOld(ladder) )) { + ladder.setDirty( true ); + } + } + + /** * Saves a ladder to its save file. * * @param ladder The {@link RankLadder} to save. * @param fileKey The key to write the ladder as. + * @param oldFileName The old file name based upon id. * @throws IOException If the ladder could not be serialized, or if the ladder could not be saved to the file. */ - public void saveLadder(RankLadder ladder, String fileKey) throws IOException { - collection.save(fileKey, ladder.toDocument()); + public void saveLadder(RankLadder ladder, String fileKey, String oldFileName) throws IOException { + collection.save(fileKey, ladder.toDocument(), oldFileName, "Ladder"); } /** @@ -134,11 +141,28 @@ 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, getLadderName(ladder)); + + String fileLadderNameNew = getLadderNameNew(ladder); + String fileLadderNameOld = getLadderNameOld(ladder); + + this.saveLadder(ladder, fileLadderNameNew, fileLadderNameOld); } - private String getLadderName( RankLadder ladder ) { - return "ladder_" + ladder.getId(); + private String getLadderNameNew( RankLadder ladder ) { + return "ladder_" + ladder.getName(); + } + + /** + * This function will generate an old ladder name only if the id is not + * -1. If it's -1, then there is no need to return anything other than null. + * This will be used to identify if an old file exists so it can be removed + * when the newer format is saved. + * + * @param ladder + * @return + */ + private String getLadderNameOld( RankLadder ladder ) { + return ladder.getId() == -1 ? null : "ladder_" + ladder.getId(); } /** @@ -157,20 +181,20 @@ private String getLadderName( RankLadder ladder ) { * @return success or failure. A value of true indicates the save was successful. */ public boolean save( RankLadder ladder ) { - boolean success = false; - - try { - saveLadder( ladder ); - success = true; - } - catch ( IOException e ) { - - String errorMessage = cannotSaveLadderFile( ladder.getName(), e.getMessage() ); - - Output.get().logError( errorMessage, e ); - } - - return success; + boolean success = false; + + try { + saveLadder( ladder ); + success = true; + } + catch ( IOException e ) { + + String errorMessage = cannotSaveLadderFile( ladder.getName(), e.getMessage() ); + + Output.get().logError( errorMessage, e ); + } + + return success; } /** @@ -194,7 +218,9 @@ public void saveLadders() throws IOException { */ public RankLadder createLadder(String name) { // Set the default values... - RankLadder newLadder = new RankLadder( getNextAvailableId(), name ); + // ladder id is no longer used, so use -1: + RankLadder newLadder = new RankLadder( -1, name ); +// RankLadder newLadder = new RankLadder( getNextAvailableId(), name ); // ... add it to the list... loadedLadders.add(newLadder); @@ -209,7 +235,8 @@ public RankLadder createLadder(String name) { * * @return The next available ladder's ID. */ - private int getNextAvailableId() { + @SuppressWarnings("unused") + private int getNextAvailableId() { // Set the highest to -1 for now, since we'll add one at the end int highest = -1; @@ -250,17 +277,18 @@ public boolean removeLadder(RankLadder ladder) { loadedLadders.remove(ladder); // ... and remove the ladder's save files. - collection.delete("ladder_" + ladder.getId()); -// collection.remove("ladder_" + ladder.id); + collection.delete( getLadderNameNew(ladder) ); + collection.delete( getLadderNameOld(ladder) ); + return true; } public RankLadder getLadderDefault() { - return getLadder( RankLadder.DEFAULT ); + return getLadder( RankLadder.DEFAULT ); } public RankLadder getLadderPrestiges() { - return getLadder( RankLadder.PRESTIGES ); + return getLadder( RankLadder.PRESTIGES ); } /** @@ -270,14 +298,14 @@ public RankLadder getLadderPrestiges() { * @return An optional containing either the {@link RankLadder} if it could be found, or empty if it does not exist by the specified name. */ public RankLadder getLadder(String name) { - RankLadder results = null; - for ( RankLadder rankLadder : loadedLadders ) { - if ( rankLadder.getName().equalsIgnoreCase( name ) ) { - results = rankLadder; - break; + RankLadder results = null; + for ( RankLadder rankLadder : loadedLadders ) { + if ( rankLadder.getName().equalsIgnoreCase( name ) ) { + results = rankLadder; + break; + } } - } - return results; + return results; } /** @@ -287,14 +315,14 @@ public RankLadder getLadder(String name) { * @return the {@link RankLadder} if it could be found, or null if it does not exist by the specified id. */ public RankLadder getLadder(int id) { - RankLadder results = null; - for ( RankLadder rankLadder : loadedLadders ) { - if ( rankLadder.getId() == id ) { - results = rankLadder; - break; + RankLadder results = null; + for ( RankLadder rankLadder : loadedLadders ) { + if ( rankLadder.getId() == id ) { + results = rankLadder; + break; + } } - } - return results; + return results; } /** @@ -359,18 +387,18 @@ public String printRankLadderInfoDetail( RankLadder ladder ) { 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 %5d %-12s %-12s", - ladder.getName(), - dFmt.format( ladder.getRankCostMultiplierPerRank() ), - rankCount, - (firstRank == null ? "" : firstRank.getName()), - (lastRank == null ? "" : lastRank.getName()) - ); - + 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 %5d %-12s %-12s", + ladder.getName(), + dFmt.format( ladder.getRankCostMultiplierPerRank() ), + rankCount, + (firstRank == null ? "" : firstRank.getName()), + (lastRank == null ? "" : lastRank.getName()) + ); + return ladderInfo; } @@ -378,12 +406,101 @@ public String getLadderByFileName(String fileName) { String results = ""; for (RankLadder rankLadder : loadedLadders) { - String ladderFileName = getLadderName(rankLadder) + ".json"; + + // NOTE: if the ladder was renamed, will need to check the old + // name? + + // Check using the new file name for the ladder: + String ladderFileName = getLadderNameNew(rankLadder) + ".json"; if ( ladderFileName.equalsIgnoreCase(fileName) ) { results = rankLadder.getName(); } + else { + + // Check using the old file name for the ladder: + String ladderFileName2 = getLadderNameOld(rankLadder) + ".json"; + if ( ladderFileName2.equalsIgnoreCase(fileName) ) { + results = rankLadder.getName(); + } + } } return results; } + /** + * A default ladder is absolutely necessary on the server, so let's create it if it doesn't exist, this also create the prestiges ladder. + */ + public void createDefaultLadder() { + if ( getLadder(LadderManager.LADDER_DEFAULT) == null ) { + RankLadder rankLadder = createLadder(LadderManager.LADDER_DEFAULT); + + if ( rankLadder == null ) { + + String failureMsg = prisonRanks.prisonRanksFailureCreateDefaultLadderMsg(); + + Output.get().logError( failureMsg ); + prisonRanks.getStatus().toFailed( failureMsg ); + return; + } + + if ( !save( rankLadder ) ) { + + String failureMsg = prisonRanks.prisonRanksFailureSavingDefaultLadderMsg(); + + Output.get().logError( failureMsg ); + prisonRanks.getStatus().toFailed( failureMsg ); + } + } + + if ( getLadder(LadderManager.LADDER_PRESTIGES) == null ) { + RankLadder rankLadder = createLadder(LadderManager.LADDER_PRESTIGES); + + if ( rankLadder == null ) { + + String failureMsg = prisonRanks.prisonRanksFailureCreatePrestigeLadderMsg(); + + Output.get().logError( failureMsg ); + prisonRanks.getStatus().toFailed( failureMsg ); + return; + } + + if ( !save( rankLadder ) ) { + + String failureMsg = prisonRanks.prisonRanksFailureSavingPrestigeLadderMsg(); + + Output.get().logError( failureMsg ); + prisonRanks.getStatus().toFailed( failureMsg ); + } + } + + } + + + + public List getLoadedLadders() { + return loadedLadders; + } + public void setLoadedLadders(List loadedLadders) { + this.loadedLadders = loadedLadders; + } + + + private void resetAllLadders() { + + this.loadedLadders = new ArrayList<>(); + } + + public void reloadAllLadders( RankManager rankManager ) + throws IOException { + Output.get().logInfo( "Ranks: Loading Ladders..." ); + + resetAllLadders(); + + loadLadders( rankManager ); + + + Output.get().logInfo( "Ranks: Finished Loading Ladders." ); + + } + } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java index ae6c2301d..12a69a397 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManager.java @@ -70,57 +70,49 @@ public class PlayerManager private Collection collection; private List players; + + // NOTE: playersByName is indexed by both the player's name, and their UUID. private TreeMap playersByName; private List translatedPlaceHolderKeys; private transient Set playerErrors; + + private transient boolean enabled = false; public PlayerManager(Collection collection) { - super("PlayerMangager"); + super("PlayerManager"); - this.collection = collection; this.players = new ArrayList<>(); this.playersByName = new TreeMap<>(); this.playerErrors = new HashSet<>(); + + if ( collection == null ) { + this.enabled = false; + + this.collection = null; + } + else { + + this.collection = collection; + + Prison.get().getEventBus().register(this); + } - - Prison.get().getEventBus().register(this); } + + - /* - * Methods - */ + public boolean isEnabled() { + return enabled; + } -// /** -// * Loads a player from a file and stores it in the registry for use on the server. -// * -// * @param playerFile The key that the player data is stored as. Case-sensitive. -// * @throws IOException If the file could not be read, or if the file does not exist. -// */ -// public void loadPlayer(String playerFile) throws IOException { -// Document document = collection.get(playerFile).orElseThrow(IOException::new); -// -// RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); -// -// RankPlayer rankPlayer = rankPlayerFactory.createRankPlayer(document); -// -// players.add( rankPlayer ); -// -// // add by uuid: -// playersByName.put( rankPlayer.getUUID().toString(), rankPlayer ); -// -// // add by name: -// if ( rankPlayer.getNames().size() > 0 ) { -// playersByName.put( rankPlayer.getDisplayName(), rankPlayer ); -// -// } -// } - /** + + /** * Loads every player in the specified playerFolder. * * @throws IOException If one of the files could not be read, or if the playerFolder does not exist. @@ -132,7 +124,7 @@ public void loadPlayers() throws IOException { for ( Document playerDocument : playerDocss ) { - RankPlayer rankPlayer = rankPlayerFactory.createRankPlayer(playerDocument); + RankPlayer rankPlayer = rankPlayerFactory.createRankPlayer(playerDocument); players.add( rankPlayer ); @@ -141,18 +133,16 @@ public void loadPlayers() throws IOException { // add by name: if ( rankPlayer.getNames().size() > 0 ) { - playersByName.put( rankPlayer.getDisplayName(), rankPlayer ); + playersByName.put( rankPlayer.getDisplayName(), rankPlayer ); + + // add lowercased name: + playersByName.put( rankPlayer.getDisplayName().toLowerCase(), rankPlayer ); } } -// players.forEach( -// document -> -// this.players.add( -// rankPlayerFactory.createRankPlayer(document) )); - } @@ -165,60 +155,38 @@ public void loadPlayers() throws IOException { * @throws IOException If the file could not be created or written to. * @see #savePlayer(RankPlayer) To save with the default conventional filename. */ - private void savePlayer(RankPlayer player, String playerFile) throws IOException { - - if ( !player.isEnableDirty() || player.isEnableDirty() && player.isDirty() ) { - - collection.save(playerFile, RankPlayerFactory.toDocument( player ) ); - - player.setDirty( false ); - } -// RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - -// collection.save(playerFile, RankPlayerFactory.toDocument( player ) ); -// collection.insert(playerFile, player.toDocument()); + private boolean savePlayer(RankPlayer player, String playerFile) throws IOException { + boolean success = false; + + if ( !player.isEnableDirty() || player.isEnableDirty() && player.isDirty() ) { + + collection.save(playerFile, RankPlayerFactory.toDocument( player ), null, "Player" ); + + player.setDirty( false ); + + success = true; + } + + return success; } - public void savePlayer(RankPlayer player) { - try { - this.savePlayer(player, player.filename()); - } - catch (IOException e) { - - String errorMessage = cannotSaveNewPlayerFile( player.getName(), player.filename() ); - - Output.get().logError( errorMessage, e); - } + public boolean savePlayer(RankPlayer player) { + boolean success = false; + + try { + success = this.savePlayer(player, player.filenamePlayer()); + } + catch (IOException e) { + + String errorMessage = cannotSaveNewPlayerFile( player.getName(), player.filenamePlayer() ); + + Output.get().logError( errorMessage, e); + } + + return success; } - /** - * Saves every player in the registry. If one player fails to save, it will not - * prevent the others from being saved. - * - * @throws IOException If one of the players could not be saved. - * @see #savePlayer(RankPlayer, String) - */ -// public void savePlayers() throws IOException { -// for (RankPlayer player : players) { -// -// // Catch exceptions if a failed save so other players can be saved: -// try { -// savePlayer(player); -// } -// catch ( Exception e ) { -// -// String errorMessage = cannotSavePlayerFile( player.filename() ); -// -// if ( !getPlayerErrors().contains( errorMessage ) ) { -// getPlayerErrors().add( errorMessage ); -// Output.get().logError( errorMessage ); -// } -// -//// Output.get().logError(errorMessage, e); -// } -// } -// } - + /** *

    If the player does not have a default rank, then assign it to them and * then save their new settings. @@ -228,7 +196,7 @@ public void savePlayer(RankPlayer player) { */ public void checkPlayerDefaultRank( RankPlayer rPlayer ) { - if ( rPlayer.getPlayerRankDefault() == null ) { + if ( isEnabled() && rPlayer.getPlayerRankDefault() == null ) { // Try to perform the first join processing to give them the default rank: RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); @@ -247,18 +215,15 @@ public void checkPlayerDefaultRank( RankPlayer rPlayer ) { * */ public void connectPlayersToRanks( boolean checkPlayerBalances ) { - for ( RankPlayer player : players ) { - - for ( PlayerRank pRank : player.getLadderRanks().values() ) { - - pRank.getRank().addPlayer( player, checkPlayerBalances ); - } + for ( RankPlayer player : players ) { + + for ( PlayerRank pRank : player.getLadderRanks().values() ) { + + pRank.getRank().addPlayer( player, checkPlayerBalances ); + } } } - /* - * Getters & Setters - */ public List getPlayers() { return players; @@ -268,10 +233,6 @@ public TreeMap getPlayersByName() { return playersByName; } -// public List getPlayersByTop() { -// return playersByTop; -// } - public Set getPlayerErrors() { return playerErrors; } @@ -280,104 +241,93 @@ public Set getPlayerErrors() { *

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

    * + * * @param uid * @return */ public RankPlayer getPlayer(UUID uid, String playerName) { - RankPlayer results = null; -// boolean dirty = false; - - playerName = playerName == null ? "" : playerName.trim(); - - if ( !playerName.isEmpty() && getPlayersByName().containsKey( playerName ) ) { - results = getPlayersByName().get( playerName ); - } - - if ( results == null ) { - - debugLogPlayerInfo( "getPlayer(): UUID check:", playerName, false ); - - for ( RankPlayer rankPlayer : players ) { - if ( uid != null && rankPlayer.getUUID().equals(uid) || - - !playerName.isEmpty() && - rankPlayer.getName() != null && - rankPlayer.getName().equalsIgnoreCase( playerName ) ) { - - // This checks to see if they have a new name, if so, then adds it to the history: - // But the UID must match: - if ( uid != null && rankPlayer.getUUID().equals(uid) ) { - rankPlayer.setEnableDirty( true ); - rankPlayer.setDirty( rankPlayer.checkName( playerName ) ); - } - - results = rankPlayer; - break; - } - } - } - -// Optional results = players.stream().filter( -// player -> (uid != null ? -// player.uid.equals(uid) : -// ( playerName != null || playerName.trim().length() == 0 ? false : -// player.checkName( playerName )))).findFirst(); - - if ( results == null && playerName != null && !"console".equalsIgnoreCase( playerName ) ) { - - debugLogPlayerInfo( "getPlayer(): addPlayer:", playerName, false ); - - results = addPlayer(uid, playerName); - - // addPlayer() will save the player: -// if ( results != null ) { -// -// results.setDirty( true ); -// } - -// dirty = results != null; - } + RankPlayer results = null; -// // Save if dirty (changed or new): -// if ( results != null && results.isDirty() ) { -// savePlayer( results ); -// -// } + playerName = playerName == null ? "" : playerName.trim(); + + if ( !playerName.isEmpty() && getPlayersByName().containsKey( playerName ) ) { + results = getPlayersByName().get( playerName ); + } + else if ( !playerName.isEmpty() && getPlayersByName().containsKey( playerName.toLowerCase() ) ) { + results = getPlayersByName().get( playerName.toLowerCase() ); + } + else if ( uid != null && getPlayersByName().containsKey( uid.toString() ) ) { + results = getPlayersByName().get( uid.toString() ); + + if ( results != null ) { + // There was probably a name change since it did not hit on the player's name, + // so update the name history: + + // This checks to see if they have a new name, if so, then adds it to the history: + // But the UID must match: + if ( uid != null && results.getUUID().equals(uid) ) { + results.setEnableDirty( true ); + results.setDirty( results.checkName( playerName ) ); + } + } + } + - return results; + + if ( results == null && uid != null && playerName != null && !"console".equalsIgnoreCase( playerName ) ) { + + // Player's uuid and name cannot be null if they are being added as a new prison player: + + debugLogPlayerInfo( "getPlayer(): addPlayer (final attempt: could not match on playerName or UUID):", + playerName, uid == null ? "none" : uid.toString(), false ); + + results = addPlayer(uid, playerName); + + } + + + return results; } public RankPlayer getPlayer( Player player ) { - RankPlayer rPlayer = null; - if ( player != null ) { - rPlayer = getPlayer( player.getUUID(), player.getName() ); - } - return rPlayer; + RankPlayer rPlayer = null; + if ( player != null ) { + + // This function is called by SpigotCommander, as an example, and if we use the + // function 'player.getRankPlayer()' then that will become an endless loop. + // Also, we cannot use that either, because if the RankPlayer is null, then it + // needs to be added, which is what this class's 'getPlayer()' does. + // rPlayer = player.getRankPlayer(); + rPlayer = getPlayer( player.getUUID(), player.getName() ); + } + return rPlayer; } public RankPlayer addPlayer( Player player ) { - return addPlayer( player.getUUID(), player.getName() ); + return addPlayer( player.getUUID(), player.getName() ); } private RankPlayer addPlayer( UUID uid, String playerName ) { - RankPlayer results = null; - - // addPlayer can only be rank in the primary thread: - if ( PrisonTaskSubmitter.isPrimaryThread() ) { - results = addPlayerSyncTask( uid, playerName ); - } - else if ( !getPlayersByName().containsKey( playerName )) { - - // Submit the sync task to add player. But since this is an - // async thread, we can only return a null. Future requests - // for this player's placeholder will resolve successfully - // and a return value of null is perfectly acceptable. - NewRankPlayerSyncTask syncTask = new NewRankPlayerSyncTask( uid, playerName ); - PrisonTaskSubmitter.runTaskLater( syncTask, 0 ); - } - return results; + RankPlayer results = null; + + // addPlayer can only be rank in the primary thread: + if ( PrisonTaskSubmitter.isPrimaryThread() ) { + results = addPlayerSyncTask( uid, playerName ); + } + else if ( !getPlayersByName().containsKey( playerName ) && + !getPlayersByName().containsKey( playerName.toLowerCase() ) + ) { + + // Submit the sync task to add player. But since this is an + // async thread, we can only return a null. Future requests + // for this player's placeholder will resolve successfully + // and a return value of null is perfectly acceptable. + NewRankPlayerSyncTask syncTask = new NewRankPlayerSyncTask( uid, playerName ); + PrisonTaskSubmitter.runTaskLater( syncTask, 0 ); + } + return results; } protected RankPlayer addPlayerSyncTask( UUID uid, String playerName ) { @@ -388,104 +338,101 @@ protected RankPlayer addPlayerSyncTask( UUID uid, String playerName ) { if ( uid != null && playerName != null && playerName.trim().length() > 0 && !"CONSOLE".equalsIgnoreCase( playerName ) && - !getPlayersByName().containsKey( playerName )) { + !getPlayersByName().containsKey( playerName ) && + !getPlayersByName().containsKey( playerName.toLowerCase() ) ) { - synchronized( getPlayersByName() ) { - - // recheck to ensure that the player's name is not in the getPlayersByName() - // collection... it could have been added since submitting the sync task: - - if ( !getPlayersByName().containsKey( playerName ) ) { - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - // We need to create a new player data file. - newPlayer = new RankPlayer( uid, playerName ); -// newPlayer.checkName( playerName ); - newPlayer.setDirty( true ); - - // WARNING: Must save the newPlayer object to the playerManager collections - // before calling firstJoin(): - - players.add(newPlayer); - getPlayersByName().put( playerName, newPlayer ); - - - debugLogPlayerInfo( "addPlayerSyncTask: firstJoin:", playerName, false ); - - rankPlayerFactory.firstJoin( newPlayer ); - - - boolean joined = newPlayer.getPlayerRankDefault() != null; - String msg = joined ? "joined" : "failed"; - debugLogPlayerInfo( "addPlayerSyncTask: " + msg, playerName, false ); - - - // the new player is now saved in firstJoin()( - //savePlayer(newPlayer); - - -// try { -// -// } -// catch (IOException e) { -// -// String errorMessage = cannotSaveNewPlayerFile( playerName, newPlayer.filename() ); -// -// Output.get().logError( errorMessage, e); -// } - } - - } + synchronized( getPlayersByName() ) { + + // recheck to ensure that the player's name is not in the getPlayersByName() + // collection... it could have been added since submitting the sync task: + + if ( !getPlayersByName().containsKey( playerName ) && + !getPlayersByName().containsKey( playerName.toLowerCase() ) ) { + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + // We need to create a new player data file. + newPlayer = new RankPlayer( uid, playerName ); + newPlayer.setDirty( true ); + + // WARNING: Must save the newPlayer object to the playerManager collections + // before calling firstJoin(): + + players.add(newPlayer); + getPlayersByName().put( playerName, newPlayer ); + getPlayersByName().put( playerName.toLowerCase(), newPlayer ); + getPlayersByName().put( uid.toString(), newPlayer ); + + + debugLogPlayerInfo( "addPlayerSyncTask: firstJoin:", playerName, + newPlayer.getUUID().toString(), false ); + + rankPlayerFactory.firstJoin( newPlayer ); + + + boolean joined = newPlayer.getPlayerRankDefault() != null; + String msg = joined ? "joined" : "failed"; + debugLogPlayerInfo( "addPlayerSyncTask: " + msg, playerName, + newPlayer.getUUID().toString(), false ); + + } + } } return newPlayer; } - /* - * Listeners - */ - + @Subscribe public void onPlayerJoin(PlayerJoinEvent event) { - - Player player = event.getPlayer(); - - debugLogPlayerInfo( "onPlayerJoin:", player.getName(), true ); - - // Player is auto added if they do not exist when calling getPlayer so don't try to - // add them a second time. - RankPlayer rPlayer = getPlayer(player.getUUID(), player.getName()); - - rPlayer.doNothing(); + + Player player = event.getPlayer(); + + if ( player != null ) { + debugLogPlayerInfo( "onPlayerJoin:", player.getName(), player.getUUID().toString(), true ); + + // Player is auto added if they do not exist when calling getPlayer so don't try to + // add them a second time. + RankPlayer rPlayer = player.getRankPlayer(); + + if ( rPlayer != null ) { + + rPlayer.doNothing(); + } + } } - public void debugLogPlayerInfo( String eventName, String playerName, boolean date ) { - - if ( Output.get().isDebug() ) { - - boolean newPlayer = !getPlayersByName().containsKey( playerName ); - - SimpleDateFormat sdFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - - String msg = String.format( - "&6%s: &c%s &6%s &d%s", - eventName, - playerName, - date ? sdFmt.format(new Date()) : "", - newPlayer ? "[New Player]" : "" - ); - - Output.get().logInfo( msg ); - } + public void debugLogPlayerInfo( String eventName, String playerName, String uuid, boolean date ) { + if ( Output.get().isDebug() ) { + + boolean newPlayer = playerName != null ? + !getPlayersByName().containsKey( playerName ) && + !getPlayersByName().containsKey( playerName.toLowerCase() ) : false; + + if ( playerName == null ) { + playerName = "**Error No player name**"; + } + + SimpleDateFormat sdFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + String msg = String.format( + "&6%s: &c%s &6%s &d%s uuid=%s", + eventName, + playerName, + date ? sdFmt.format(new Date()) : "", + newPlayer ? "[New Player]" : "", + uuid + ); + + Output.get().logInfo( msg ); + } } - public String getPlayerRankName( RankPlayer rankPlayer, String ladderName ) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); if ( !rankPlayer.getLadderRanks().isEmpty()) { for (Map.Entry entry : rankPlayer.getLadderRanks().entrySet()) { @@ -513,31 +460,31 @@ public String getPlayerRankName( RankPlayer rankPlayer, String ladderName ) { public String getPlayerRankNumber( RankPlayer rankPlayer, String ladderName, PlaceholderAttributeNumberFormat attributeNFormat ) { - StringBuilder sb = new StringBuilder(); - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - for (Map.Entry entry : rankPlayer.getLadderRanks().entrySet()) { - if ( ladderName == null || - ladderName != null && entry.getKey().getName().equalsIgnoreCase( ladderName )) { - - if ( sb.length() > 0 ) { - sb.append(" "); - } - - int rankNumber = rankNumber(entry.getValue().getRank()); - - if ( attributeNFormat != null ) { - - sb.append( attributeNFormat.format( (long) rankNumber ) ); - } - else { - sb.append( Integer.toString( rankNumber ) ); - } - } - } - } - - return (sb.length() == 0 ? "0" : sb.toString()); + StringBuilder sb = new StringBuilder(); + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + for (Map.Entry entry : rankPlayer.getLadderRanks().entrySet()) { + if ( ladderName == null || + ladderName != null && entry.getKey().getName().equalsIgnoreCase( ladderName )) { + + if ( sb.length() > 0 ) { + sb.append(" "); + } + + int rankNumber = rankNumber(entry.getValue().getRank()); + + if ( attributeNFormat != null ) { + + sb.append( attributeNFormat.format( (long) rankNumber ) ); + } + else { + sb.append( Integer.toString( rankNumber ) ); + } + } + } + } + + return (sb.length() == 0 ? "0" : sb.toString()); } /** @@ -549,52 +496,32 @@ public String getPlayerRankNumber( RankPlayer rankPlayer, String ladderName, * @return */ private int rankNumber( Rank value ) { - int results = 0; - if ( value != null ) { - Rank r = value; - while ( r != null ) { - results++; - r = r.getRankPrior(); - } - } + int results = 0; + if ( value != null ) { + Rank r = value; + while ( r != null ) { + results++; + r = r.getRankPrior(); + } + } return results; } public String getPlayerRankTag( RankPlayer rankPlayer, String ladderName ) { - StringBuilder sb = new StringBuilder(); - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - for (Map.Entry entry : rankPlayer.getLadderRanks().entrySet()) { - if ( ladderName == null || - ladderName != null && entry.getKey().getName().equalsIgnoreCase( ladderName )) { - -// if ( sb.length() > 0 ) { -// sb.append(" "); -// } - Rank rank = entry.getValue().getRank(); - -// if ( rank.getLadder() != null && rank.getLadder().isDefault() && -// rank.getRankNext() == null ) { -// PlayerRank prestigeRank = rankPlayer.getPlayerRankPrestiges(); -// -// if ( prestigeRank == null ) { -// RankLadder prestigeLadder = PrisonRanks.getInstance() -// .getLadderManager().getLadderPrestiges(); -// if ( prestigeLadder != null ) { -// rank = prestigeLadder.getLowestRank().orElseGet( null ); -// } -// } -// else { -// rank = prestigeRank.getRank().getRankNext(); -// } -// -// } - - String tag = rank.getTag(); - sb.append( tag == null ? rank.getName() : tag ); - } - } - } + StringBuilder sb = new StringBuilder(); + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + for (Map.Entry entry : rankPlayer.getLadderRanks().entrySet()) { + if ( ladderName == null || + ladderName != null && entry.getKey().getName().equalsIgnoreCase( ladderName )) { + + Rank rank = entry.getValue().getRank(); + + String tag = rank.getTag(); + sb.append( tag == null ? rank.getName() : tag ); + } + } + } if ( sb.length() == 0 && LadderManager.LADDER_PRESTIGES.equals( ladderName ) ) { // Use config setting for no-prestige-value ladder rank: @@ -603,11 +530,11 @@ public String getPlayerRankTag( RankPlayer rankPlayer, String ladderName ) { sb.append( prestigeEmpty ); } - return sb.toString(); + return sb.toString(); } public List getPlayerRanks( RankPlayer rankPlayer ) { - List results = new ArrayList<>(); + List results = new ArrayList<>(); if ( !rankPlayer.getLadderRanks().isEmpty()) { for (Map.Entry entry : rankPlayer.getLadderRanks().entrySet()) { @@ -619,82 +546,80 @@ public List getPlayerRanks( RankPlayer rankPlayer ) { } public List getPlayerNextRanks( RankPlayer rankPlayer ) { - List results = new ArrayList<>(); - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { - - Rank rank = rankPlayerFactory.getRank( rankPlayer, ladder ).getRank(); - if ( rank != null && rank.getRankNext() != null ) { - Rank nextRank = rank.getRankNext(); - - results.add( nextRank ); - } - } - } - - return results; + List results = new ArrayList<>(); + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { + + Rank rank = rankPlayerFactory.getRank( rankPlayer, ladder ).getRank(); + if ( rank != null && rank.getRankNext() != null ) { + Rank nextRank = rank.getRankNext(); + + results.add( nextRank ); + } + } + } + + return results; } public String getPlayerNextRankCost( RankPlayer rankPlayer, String ladderName, boolean formatted, PlaceholderAttributeNumberFormat attributeNFormat ) { - StringBuilder sb = new StringBuilder(); - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { - - if ( ladderName == null || - ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - - boolean isDefault = ladder.getName().equals( LadderManager.LADDER_DEFAULT ) ; - - PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); - Rank nextRank = pRank.getRank().getRankNext(); - - if ( pRank != null && - ( nextRank != null || nextRank == null && isDefault )) { - - nextRank = getNextPrestigeRank( rankPlayer, isDefault, nextRank ); - - // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); -// PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); - - //PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); - - if ( nextPRank != null ) { - - if ( sb.length() > 0 ) { - sb.append(", "); - } - - double cost = nextPRank.getRankCost(); - - if ( attributeNFormat != null ) { - - sb.append( attributeNFormat.format( cost ) ); - } - else if ( formatted ) { - sb.append( PlaceholdersUtil.formattedMetricSISize( cost )); - } - else { - sb.append( dFmt.format( cost )); - } - } - } - } - } - - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { + + if ( ladderName == null || + ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { + + boolean isDefault = ladder.getName().equals( LadderManager.LADDER_DEFAULT ) ; + + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + Rank nextRank = pRank.getRank().getRankNext(); + + if ( pRank != null && + ( nextRank != null || nextRank == null && isDefault )) { + + nextRank = getNextPrestigeRank( rankPlayer, isDefault, nextRank ); + + // This calculates the target rank, and takes in to consideration the player's existing rank: + PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); + + + if ( nextPRank != null ) { + + if ( sb.length() > 0 ) { + sb.append(", "); + } + + double cost = nextPRank.getRankCost(); + + if ( attributeNFormat != null ) { + + sb.append( attributeNFormat.format( cost ) ); + } + else if ( formatted ) { + sb.append( PlaceholdersUtil.formattedMetricSISize( cost )); + } + else { + sb.append( dFmt.format( cost )); + } + } + } + } + } + + } + + return sb.toString(); } private Rank getNextPrestigeRank( RankPlayer rankPlayer, boolean isDefault, Rank nextRank ) @@ -729,120 +654,109 @@ private Rank getNextPrestigeRank( RankPlayer rankPlayer, boolean isDefault, Rank public String getPlayerNextRankCostPercent( RankPlayer rankPlayer, String ladderName, PlaceholderAttributeNumberFormat attributeNFormat ) { - StringBuilder sb = new StringBuilder(); - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { - - if ( ladderName == null || - ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - - boolean isDefault = ladder.getName().equals( LadderManager.LADDER_DEFAULT ) ; - - PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); - Rank nextRank = pRank.getRank().getRankNext(); - - if ( pRank != null && - ( nextRank != null || nextRank == null && isDefault ) ) { - - nextRank = getNextPrestigeRank( rankPlayer, isDefault, nextRank ); - - // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); -// PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); - -// PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); - - if ( nextPRank != null ) { - - if ( sb.length() > 0 ) { - sb.append(", "); - } - -// Rank rank = key.getNext(key.getPositionOfRank(entry.getValue())).get(); - double cost = nextPRank.getRankCost(); - double balance = rankPlayer.getBalance( pRank.getRank().getCurrency() ); -// double balance = getPlayerBalance(prisonPlayer,nextRank); - - double percent = (balance < 0 ? 0 : - (cost == 0.0d || balance > cost ? 100.0 : - balance / cost * 100.0 ) - ); - - if ( attributeNFormat != null ) { - - sb.append( attributeNFormat.format( percent ) ); - } - else { - - sb.append( dFmt.format( percent )); - } - } - } - } - } - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { + + if ( ladderName == null || + ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { + + boolean isDefault = ladder.getName().equals( LadderManager.LADDER_DEFAULT ) ; + + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + Rank nextRank = pRank.getRank().getRankNext(); + + if ( pRank != null && + ( nextRank != null || nextRank == null && isDefault ) ) { + + nextRank = getNextPrestigeRank( rankPlayer, isDefault, nextRank ); + + // This calculates the target rank, and takes in to consideration the player's existing rank: + PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); + + if ( nextPRank != null ) { + + if ( sb.length() > 0 ) { + sb.append(", "); + } + + double cost = nextPRank.getRankCost(); + double balance = rankPlayer.getBalance( pRank.getRank().getCurrency() ); + + double percent = (balance < 0 ? 0 : + (cost == 0.0d || balance > cost ? 100.0 : + balance / cost * 100.0 ) + ); + + if ( attributeNFormat != null ) { + + sb.append( attributeNFormat.format( percent ) ); + } + else { + + sb.append( dFmt.format( percent )); + } + } + } + } + } + } + + return sb.toString(); } public String getPlayerNextRankCostBar( RankPlayer rankPlayer, String ladderName, PlaceholderAttributeBar attributeBar ) { - StringBuilder sb = new StringBuilder(); - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - -// DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { - - if ( ladderName == null || - ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - - boolean isDefault = ladder.getName().equals( LadderManager.LADDER_DEFAULT ) ; - - PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); - Rank rank = pRank.getRank(); - Rank nextRank = rank.getRankNext(); - - if ( rank != null && - ( nextRank != null || nextRank == null && isDefault )) { - - nextRank = getNextPrestigeRank( rankPlayer, isDefault, nextRank ); - - // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); -// PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); - -// PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); - - if ( nextPRank != null ) { - - if ( sb.length() > 0 ) { - sb.append(", "); - } - - double cost = nextPRank.getRankCost(); - double balance = rankPlayer.getBalance( rank.getCurrency() ); -// double balance = getPlayerBalance(prisonPlayer,nextRank); - - - sb.append( PlaceholderManagerUtils.getInstance(). - getProgressBar( balance, cost, false, attributeBar )); - } - - } - } - } - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { + + if ( ladderName == null || + ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { + + boolean isDefault = ladder.getName().equals( LadderManager.LADDER_DEFAULT ) ; + + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + Rank rank = pRank.getRank(); + Rank nextRank = rank.getRankNext(); + + if ( rank != null && + ( nextRank != null || nextRank == null && isDefault )) { + + nextRank = getNextPrestigeRank( rankPlayer, isDefault, nextRank ); + + // This calculates the target rank, and takes in to consideration the player's existing rank: + PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); + + if ( nextPRank != null ) { + + if ( sb.length() > 0 ) { + sb.append(", "); + } + + double cost = nextPRank.getRankCost(); + double balance = rankPlayer.getBalance( rank.getCurrency() ); + + + sb.append( PlaceholderManagerUtils.getInstance(). + getProgressBar( balance, cost, false, attributeBar )); + } + + } + } + } + } + + return sb.toString(); } /** @@ -859,72 +773,68 @@ public String getPlayerNextRankCostBar( RankPlayer rankPlayer, String ladderName */ public String getPlayerNextRankCostRemaining( RankPlayer rankPlayer, String ladderName, boolean formatted, PlaceholderAttributeNumberFormat attributeNFormat ) { - StringBuilder sb = new StringBuilder(); - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { - - if ( ladderName == null || - ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - - boolean isDefault = ladder.getName().equals( LadderManager.LADDER_DEFAULT ) ; - - PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); - Rank rank = pRank.getRank(); - Rank nextRank = rank.getRankNext(); - - if ( rank != null && - ( nextRank != null || nextRank == null && isDefault ) ) { - - nextRank = getNextPrestigeRank( rankPlayer, isDefault, nextRank ); - - // This calculates the target rank, and takes in to consideration the player's existing rank: - PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); -// PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); - -// PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); - - if ( nextPRank != null ) { - - if ( sb.length() > 0 ) { - sb.append(", "); - } - - double cost = nextPRank.getRankCost(); - double balance = rankPlayer.getBalance( rank.getCurrency() ); -// double balance = getPlayerBalance(prisonPlayer,nextRank); - - double remaining = cost - balance; - - // Without the following, if the player has more money than what the rank will cost, - // then it would result in a negative amount, which is wrong. - // This is cost remaining... once they are able to afford a rankup, then remaining - // cost will be zero. - if ( remaining < 0 ) { - remaining = 0; - } - - if ( attributeNFormat != null ) { - sb.append( attributeNFormat.format( remaining ) ); - } - - else if ( formatted ) { - sb.append( PlaceholdersUtil.formattedMetricSISize( remaining )); - } - else { - sb.append( dFmt.format( remaining )); - } - } - } - } - } - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { + + if ( ladderName == null || + ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { + + boolean isDefault = ladder.getName().equals( LadderManager.LADDER_DEFAULT ) ; + + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + Rank rank = pRank.getRank(); + Rank nextRank = rank.getRankNext(); + + if ( rank != null && + ( nextRank != null || nextRank == null && isDefault ) ) { + + nextRank = getNextPrestigeRank( rankPlayer, isDefault, nextRank ); + + // This calculates the target rank, and takes in to consideration the player's existing rank: + PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); + + if ( nextPRank != null ) { + + if ( sb.length() > 0 ) { + sb.append(", "); + } + + double cost = nextPRank.getRankCost(); + double balance = rankPlayer.getBalance( rank.getCurrency() ); + + double remaining = cost - balance; + + // Without the following, if the player has more money than what the rank will cost, + // then it would result in a negative amount, which is wrong. + // This is cost remaining... once they are able to afford a rankup, then remaining + // cost will be zero. + if ( remaining < 0 ) { + remaining = 0; + } + + if ( attributeNFormat != null ) { + sb.append( attributeNFormat.format( remaining ) ); + } + + else if ( formatted ) { + sb.append( PlaceholdersUtil.formattedMetricSISize( remaining )); + } + else { + sb.append( dFmt.format( remaining )); + } + } + } + } + } + } + + return sb.toString(); } @@ -954,34 +864,31 @@ public String getPlayerNextRankCostRemainingPercent( RankPlayer rankPlayer, Stri // This calculates the target rank, and takes in to consideration the player's existing rank: PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); -// PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); - -// PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); if ( nextPRank != null ) { - if ( sb.length() > 0 ) { - sb.append(", "); - } - - double cost = nextPRank.getRankCost(); - double balance = rankPlayer.getBalance( rank.getCurrency() ); -// double balance = getPlayerBalance(prisonPlayer,nextRank); - - double remaining = cost - balance; - - // Without the following, if the player has more money than what the rank will cost, - // then it would result in a negative amount, which is wrong. - // This is cost remaining... once they are able to afford a rankup, then remaining - // cost will be zero. - if ( remaining < 0 ) { - remaining = 0; - } - double percent = (remaining < 0 ? 0.0 : - (cost == 0.0d || remaining > cost ? 100.0 : - remaining / cost * 100.0 ) - ); - sb.append( dFmt.format( percent )); + if ( sb.length() > 0 ) { + sb.append(", "); + } + + double cost = nextPRank.getRankCost(); + double balance = rankPlayer.getBalance( rank.getCurrency() ); + // double balance = getPlayerBalance(prisonPlayer,nextRank); + + double remaining = cost - balance; + + // Without the following, if the player has more money than what the rank will cost, + // then it would result in a negative amount, which is wrong. + // This is cost remaining... once they are able to afford a rankup, then remaining + // cost will be zero. + if ( remaining < 0 ) { + remaining = 0; + } + double percent = (remaining < 0 ? 0.0 : + (cost == 0.0d || remaining > cost ? 100.0 : + remaining / cost * 100.0 ) + ); + sb.append( dFmt.format( percent )); } } } @@ -996,7 +903,6 @@ public String getPlayerNextRankCostRemainingBar( RankPlayer rankPlayer, String l StringBuilder sb = new StringBuilder(); if ( !rankPlayer.getLadderRanks().isEmpty()) { - // DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); @@ -1019,37 +925,28 @@ public String getPlayerNextRankCostRemainingBar( RankPlayer rankPlayer, String l // This calculates the target rank, and takes in to consideration the player's existing rank: PlayerRank nextPRank = rankPlayer.calculateTargetPlayerRank( nextRank ); -// PlayerRank nextPRank = pRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); - -// PlayerRank nextPRank = new PlayerRank( nextRank, pRank.getRankMultiplier() ); if ( nextPRank != null ) { - if ( sb.length() > 0 ) { - sb.append(", "); - } - - double cost = nextPRank.getRankCost(); - double balance = rankPlayer.getBalance( rank.getCurrency() ); -// double balance = getPlayerBalance(prisonPlayer,nextRank); - - double remaining = cost - balance; - - // Without the following, if the player has more money than what the rank will cost, - // then it would result in a negative amount, which is wrong. - // This is cost remaining... once they are able to afford a rankup, then remaining - // cost will be zero. - if ( remaining < 0 ) { - remaining = 0; - } - // double percent = (remaining < 0 ? 0.0 : - // (cost == 0.0d || remaining > cost ? 100.0 : - // remaining / cost * 100.0 ) - // ); - // sb.append( dFmt.format( percent )); - - sb.append( PlaceholderManagerUtils.getInstance(). - getProgressBar( remaining, cost, false, attributeBar )); + if ( sb.length() > 0 ) { + sb.append(", "); + } + + double cost = nextPRank.getRankCost(); + double balance = rankPlayer.getBalance( rank.getCurrency() ); + + double remaining = cost - balance; + + // Without the following, if the player has more money than what the rank will cost, + // then it would result in a negative amount, which is wrong. + // This is cost remaining... once they are able to afford a rankup, then remaining + // cost will be zero. + if ( remaining < 0 ) { + remaining = 0; + } + + sb.append( PlaceholderManagerUtils.getInstance(). + getProgressBar( remaining, cost, false, attributeBar )); } } @@ -1075,437 +972,362 @@ public String getPlayerNextRankCostRemainingBar( RankPlayer rankPlayer, String l */ private String getPlayerBalance( RankPlayer rankPlayer, String ladderName, boolean formatted, PlaceholderAttributeNumberFormat attributeNFormat ) { - StringBuilder sb = new StringBuilder(); - -// Player prisonPlayer = PrisonAPI.getPlayer(rankPlayer.getUUID()).orElse(null); -// if( prisonPlayer == null ) { -// -// String errorMessage = cannotLoadPlayerFile( rankPlayer.getUUID().toString() ); -// -// String message = "getPlayerBalance: " + errorMessage; -// -// if ( !getPlayerErrors().contains( message ) ) { -// getPlayerErrors().add( message ); -// Output.get().logError( message ); -// } -// -//// return "0"; -// } - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { - - if ( ladderName == null || - ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - - PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); - Rank rank = pRank.getRank(); - if ( rank != null ) { - if ( sb.length() > 0 ) { - sb.append(", "); - } - - double balance = rankPlayer.getBalance( rank.getCurrency() ); -// double balance = getPlayerBalance(prisonPlayer,rank); - - if ( attributeNFormat != null ) { - - sb.append( attributeNFormat.format( balance ) ); - } - - else if ( formatted ) { - sb.append( PlaceholdersUtil.formattedMetricSISize( balance )); - } - else { - sb.append( dFmt.format( balance )); - } - } - } - } - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { + + if ( ladderName == null || + ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { + + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + Rank rank = pRank.getRank(); + if ( rank != null ) { + if ( sb.length() > 0 ) { + sb.append(", "); + } + + double balance = rankPlayer.getBalance( rank.getCurrency() ); + + if ( attributeNFormat != null ) { + + sb.append( attributeNFormat.format( balance ) ); + } + + else if ( formatted ) { + sb.append( PlaceholdersUtil.formattedMetricSISize( balance )); + } + else { + sb.append( dFmt.format( balance )); + } + } + } + } + } + + return sb.toString(); } private String getPlayerAverageEarningsPerMinute( RankPlayer rankPlayer, String ladderName, boolean formatted, PlaceholderAttributeNumberFormat attributeNFormat ) { - StringBuilder sb = new StringBuilder(); - - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - - double epm = PlayerCache.getInstance().getPlayerEarningsPerMinute( rankPlayer ); - - if ( attributeNFormat != null ) { - - sb.append( attributeNFormat.format( epm ) ); - } - - else if ( formatted ) { - sb.append( PlaceholdersUtil.formattedMetricSISize( epm )); - } - else { - sb.append( dFmt.format( epm )); - } - - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + + double epm = PlayerCache.getInstance().getPlayerEarningsPerMinute( rankPlayer ); + + if ( attributeNFormat != null ) { + + sb.append( attributeNFormat.format( epm ) ); + } + + else if ( formatted ) { + sb.append( PlaceholdersUtil.formattedMetricSISize( epm )); + } + else { + sb.append( dFmt.format( epm )); + } + + } + + return sb.toString(); } private String getPlayerTokenBalance( RankPlayer rankPlayer, int formatMode, PlaceholderAttributeNumberFormat attributeNFormat ) { - StringBuilder sb = new StringBuilder(); - - DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - - long tokens = rankPlayer.getPlayerCachePlayerData().getTokens(); - - if ( attributeNFormat != null ) { - - sb.append( attributeNFormat.format( tokens ) ); - } - - else { - switch ( formatMode ) - { - case 1: { - sb.append( dFmt.format( tokens )); - - break; - } - case 2: { - sb.append( PlaceholdersUtil.formattedMetricSISize( tokens )); - - break; - } - case 3: { - sb.append( PlaceholdersUtil.formattedKmbtSISize( tokens, dFmt, " " )); - - break; + StringBuilder sb = new StringBuilder(); + + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + + long tokens = rankPlayer.getPlayerCachePlayerData().getTokens(); + + if ( attributeNFormat != null ) { + + sb.append( attributeNFormat.format( tokens ) ); + } + + else { + switch ( formatMode ) + { + case 1: { + sb.append( dFmt.format( tokens )); + + break; + } + case 2: { + sb.append( PlaceholdersUtil.formattedMetricSISize( tokens )); + + break; + } + case 3: { + sb.append( PlaceholdersUtil.formattedKmbtSISize( tokens, dFmt, " " )); + + break; + } + default: + sb.append( Long.toString( tokens )); } - default: - sb.append( Long.toString( tokens )); - } - } - -// if ( formatted ) { -// sb.append( PlaceholdersUtil.formattedMetricSISize( tokens )); -// } -// else { -// sb.append( dFmt.format( tokens )); -// } - - return sb.toString(); + } + + return sb.toString(); } private String getPlayerTokenAverageEarningsPerMinute( RankPlayer rankPlayer, boolean formatted, PlaceholderAttributeNumberFormat attributeNFormat ) { - StringBuilder sb = new StringBuilder(); - - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - - - double tpm = rankPlayer.getPlayerCachePlayerData().getAverageTokensPerMinute(); - - if ( attributeNFormat != null ) { - - sb.append( attributeNFormat.format( tpm ) ); - } - - else if ( formatted ) { - sb.append( PlaceholdersUtil.formattedMetricSISize( tpm )); - } - else { - sb.append( dFmt.format( tpm )); - } - - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + + + double tpm = rankPlayer.getPlayerCachePlayerData().getAverageTokensPerMinute(); + + if ( attributeNFormat != null ) { + + sb.append( attributeNFormat.format( tpm ) ); + } + + else if ( formatted ) { + sb.append( PlaceholdersUtil.formattedMetricSISize( tpm )); + } + else { + sb.append( dFmt.format( tpm )); + } + + } + + return sb.toString(); } - -// /** -// *

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

    -// * -// * @param player -// * @param rank -// * @return -// */ -// public double getPlayerBalance(Player player, Rank rank) { -// double playerBalance = 0; -// -// if ( player != null ) { -// -// if ( rank != null && rank.getCurrency() != null ) { -// EconomyCurrencyIntegration currencyEcon = PrisonAPI.getIntegrationManager() -// .getEconomyForCurrency( rank.getCurrency() ); -// if ( currencyEcon != null ) { -// playerBalance = currencyEcon.getBalance( player, rank.getCurrency() ); -// } else { -// -// String errorMessage = cannotLoadEconomyCurrency( player.getName(), rank.getCurrency() ); -// -// if ( !getPlayerErrors().contains( errorMessage ) ) { -// getPlayerErrors().add( errorMessage ); -// Output.get().logError( errorMessage ); -// } -// -// } -// -// } else { -// -// EconomyIntegration economy = PrisonAPI.getIntegrationManager().getEconomy(); -// -// if ( economy != null ) { -// playerBalance = economy.getBalance( player ); -// } else { -// -// String errorMessage = cannotLoadEconomy( player.getName() ); -// -// if ( !getPlayerErrors().contains( errorMessage ) ) { -// -// getPlayerErrors().add( errorMessage ); -// Output.get().logError( errorMessage ); -// } -// -// } -// } -// } -// -// return playerBalance; -// } - public String getPlayerNextRankName( RankPlayer rankPlayer, String ladderName ) { - StringBuilder sb = new StringBuilder(); - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { - - if ( ladderName == null || - ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - - PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); - Rank rank = pRank.getRank(); - - if ( rank != null && rank.getRankNext() != null ) { - Rank nextRank = rank.getRankNext(); - - if ( sb.length() > 0 ) { - sb.append(" "); - } - sb.append( nextRank.getName( )); - } - } - } - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { + + if ( ladderName == null || + ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { + + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + Rank rank = pRank.getRank(); + + if ( rank != null && rank.getRankNext() != null ) { + Rank nextRank = rank.getRankNext(); + + if ( sb.length() > 0 ) { + sb.append(" "); + } + sb.append( nextRank.getName( )); + } + } + } + } + + return sb.toString(); } public String getPlayerNextLinkedRankTag( RankPlayer rankPlayer, String ladderName ) { - StringBuilder sb = new StringBuilder(); - - // Must always have a default rank: - PlayerRank pRankDefault = rankPlayer.getPlayerRankDefault(); - - // Prestiges ladder may not be enabled, or this may be null because they have not yet prestiged: - PlayerRank pRankPrestiges = rankPlayer.getPlayerRankPrestiges(); - - if ( ladderName == null || ladderName.equalsIgnoreCase( LadderManager.LADDER_PRESTIGES ) ) { - - - // If default rank is the last rank, or at the last prestiges rank, - // then get next prestige rank for player: - if ( pRankDefault.getRank().getRankNext() == null ) { - - // If the player does not have a prestiges rank, then get the first one: - if ( pRankPrestiges == null && PrisonRanks.getInstance().getPrestigesLadder() != null ) { - - Rank firstPrestigeRank = PrisonRanks.getInstance().getPrestigesLadder().getLowestRank().orElse(null); - if ( firstPrestigeRank != null ) { - sb.append( firstPrestigeRank.getTag() ); - } - } - // Else if player has a prestige rank, and there is a next prestige rank, get it's tag: - else if ( pRankPrestiges != null && pRankPrestiges.getRank().getRankNext() != null ) { - sb.append( pRankPrestiges.getRank().getRankNext().getTag() ); - - } - - // else, if player has a prestige rank, and it's the last one, then just get that tag: - else if ( pRankPrestiges != null ) { - sb.append( pRankPrestiges.getRank().getTag() ); - - } - - } - // else just get current prestige rank for player: - else if ( pRankPrestiges != null ) { - - sb.append( pRankPrestiges.getRank().getTag() ); - } - } - if ( ladderName == null || ladderName.equalsIgnoreCase( LadderManager.LADDER_DEFAULT ) ) { - - boolean showFirstRank = false; - boolean showNextRank = true; - - - // If at last default rank, then get the default ladder's first rank's tag or just show current tag: - if ( pRankDefault.getRank().getRankNext() == null ) { - - // Since the current default rank is the last, cannot show next default rank: - showNextRank = false; - - Rank firstPrestigeRank = PrisonRanks.getInstance().getPrestigesLadder().getLowestRank().orElse(null); - - // If firstPrestigeRank is null, then prestiges is not enabled, so cannot show first rank: - if ( firstPrestigeRank == null ) { - showFirstRank = false; -// showNextRank = false; - } - - // If current presetiges is null, then use the first prestiges rank: - else if ( pRankPrestiges == null ) { - showFirstRank = true; -// showNextRank = false; - - } - else if ( pRankPrestiges.getRank().getRankNext() == null ) { - // At the last presetiges rank... so do not reset the default ranks: - showFirstRank = false; - } - - else { - // Presetige is possible, so show first default rank: - showFirstRank = true; - - } - - } - - - if ( !showFirstRank && !showNextRank ) { - // Show current rank: - - sb.append( pRankDefault.getRank().getTag() ); - } - else if ( showFirstRank ) { - - Rank firstDefaultRank = PrisonRanks.getInstance().getDefaultLadder().getLowestRank().orElse(null); - sb.append( firstDefaultRank.getTag() ); - } - else { - // Show next rank: - - // Not at last default rank, so get next rank tag: - sb.append( pRankDefault.getRank().getRankNext().getTag() ); - } - - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + // Must always have a default rank: + PlayerRank pRankDefault = rankPlayer.getPlayerRankDefault(); + + // Prestiges ladder may not be enabled, or this may be null because they have not yet prestiged: + PlayerRank pRankPrestiges = rankPlayer.getPlayerRankPrestiges(); + + if ( ladderName == null || ladderName.equalsIgnoreCase( LadderManager.LADDER_PRESTIGES ) ) { + + + // If default rank is the last rank, or at the last prestiges rank, + // then get next prestige rank for player: + if ( pRankDefault.getRank().getRankNext() == null ) { + + // If the player does not have a prestiges rank, then get the first one: + if ( pRankPrestiges == null && PrisonRanks.getInstance().getPrestigesLadder() != null ) { + + Rank firstPrestigeRank = PrisonRanks.getInstance().getPrestigesLadder().getLowestRank().orElse(null); + if ( firstPrestigeRank != null ) { + sb.append( firstPrestigeRank.getTag() ); + } + } + // Else if player has a prestige rank, and there is a next prestige rank, get it's tag: + else if ( pRankPrestiges != null && pRankPrestiges.getRank().getRankNext() != null ) { + sb.append( pRankPrestiges.getRank().getRankNext().getTag() ); + + } + + // else, if player has a prestige rank, and it's the last one, then just get that tag: + else if ( pRankPrestiges != null ) { + sb.append( pRankPrestiges.getRank().getTag() ); + + } + + } + // else just get current prestige rank for player: + else if ( pRankPrestiges != null ) { + + sb.append( pRankPrestiges.getRank().getTag() ); + } + } + if ( ladderName == null || ladderName.equalsIgnoreCase( LadderManager.LADDER_DEFAULT ) ) { + + boolean showFirstRank = false; + boolean showNextRank = true; + + + // If at last default rank, then get the default ladder's first rank's tag or just show current tag: + if ( pRankDefault.getRank().getRankNext() == null ) { + + // Since the current default rank is the last, cannot show next default rank: + showNextRank = false; + + Rank firstPrestigeRank = PrisonRanks.getInstance().getPrestigesLadder().getLowestRank().orElse(null); + + // If firstPrestigeRank is null, then prestiges is not enabled, so cannot show first rank: + if ( firstPrestigeRank == null ) { + showFirstRank = false; + } + + // If current presetiges is null, then use the first prestiges rank: + else if ( pRankPrestiges == null ) { + showFirstRank = true; + + } + else if ( pRankPrestiges.getRank().getRankNext() == null ) { + // At the last presetiges rank... so do not reset the default ranks: + showFirstRank = false; + } + + else { + // Presetige is possible, so show first default rank: + showFirstRank = true; + + } + + } + + + if ( !showFirstRank && !showNextRank ) { + // Show current rank: + + sb.append( pRankDefault.getRank().getTag() ); + } + else if ( showFirstRank ) { + + Rank firstDefaultRank = PrisonRanks.getInstance().getDefaultLadder().getLowestRank().orElse(null); + sb.append( firstDefaultRank.getTag() ); + } + else { + // Show next rank: + + // Not at last default rank, so get next rank tag: + sb.append( pRankDefault.getRank().getRankNext().getTag() ); + } + + } + + return sb.toString(); } public String getPlayerNextRankTag( RankPlayer rankPlayer, String ladderName ) { - StringBuilder sb = new StringBuilder(); - -// boolean hasDefault = false; -// boolean hasPrestige = false; - - if ( !rankPlayer.getLadderRanks().isEmpty()) { - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { - - if ( ladderName == null || - ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { - - PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); - Rank rank = pRank.getRank(); - - if ( rank.getLadder() != null && rank.getLadder().isDefault() && - rank.getRankNext() == null ) { - PlayerRank prestigeRank = rankPlayer.getPlayerRankPrestiges(); - - if ( prestigeRank == null ) { - RankLadder prestigeLadder = PrisonRanks.getInstance() - .getLadderManager().getLadderPrestiges(); - if ( prestigeLadder != null ) { - - // Player does not have any prestige rank, so use the lowest prestige rank: - Rank nextRank = prestigeLadder.getLowestRank().orElseGet( null ); - sb.append( nextRank.getTag() ); - continue; - } - } - else { - // Get current prestige rank - rank = prestigeRank.getRank(); - } - - } - - if ( rank != null && rank.getRankNext() != null ) { - Rank nextRank = rank.getRankNext(); - -// if ( sb.length() > 0 ) { -// sb.append(", "); -// } - - sb.append( nextRank.getTag() ); - } - } - } - } - - - // NOTE: Only for the last rank on the default ladder, use the text value - // from the language file to display in the place of the empty tag. - // The idea is that if prestiges is enabled, then this is a way to - // indicate the player could prestige as the next step. - if ( sb.length() == 0 && LadderManager.LADDER_DEFAULT.equalsIgnoreCase( ladderName ) ) { - String replacementText = lastRankMessageForDefaultLadder(); - if ( replacementText != null && !replacementText.trim().isEmpty() ) { - - sb.append( replacementText ); - } - } - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + if ( !rankPlayer.getLadderRanks().isEmpty()) { + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + for ( RankLadder ladder : rankPlayer.getLadderRanks().keySet() ) { + + if ( ladderName == null || + ladderName != null && ladder.getName().equalsIgnoreCase( ladderName )) { + + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + Rank rank = pRank.getRank(); + + if ( rank.getLadder() != null && rank.getLadder().isDefault() && + rank.getRankNext() == null ) { + PlayerRank prestigeRank = rankPlayer.getPlayerRankPrestiges(); + + if ( prestigeRank == null ) { + RankLadder prestigeLadder = PrisonRanks.getInstance() + .getLadderManager().getLadderPrestiges(); + if ( prestigeLadder != null ) { + + // Player does not have any prestige rank, so use the lowest prestige rank: + Rank nextRank = prestigeLadder.getLowestRank().orElseGet( null ); + sb.append( nextRank.getTag() ); + continue; + } + } + else { + // Get current prestige rank + rank = prestigeRank.getRank(); + } + + } + + if ( rank != null && rank.getRankNext() != null ) { + Rank nextRank = rank.getRankNext(); + + sb.append( nextRank.getTag() ); + } + } + } + } + + + // NOTE: Only for the last rank on the default ladder, use the text value + // from the language file to display in the place of the empty tag. + // The idea is that if prestiges is enabled, then this is a way to + // indicate the player could prestige as the next step. + if ( sb.length() == 0 && LadderManager.LADDER_DEFAULT.equalsIgnoreCase( ladderName ) ) { + String replacementText = lastRankMessageForDefaultLadder(); + if ( replacementText != null && !replacementText.trim().isEmpty() ) { + + sb.append( replacementText ); + } + } + + return sb.toString(); } private String getPlayerSellallMultiplier( RankPlayer rankPlayer, PlaceholderAttributeNumberFormat attributeNFormat ) { - String results; - double multiplier = rankPlayer.getSellAllMultiplier(); - if ( attributeNFormat != null ) { - - results = attributeNFormat.format( multiplier ); - } - else { - results = Double.toString( multiplier ); + String results = ""; + + UUID pUuid = rankPlayer.getUUID(); + + Player player = + Prison.get().getPlatform().getPlayer( pUuid ).orElse( + Prison.get().getPlatform().getOfflinePlayer( pUuid ).orElse(null) + ); + + if ( player != null ) { + + double multiplier = player.getSellAllMultiplier(); + + if ( attributeNFormat != null ) { + + results = attributeNFormat.format( multiplier ); + } + else { + results = Double.toString( multiplier ); + } } + return results; } @@ -1513,7 +1335,7 @@ private String getPlayerSellallMultiplier( RankPlayer rankPlayer, PlaceholderAtt public String getTranslatePlayerPlaceHolder( PlaceholderIdentifier identifier ) { - Player player = identifier.getPlayer(); + Player player = identifier.getPlayer(); PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); RankPlayer rankPlayer = null; @@ -1545,9 +1367,6 @@ public String getTranslatePlayerPlaceHolder( PlaceholderIdentifier identifier ) PlaceholderAttributeNumberFormat attributeNFormat = identifier.getAttributeNFormat(); PlaceholderAttributeText attributeText = identifier.getAttributeText(); -// int sequence = identifier.getSequence(); - - PrisonPlaceHolders placeHolder = placeHolderKey.getPlaceholder(); @@ -2011,7 +1830,6 @@ public String getTranslatePlayerPlaceHolder( PlaceholderIdentifier identifier ) // results = applySecondaryPlaceholders( rankPlayer, results ); - if ( attributeText != null && results != null ) { results = attributeText.format( results ); @@ -2053,6 +1871,7 @@ public String getTranslatePlayerPlaceHolder( PlaceholderIdentifier identifier ) * @param results * @return */ + @SuppressWarnings("unused") private String applySecondaryPlaceholders(RankPlayer rankPlayer, String results) { results = applySecondaryPlaceholdersCheck( "{player}", rankPlayer.getName(), results ); @@ -2115,84 +1934,115 @@ private String applySecondaryPlaceholdersCheck( String placeholder, String value @Override public List getTranslatedPlaceHolderKeys() { - if ( translatedPlaceHolderKeys == null ) { - translatedPlaceHolderKeys = new ArrayList<>(); - - // This generates all of the placeholders for the player ranks: - List placeHolders = PrisonPlaceHolders.getTypes( PlaceholderFlags.PLAYER ); - for ( PrisonPlaceHolders ph : placeHolders ) { - PlaceHolderKey placeholder = new PlaceHolderKey(ph.name(), ph ); - if ( ph.getAlias() != null ) { - String aliasName = ph.getAlias().name(); - placeholder.setAliasName( aliasName ); - } - - translatedPlaceHolderKeys.add( placeholder ); - - // Getting too many placeholders... add back the extended prefix when looking up: - -// // Now generate a new key based upon the first key, but without the prison_ prefix: -// String key2 = ph.name().replace( -// IntegrationManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED, "" ); -// PlaceHolderKey placeholder2 = new PlaceHolderKey(key2, ph, false ); -// translatedPlaceHolderKeys.add( placeholder2 ); - } - - - // This generates all of the placeholders for the ladders: - placeHolders = PrisonPlaceHolders.getTypes( PlaceholderFlags.LADDERS ); - - List ladders = PrisonRanks.getInstance().getLadderManager().getLadders(); - for ( RankLadder ladder : ladders ) { - for ( PrisonPlaceHolders ph : placeHolders ) { - - if ( ph.hasFlag( PlaceholderFlags.ONLY_DEFAULT_OR_PRESTIGES ) && - !ladder.getName().equalsIgnoreCase( LadderManager.LADDER_DEFAULT ) && - !ladder.getName().equalsIgnoreCase( LadderManager.LADDER_PRESTIGES ) - ) { - // Placeholder is invalid for ladders that are not default or prestiges, so skip: - continue; - } - - String key = ph.name().replace( - PlaceholderManager.PRISON_PLACEHOLDER_LADDERNAME_SUFFIX, "_" + ladder.getName() ). - toLowerCase(); - - PlaceHolderKey placeholder = new PlaceHolderKey(key, ph, ladder.getName() ); - if ( ph.getAlias() != null ) { - String aliasName = ph.getAlias().name().replace( - PlaceholderManager.PRISON_PLACEHOLDER_LADDERNAME_SUFFIX, "_" + ladder.getName() ). - toLowerCase(); - placeholder.setAliasName( aliasName ); - } - translatedPlaceHolderKeys.add( placeholder ); - - // Getting too many placeholders... add back the extended prefix when looking up: - -// // Now generate a new key based upon the first key, but without the prison_ prefix: -// String key2 = key.replace( -// IntegrationManager.PRISON_PLACEHOLDER_PREFIX_EXTENDED, "" ); -// PlaceHolderKey placeholder2 = new PlaceHolderKey(key2, ph, ladder.name, false ); -// translatedPlaceHolderKeys.add( placeholder2 ); - - } - - } - - } - - return translatedPlaceHolderKeys; + if ( translatedPlaceHolderKeys == null ) { + translatedPlaceHolderKeys = new ArrayList<>(); + + // This generates all of the placeholders for the player ranks: + List placeHolders = PrisonPlaceHolders.getTypes( PlaceholderFlags.PLAYER ); + for ( PrisonPlaceHolders ph : placeHolders ) { + PlaceHolderKey placeholder = new PlaceHolderKey(ph.name(), ph ); + if ( ph.getAlias() != null ) { + String aliasName = ph.getAlias().name(); + placeholder.setAliasName( aliasName ); + } + + translatedPlaceHolderKeys.add( placeholder ); + + } + + + // This generates all of the placeholders for the ladders: + placeHolders = PrisonPlaceHolders.getTypes( PlaceholderFlags.LADDERS ); + + List ladders = PrisonRanks.getInstance().getLadderManager().getLadders(); + for ( RankLadder ladder : ladders ) { + for ( PrisonPlaceHolders ph : placeHolders ) { + + if ( ph.hasFlag( PlaceholderFlags.ONLY_DEFAULT_OR_PRESTIGES ) && + !ladder.getName().equalsIgnoreCase( LadderManager.LADDER_DEFAULT ) && + !ladder.getName().equalsIgnoreCase( LadderManager.LADDER_PRESTIGES ) + ) { + // Placeholder is invalid for ladders that are not default or prestiges, so skip: + continue; + } + + String key = ph.name().replace( + PlaceholderManager.PRISON_PLACEHOLDER_LADDERNAME_SUFFIX, "_" + ladder.getName() ). + toLowerCase(); + + PlaceHolderKey placeholder = new PlaceHolderKey(key, ph, ladder.getName() ); + if ( ph.getAlias() != null ) { + String aliasName = ph.getAlias().name().replace( + PlaceholderManager.PRISON_PLACEHOLDER_LADDERNAME_SUFFIX, "_" + ladder.getName() ). + toLowerCase(); + placeholder.setAliasName( aliasName ); + } + translatedPlaceHolderKeys.add( placeholder ); + + } + + } + + } + + return translatedPlaceHolderKeys; } @Override public void reloadPlaceholders() { - // clear the class variable so they will regenerate: - translatedPlaceHolderKeys = null; - - // Regenerate the translated placeholders: - getTranslatedPlaceHolderKeys(); + // clear the class variable so they will regenerate: + translatedPlaceHolderKeys = null; + + // Regenerate the translated placeholders: + getTranslatedPlaceHolderKeys(); } + public void unloadAllPlayers() { + + for (RankPlayer player : getPlayers() ) { + + if ( player.isDirty() ) { + savePlayer(player); + } + } + + getPlayers().clear(); + getPlayersByName().clear(); + + getPlayerErrors().clear(); + } + + + public void loadAllPlayers() + throws IOException { + Output.get().logInfo( "Ranks: Loading Players..." ); + + loadPlayers(); + + + + // Hook up all players to the ranks: + // - parameter checkPlayerBalances is set to false + connectPlayersToRanks( false ); + + Output.get().logInfo( "Ranks: Finished Connecting Players to Ranks." ); + } + + + public void reloadAllPlayers() + throws IOException { + + synchronized ( getPlayers() ) { + + unloadAllPlayers(); + + + loadAllPlayers(); + + reloadPlaceholders(); + } + } + } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManagerMessages.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManagerMessages.java index 03a075179..88cec16e5 100644 --- a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManagerMessages.java +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/managers/PlayerManagerMessages.java @@ -87,7 +87,4 @@ protected String lastRankMessageForDefaultLadder() { .localize(); } - - - } 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 561bb8c87..8bc53ba50 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 @@ -68,10 +68,6 @@ public class RankManager implements ManagerPlaceholders { - /* - * Fields & Constants - */ - private Collection collection; private List loadedRanks; @@ -85,93 +81,112 @@ public class RankManager private List translatedPlaceHolderKeys; + private transient boolean enabled; + public enum RanksByLadderOptions { - playersOnly("players"), - allRanks("all"), - full; - - - private final String altName; - - private RanksByLadderOptions() { - this.altName = null; - } - - private RanksByLadderOptions( String altName ) { - this.altName = altName; - } - - public static RanksByLadderOptions fromString( String value ) { - RanksByLadderOptions results = null; - - for ( RanksByLadderOptions opt : values() ) { - if ( opt.name().equalsIgnoreCase( value ) || - opt.getAltName() != null && opt.getAltName().equalsIgnoreCase( value )) { - results = opt; - break; + playersOnly("players"), + allRanks("all"), + full; + + + private final String altName; + + private RanksByLadderOptions() { + this.altName = null; + } + + private RanksByLadderOptions( String altName ) { + this.altName = altName; + } + + public static RanksByLadderOptions fromString( String value ) { + RanksByLadderOptions results = null; + + for ( RanksByLadderOptions opt : values() ) { + if ( opt.name().equalsIgnoreCase( value ) || + opt.getAltName() != null && opt.getAltName().equalsIgnoreCase( value )) { + results = opt; + break; + } } - } - - return results; - } + + return results; + } public String getAltName() { return altName; } } - /* - * Constructor - */ - - /** - * Instantiate this {@link RankManager}. - */ + + public RankManager() { + this.collection = null; + + this.loadedRanks = new ArrayList<>(); + this.ranksByName = new TreeMap<>(); + this.ranksById = new TreeMap<>(); + + this.enabled = false; + } + public RankManager(Collection collection) { + this(); + + this.enabled = true; + this.collection = collection; - this.loadedRanks = new ArrayList<>(); - this.ranksByName = new TreeMap<>(); - this.ranksById = new TreeMap<>(); } - private void addRank( Rank rank ) { - if ( rank != null ) { - getLoadedRanks().add( rank ); - String rankName = rank.getName(); - getRanksByName().put( rankName.toLowerCase(), rank ); - getRanksById().put( rank.getId(), rank ); - - // Do not have to reset position number since the new rank is - // added to the end of the ladder's rank List, and therefore - // no other rank is impacted. - } + public boolean isEnabled() { + return enabled; + } + + + private void addRank( Rank rank ) { + if ( rank != null ) { + getLoadedRanks().add( rank ); + String rankName = rank.getName(); + getRanksByName().put( rankName.toLowerCase(), rank ); + + if ( rank.getId() != -1 ) { + getRanksById().put( rank.getId(), rank ); + } + + // Do not have to reset position number since the new rank is + // added to the end of the ladder's rank List, and therefore + // no other rank is impacted. + } } private void removeRankFromCollections( Rank rank ) { - if ( rank != null ) { - getLoadedRanks().remove( rank ); - getRanksByName().remove( rank.getName().toLowerCase() ); - getRanksById().remove( rank.getId() ); - - // Since the removal of a rank could shift the position of - // more than one rank, then all positions should be reset. - - resetRankPositions( rank ); - } + if ( rank != null ) { + getLoadedRanks().remove( rank ); + getRanksByName().remove( rank.getName().toLowerCase() ); + + if ( rank.getId() != -1 && getRanksById().containsKey( rank.getId() ) ) { + + getRanksById().remove( rank.getId() ); + } + + // Since the removal of a rank could shift the position of + // more than one rank, then all positions should be reset. + + resetRankPositions( rank ); + } } private void resetRankPositions( Rank rank ) { - if ( rank != null && rank.getLadder() != null ) { - - for ( Rank r : rank.getLadder().getRanks() ) { - r.resetPosition(); - } - } + if ( rank != null && rank.getLadder() != null ) { + + for ( Rank r : rank.getLadder().getRanks() ) { + r.resetPosition(); + } + } } @@ -188,7 +203,6 @@ public void loadRank(String rankFile) throws IOException { RankFactory rankFactory = new RankFactory(); addRank( rankFactory.createRank( document ) ); -// loadedRanks.add(new Rank(document)); } /** @@ -204,25 +218,43 @@ public void loadRanks() throws IOException { for ( Document rankDocument : ranks ) { - Rank rank = rankFactory.createRank( rankDocument ); - addRank( rank ); - } + Rank rank = rankFactory.createRank( rankDocument ); + addRank( rank ); + + // If old file exists, then set dirty so it can be saved and update the file name: + checkIfOldFileExists( rank ); + + if ( rank.isDirty() ) { + saveRank(rank); + } + } -// ranks.forEach(document -> addRank(new Rank(document))); -// ranks.forEach(document -> loadedRanks.add(new Rank(document))); } + + /** + * If the old file name exists, then this ladder has not been upgraded + * yet. So set it to dirty so it can be saved and update the file name. + * + * @param ladder + */ + private void checkIfOldFileExists(Rank rank) { + if ( collection.exists( rank.filenameOld() )) { + rank.setDirty( true ); + } + } + /** * Saves a rank to its save file. * * @param rank The {@link Rank} to save. * @param saveFile The key to write the rank as. Case sensitive. */ - public void saveRank(Rank rank, String saveFile) { + public void saveRank(Rank rank, String saveFileNew, String saveFileOld ) { - RankFactory rankFactory = new RankFactory(); - - collection.save(saveFile, rankFactory.toDocument( rank ) ); + RankFactory rankFactory = new RankFactory(); + + collection.save(saveFileNew, rankFactory.toDocument( rank ), saveFileOld, "Ranks" ); } /** @@ -231,7 +263,7 @@ public void saveRank(Rank rank, String saveFile) { * @param rank The {@link Rank} to save. */ public void saveRank(Rank rank) { - this.saveRank(rank, rank.filename()); + this.saveRank(rank, rank.filenameNew(), rank.filenameOld() ); } /** @@ -258,14 +290,12 @@ public void saveRanks() { public Optional createRank(String name, String tag, double cost) { // Set the default values... - Rank newRank = new Rank( getNextAvailableId(), name, tag, cost ); + // rank id is no longer used, so use -1: + Rank newRank = new Rank( -1, name, tag, cost ); // ... add it to the list... addRank(newRank); -// // Reset the rank relationships: -// connectRanks(); - // ...and return it. return Optional.of(newRank); } @@ -276,24 +306,18 @@ public Optional createRank(String name, String tag, double cost) { * * @return The next available rank's ID. */ - private int getNextAvailableId() { - - int current = (getRanksById().size() == 0 ? - -1 : getRanksById().lastKey().intValue()); - - return current + 1; + @SuppressWarnings("unused") + private int getNextAvailableId() { -// // Set the highest to -1 for now, since we'll add one at the end -// int highest = -1; -// -// // If anything's higher, it's now the highest... -// for (Rank rank : loadedRanks) { -// if (highest < rank.id) { -// highest = rank.id; -// } -// } -// -// return highest + 1; + int current = -1; + + for (Rank rank : loadedRanks) { + if ( rank.getId() != -1 && rank.getId() > current ) { + current = rank.getId(); + } + } + + return current + 1; } /** @@ -319,18 +343,11 @@ public Optional getRankOptional(String name) { * @return */ public Rank getRank(String name) { - return name == null ? null : getRanksByName().get( name.toLowerCase() ); + return name == null || !isEnabled() ? + null : + getRanksByName().get( name.toLowerCase() ); } - -// Not used anywhere... -// /** -// * Returns the first rank that has an escaped name that has the & replaced with -. -// */ -// public Rank getRankEscaped(String name) { -// return loadedRanks.stream().filter(rank -> -// rank.getName().replace( "&", "-" ).equals(name)).findFirst().orElse( null ); -// } /** * Removes the provided rank. This will go through the process of removing the rank from the loaded @@ -344,106 +361,86 @@ public Rank getRank(String name) { public boolean removeRank(Rank rank) { // ... remove it from each user, bumping them down to the next lowest rank... - final Rank newRank = ( rank.getRankPrior() != null ? - rank.getRankPrior() : - rank.getRankNext() ); - if ( newRank == null ) { - Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankManager__remove_rank_warning" ); - - Output.get().logError( localManagerLog.localize() ); - } - - - boolean success = true; - - RankLadder ladder = rank.getLadder(); + final Rank newRank = ( rank.getRankPrior() != null ? + rank.getRankPrior() : + rank.getRankNext() ); + if ( newRank == null ) { + Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankManager__remove_rank_warning" ); + + Output.get().logError( localManagerLog.localize() ); + } + + + boolean success = true; + + RankLadder ladder = rank.getLadder(); // for (RankLadder ladder : PrisonRanks.getInstance().getLadderManager() .getLadder( rank )) { - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); // Move each player in this ladder to the new rank PrisonRanks.getInstance().getPlayerManager().getPlayers().forEach(rankPlayer -> { - PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); - if ( pRank != null && pRank.getRank() != null ) { - - Rank curRank = pRank.getRank(); - if ( curRank != null && rank.equals( curRank ) ) { - rankPlayer.removeRank(curRank); - if ( newRank != null ) { - rankPlayer.addRank(newRank); - } - - rankPlayer.setDirty( true ); - - PrisonRanks.getInstance().getPlayerManager().savePlayer(rankPlayer); - - -// try { -// } catch (IOException e) { -// Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() -// .getLocalizable( "ranks_rankManager__cannot_save_player_file" ); -// -// Output.get().logError( localManagerLog.localize() ); -// } - - Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankManager__cannot_save_player_file" ) - .withReplacements( - rankPlayer.getName(), - newRank.getName() ); - PrisonAPI.debug( localManagerLog.localize() ); - } - } + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, ladder ); + if ( pRank != null && pRank.getRank() != null ) { + + Rank curRank = pRank.getRank(); + if ( curRank != null && rank.equals( curRank ) ) { + rankPlayer.removeRank(curRank); + if ( newRank != null ) { + rankPlayer.addRank(newRank); + } + + rankPlayer.setDirty( true ); + + PrisonRanks.getInstance().getPlayerManager().savePlayer(rankPlayer); + + Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankManager__cannot_save_player_file" ) + .withReplacements( + rankPlayer.getName(), + newRank.getName() ); + PrisonAPI.debug( localManagerLog.localize() ); + } + } }); // ... remove it from each ladder it was in... ladder.removeRank( rank ); -// ladder.removeRank(ladder.getPositionOfRank(rank)); if ( !PrisonRanks.getInstance().getLadderManager().save(ladder) ) { - success = false; - - Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankManager__cannot_save_ladder_file" ) - .withReplacements( ladder.getName() ); - - Output.get().logError( localManagerLog.localize() ); + success = false; + + Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankManager__cannot_save_ladder_file" ) + .withReplacements( ladder.getName() ); + + Output.get().logError( localManagerLog.localize() ); } } if( success ) { - // Remove it from the list... - removeRankFromCollections( rank ); - - // Reset the rank relationships: - // connectRanks(); - - // ... and remove the rank's save files. - collection.delete(rank.filename()); + // Remove it from the list... + removeRankFromCollections( rank ); + + + // ... and remove the rank's save files. + // try both the old and new names: + collection.delete(rank.filenameNew()); + collection.delete(rank.filenameOld()); } return success; } -// /** -// * Returns the rank with the specified ID. -// * -// * @param id The rank's ID. -// * @return An optional containing either the {@link Rank} if it could be found, or empty if it does not exist by the specified id. -// */ -// @Deprecated -// public Optional getRankOptional(int id) { -// return loadedRanks.stream().filter(rank -> rank.getId() == id).findFirst(); -// } public Rank getRank( int id ) { - return getRanksById().get( id ); + return getRanksById().get( id ); } /** @@ -455,46 +452,6 @@ public List getRanks() { return loadedRanks; } -// /** -// *

    This should be ran after the RanksManager and LadderManger are loaded. Or any -// * time a rank is add, removed, or position changed within a ladder. -// *

    -// * -// *

    This function will set the temporal rankPrior and rankNext value in -// * each rank based upon each ladder. This will greatly simplify walking the -// * ladder by using the linked ranks without having to perform any expensive -// * calculations. -// *

    -// */ -// public void connectRanks() { -// LadderManager lman = PrisonRanks.getInstance().getLadderManager(); -// -// for ( RankLadder rLadder : lman.getLadders() ) { -// -// rLadder.getPositionRanks().sort(Comparator.comparingInt(PositionRank::getPosition)); -// -// Rank rankLast = null; -// for ( PositionRank pRank : rLadder.getPositionRanks() ) { -// if ( pRank != null && pRank.getPosition() >= 0 ) { -// Optional opRank = rLadder.getByPosition(pRank.getPosition()); -// if ( opRank.isPresent() ) { -// Rank rank = opRank.get(); -// -// // reset the rankPrior and rankNext in case there are no hookups: -// // Important if ranks are removed, or inserted, or moved: -// rank.setRankPrior( null ); -// rank.setRankNext( null ); -// -// if ( rankLast != null ) { -// rank.setRankPrior( rankLast ); -// rankLast.setRankNext( rank ); -// } -// rankLast = rank; -// } -// } -// } -// } -// } /* *

    This function will go through ranks and find ranks that have defined currencies. @@ -515,7 +472,7 @@ public List getRanks() { * */ public void identifyAllRankCurrencies( List prisonStartupDetails ) { - for ( Rank rank : loadedRanks ) { + for ( Rank rank : loadedRanks ) { if ( rank.getCurrency() != null ) { EconomyCurrencyIntegration currencyEcon = PrisonAPI.getIntegrationManager() .getEconomyForCurrency( rank.getCurrency() ); @@ -525,7 +482,7 @@ public void identifyAllRankCurrencies( List prisonStartupDetails ) { .getLocalizable( "ranks_rankManager__failure_no_economy" ) .withReplacements( rank.getCurrency(), rank.getName() ); - Output.get().logError( localManagerLog.localize() ); + Output.get().logError( localManagerLog.localize() ); prisonStartupDetails.add( localManagerLog.localize() ); } @@ -537,68 +494,58 @@ public void identifyAllRankCurrencies( List prisonStartupDetails ) { public String listAllRanks( String ladderName, List ranks, RanksByLadderOptions option ) { - StringBuilder sb = new StringBuilder(); - - sb.append( "&7 " ); - sb.append( ladderName ); - sb.append( ": " ); - -// PlayerManager playerManager = PrisonRanks.getInstance().getPlayerManager(); - - int count = 0; - for (Rank rank : ranks ) { - - int players = rank.getPlayers().size(); - - // Get the players per rank!! -// List playersList = -// playerManager.getPlayers().stream() -// .filter(rankPlayer -> rankPlayer.getLadderRanks().values().contains(rank)) -// .collect(Collectors.toList()); -// int players = playersList.size(); - - if ( option == RanksByLadderOptions.allRanks || - option == RanksByLadderOptions.full || players > 0 ) { - if ( count++ > 0 ) { - sb.append( ", " ); - - if ( count >= 10 && (count - 1) % 15 == 0 ) { - sb.append( "{br} " ); - } - } - - - sb.append( " " ).append( rank.getName() ); - - if ( players > 0 ) { - - sb.append( " (" ).append( players ).append( ")" ); - - if ( option == RanksByLadderOptions.full ) { - sb.append( "[" ); - - for ( RankPlayer rankPlayer : rank.getPlayers() ) - { - if ( rankPlayer.getName() != null ) { - - sb.append( rankPlayer.getName() ).append( " " ); - } + StringBuilder sb = new StringBuilder(); + + sb.append( "&7 " ); + sb.append( ladderName ); + sb.append( ": " ); + + int count = 0; + for (Rank rank : ranks ) { + + int players = rank.getPlayers().size(); + + if ( option == RanksByLadderOptions.allRanks || + option == RanksByLadderOptions.full || players > 0 ) { + if ( count++ > 0 ) { + sb.append( ", " ); + + if ( count >= 10 && (count - 1) % 15 == 0 ) { + sb.append( "{br} " ); + } + } + + + sb.append( " " ).append( rank.getName() ); + + if ( players > 0 ) { + + sb.append( " (" ).append( players ).append( ")" ); + + if ( option == RanksByLadderOptions.full ) { + sb.append( "[" ); + + for ( RankPlayer rankPlayer : rank.getPlayers() ) { + if ( rankPlayer.getName() != null ) { + + sb.append( rankPlayer.getName() ).append( " " ); + } } - - // if last character is a space, then remove it: - if ( sb.charAt( sb.length() - 1 ) == ' ' ) { - sb.setLength( sb.length() - 1 ); - } - sb.append( "]" ); - } - - } - - - } + + // if last character is a space, then remove it: + if ( sb.charAt( sb.length() - 1 ) == ' ' ) { + sb.setLength( sb.length() - 1 ); + } + sb.append( "]" ); + } + + } + + + } } - - return sb.toString(); + + return sb.toString(); } @@ -609,13 +556,13 @@ public String listAllRanks( String ladderName, List ranks, RanksByLadderOp * @param includeAll If true then includes all ranks, otherwise just ranks within one more players */ public List ranksByLadders() { - return ranksByLadders( "all", RanksByLadderOptions.allRanks ); + return ranksByLadders( "all", RanksByLadderOptions.allRanks ); } public void ranksByLadders( CommandSender sender, RanksByLadderOptions option ) { - List results = ranksByLadders( "all", option ); - for (String msg : results) { - rankByLadderOutput( sender, msg ); + List results = ranksByLadders( "all", option ); + for (String msg : results) { + rankByLadderOutput( sender, msg ); } } @@ -628,46 +575,46 @@ public void ranksByLadders( CommandSender sender, String ladderName, RanksByLadd } private List ranksByLadders( String ladderName, RanksByLadderOptions option ) { - List results = new ArrayList<>(); - - - Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() - .getLocalizable( "ranks_rankManager__ranks_by_ladders" ); - - results.add( localManagerLog.localize() ); - - // Track which ranks were included in the ladders listed: - List ranksIncluded = new ArrayList<>(); - - for ( RankLadder ladder : PrisonRanks.getInstance().getLadderManager().getLadders() ) { - if ( ladderName.equalsIgnoreCase( "all" ) || ladderName.equalsIgnoreCase( ladder.getName() ) ) { - - List ladderRanks = ladder.getRanks(); - ranksIncluded.addAll( ladderRanks ); - - String ranksByLadder = listAllRanks( ladder.getName(), ladderRanks, option ); - - results.add( ranksByLadder ); - } - } - - if ( ladderName.equalsIgnoreCase( "all" ) || ladderName.equalsIgnoreCase( "none" ) ) { - - // Next we need to get a list of all ranks that were not included. Use set - List ranksExcluded = new ArrayList<>( loadedRanks ); - ranksExcluded.removeAll( ranksIncluded ); - - // Next generate a list of ranks that are not associated with any ladder: - // NOTE: No players should be associated with ranks that are not tied to a ladder, - // so enable "true" for includeAll to list all ranks that are not tied to ladders - // since player count will always be zero. - // Update: Set the RanksByLadderOptions to full - String ranksByLadder = listAllRanks( "(*no-ladder*)", ranksExcluded, RanksByLadderOptions.full ); - - results.add( ranksByLadder ); - } - - return results; + List results = new ArrayList<>(); + + + Localizable localManagerLog = PrisonRanks.getInstance().getRanksMessages() + .getLocalizable( "ranks_rankManager__ranks_by_ladders" ); + + results.add( localManagerLog.localize() ); + + // Track which ranks were included in the ladders listed: + List ranksIncluded = new ArrayList<>(); + + for ( RankLadder ladder : PrisonRanks.getInstance().getLadderManager().getLadders() ) { + if ( ladderName.equalsIgnoreCase( "all" ) || ladderName.equalsIgnoreCase( ladder.getName() ) ) { + + List ladderRanks = ladder.getRanks(); + ranksIncluded.addAll( ladderRanks ); + + String ranksByLadder = listAllRanks( ladder.getName(), ladderRanks, option ); + + results.add( ranksByLadder ); + } + } + + if ( ladderName.equalsIgnoreCase( "all" ) || ladderName.equalsIgnoreCase( "none" ) ) { + + // Next we need to get a list of all ranks that were not included. Use set + List ranksExcluded = new ArrayList<>( loadedRanks ); + ranksExcluded.removeAll( ranksIncluded ); + + // Next generate a list of ranks that are not associated with any ladder: + // NOTE: No players should be associated with ranks that are not tied to a ladder, + // so enable "true" for includeAll to list all ranks that are not tied to ladders + // since player count will always be zero. + // Update: Set the RanksByLadderOptions to full + String ranksByLadder = listAllRanks( "(*no-ladder*)", ranksExcluded, RanksByLadderOptions.full ); + + results.add( ranksByLadder ); + } + + return results; } private void rankByLadderOutput( CommandSender sender, String ranksByLadder ) { @@ -703,12 +650,12 @@ else if ( formatted ) { public String getTranslateRanksPlaceHolder( PlaceholderIdentifier identifier ) { - Player player = identifier.getPlayer(); + Player player = identifier.getPlayer(); PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); RankPlayer rankPlayer = pm.getPlayer( player ); - PlaceHolderKey placeHolderKey = identifier.getPlaceholderKey(); + PlaceHolderKey placeHolderKey = identifier.getPlaceholderKey(); String rankName = placeHolderKey.getData(); @@ -716,10 +663,11 @@ public String getTranslateRanksPlaceHolder( PlaceholderIdentifier identifier ) { - PlaceholderAttributeBar attributeBar = identifier.getAttributeBar(); - PlaceholderAttributeNumberFormat attributeNFormat = identifier.getAttributeNFormat(); - PlaceholderAttributeText attributeText = identifier.getAttributeText(); - PlaceholderAttributeTime attributeTime = identifier.getAttributeTime(); + PlaceholderAttributeBar attributeBar = identifier.getAttributeBar(); + PlaceholderAttributeNumberFormat attributeNFormat = identifier.getAttributeNFormat(); + PlaceholderAttributeText attributeText = identifier.getAttributeText(); + @SuppressWarnings("unused") + PlaceholderAttributeTime attributeTime = identifier.getAttributeTime(); int sequence = identifier.getSequence(); @@ -739,11 +687,6 @@ public String getTranslateRanksPlaceHolder( PlaceholderIdentifier identifier ) { ) { -// if ( !( isStatsPlayers ) && -// rank != null && -// ( rankPlayer != null || -// rankPlayer == null && isStatsRank ) ) { - identifier.setFoundAMatch( true ); switch ( placeHolder ) { @@ -772,7 +715,7 @@ public String getTranslateRanksPlaceHolder( PlaceholderIdentifier identifier ) { if ( attributeNFormat != null ) { results = attributeNFormat.format( cost ); - } + } else { results = PlaceholdersUtil.formattedMetricSISize( cost ); @@ -786,18 +729,17 @@ public String getTranslateRanksPlaceHolder( PlaceholderIdentifier identifier ) { { double cost = calculateRankCost( rankPlayer, rank ); double balance = rankPlayer.getBalance( rank.getCurrency() ); -// double balance = pm.getPlayerBalance( rankPlayer, rank); double remaining = cost - balance; if ( remaining < 0 ) { - remaining = 0; - } + remaining = 0; + } if ( attributeNFormat != null ) { results = attributeNFormat.format( remaining ); - } + } else { results = dFmt.format( remaining ); @@ -810,18 +752,17 @@ public String getTranslateRanksPlaceHolder( PlaceholderIdentifier identifier ) { { double cost = calculateRankCost( rankPlayer, rank ); double balance = rankPlayer.getBalance( rank.getCurrency() ); -// double balance = pm.getPlayerBalance( rankPlayer, rank); double remaining = cost - balance; if ( remaining < 0 ) { remaining = 0; - } + } if ( attributeNFormat != null ) { results = attributeNFormat.format( remaining ); - } + } else { results = PlaceholdersUtil.formattedMetricSISize( remaining ); @@ -838,13 +779,12 @@ public String getTranslateRanksPlaceHolder( PlaceholderIdentifier identifier ) { { double cost = calculateRankCost( rankPlayer, rank ); double balance = rankPlayer.getBalance( rank.getCurrency() ); -// double balance = pm.getPlayerBalance( rankPlayer, rank); double percent = (balance < 0 ? 0 : (cost == 0.0d || balance > cost ? 100.0 : balance / cost * 100.0 ) ); - results = dFmt.format( percent ); + results = dFmt.format( percent ); } break; @@ -853,7 +793,6 @@ public String getTranslateRanksPlaceHolder( PlaceholderIdentifier identifier ) { { double cost = calculateRankCost( rankPlayer, rank ); double balance = rankPlayer.getBalance( rank.getCurrency() ); -// double balance = pm.getPlayerBalance( rankPlayer, rank); results = PlaceholderManagerUtils.getInstance(). getProgressBar( balance, cost, false, attributeBar ); @@ -1027,7 +966,7 @@ else if ( placeHolder == PrisonPlaceHolders.prison_top_player_balance_raw_nnn_tp if ( attributeNFormat != null ) { results = attributeNFormat.format( rankScore ); - } + } else { results = dFmt.format(rankScore); } @@ -1077,7 +1016,7 @@ else if ( placeHolder == PrisonPlaceHolders.prison_top_player_balance_raw_nnn_tp if ( attributeNFormat != null ) { results = attributeNFormat.format( rsPenalty ); - } + } else if ( placeHolder == PrisonPlaceHolders.prison_top_player_penalty_formatted_nnn_tp || placeHolder == PrisonPlaceHolders.prison_tppf_nnn_tp ) { @@ -1211,10 +1150,12 @@ else if ( placeHolder == PrisonPlaceHolders.prison_top_player_penalty_raw_nnn_tp PlayerRank pRank = rankPlayer.calculateTargetPlayerRank( rank ); -// RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); -// PlayerRank pRank = rankPlayerFactory.createPlayerRank( rank ); - - results = Double.toString( pRank.getLadderBasedRankMultiplier() ); + if ( pRank == null ) { + results = ""; + } + else { + results = Double.toString( pRank.getLadderBasedRankMultiplier() ); + } break; @@ -1310,7 +1251,7 @@ else if ( Output.get().isDebug() ) { private RankPlayer getTopNRankPlayer( int rankPosition ) { - return TopNPlayers.getInstance().getTopNRankPlayer( rankPosition ); + return TopNPlayers.getInstance().getTopNRankPlayer( rankPosition ); } @@ -1360,42 +1301,6 @@ private double calculateRankCost( RankPlayer rankPlayer, Rank targetRank ) } -// PlayerRank playerRank = rankPlayerFactory.getRank( rankPlayer, targetRank.getLadder() ); - - -// if ( playerRank != null ) { -// -// -//// List -// -// -// // If the player is at a higher rank, or the same rank, then the cost will be -// // zero for the rank that is being passed in, since the player has -// // already paid for that rank. -// if ( rank.getPosition() <= playerRank.getRank().getPosition() ) { -// cost = 0; -// } -// else { -// //cost = playerRank.getRankCost(); -// Rank nextRank = playerRank.getRank(); -// -// while ( nextRank != null && -// nextRank.getPosition() <= targetRank.getPosition() ) { -// -// // Need to calculate the next PlayerRank value for the next rank: -// -// // This calculates the target rank, and takes in to consideration the player's existing rank: -// playerRank = playerRank.getTargetPlayerRankForPlayer( rankPlayer, nextRank ); -// -// -//// playerRank = rankPlayerFactory.createPlayerRank( nextRank ); -//// playerRank = new PlayerRank(nextRank); -// -// cost += playerRank.getRankCost(); -// nextRank = nextRank.getRankNext(); -// } -// } -// } return cost; } @@ -1508,68 +1413,68 @@ private Rank findNextRanksOnDefaultLadder( Rank rankDefault, Rank targetRank, Ar @Override public List getTranslatedPlaceHolderKeys() { - if ( translatedPlaceHolderKeys == null ) { - translatedPlaceHolderKeys = new ArrayList<>(); - - // This generates all the placeholders for all ranks: - List placeHolders = PrisonPlaceHolders.getTypes( PlaceholderFlags.RANKS ); - - placeHolders.addAll( PrisonPlaceHolders.getTypes( PlaceholderFlags.RANKPLAYERS ) ); - - placeHolders.addAll( PrisonPlaceHolders.getTypes( PlaceholderFlags.STATSRANKS ) ); - - - List ranks = PrisonRanks.getInstance().getRankManager().getRanks(); - for ( Rank rank : ranks ) { - for ( PrisonPlaceHolders ph : placeHolders ) { - - String rankName = rank.getName().toLowerCase(); - - String key = ph.name().replace( - PlaceholderManager.PRISON_PLACEHOLDER_RANKNAME_SUFFIX, "_" + rankName ). - toLowerCase(); - - PlaceHolderKey placeholder = new PlaceHolderKey(key, ph, rankName ); - if ( ph.getAlias() != null ) { - String aliasName = ph.getAlias().name().replace( - PlaceholderManager.PRISON_PLACEHOLDER_RANKNAME_SUFFIX, "_" + rankName ). - toLowerCase(); - placeholder.setAliasName( aliasName ); - } - translatedPlaceHolderKeys.add( placeholder ); - - } - - } - - - // This generates all the placeholders for all ranks: - List placeHolders2 = PrisonPlaceHolders.getTypes( PlaceholderFlags.STATSPLAYERS ); - - for ( PrisonPlaceHolders ph : placeHolders2 ) { - String key = ph.name(); - - PlaceHolderKey placeholder = new PlaceHolderKey(key, ph ); - if ( ph.getAlias() != null ) { - String aliasName = ph.getAlias().name(); - placeholder.setAliasName( aliasName ); - } - translatedPlaceHolderKeys.add( placeholder ); - } - - } - - return translatedPlaceHolderKeys; + if ( translatedPlaceHolderKeys == null ) { + translatedPlaceHolderKeys = new ArrayList<>(); + + // This generates all the placeholders for all ranks: + List placeHolders = PrisonPlaceHolders.getTypes( PlaceholderFlags.RANKS ); + + placeHolders.addAll( PrisonPlaceHolders.getTypes( PlaceholderFlags.RANKPLAYERS ) ); + + placeHolders.addAll( PrisonPlaceHolders.getTypes( PlaceholderFlags.STATSRANKS ) ); + + + List ranks = PrisonRanks.getInstance().getRankManager().getRanks(); + for ( Rank rank : ranks ) { + for ( PrisonPlaceHolders ph : placeHolders ) { + + String rankName = rank.getName().toLowerCase(); + + String key = ph.name().replace( + PlaceholderManager.PRISON_PLACEHOLDER_RANKNAME_SUFFIX, "_" + rankName ). + toLowerCase(); + + PlaceHolderKey placeholder = new PlaceHolderKey(key, ph, rankName ); + if ( ph.getAlias() != null ) { + String aliasName = ph.getAlias().name().replace( + PlaceholderManager.PRISON_PLACEHOLDER_RANKNAME_SUFFIX, "_" + rankName ). + toLowerCase(); + placeholder.setAliasName( aliasName ); + } + translatedPlaceHolderKeys.add( placeholder ); + + } + + } + + + // This generates all the placeholders for all ranks: + List placeHolders2 = PrisonPlaceHolders.getTypes( PlaceholderFlags.STATSPLAYERS ); + + for ( PrisonPlaceHolders ph : placeHolders2 ) { + String key = ph.name(); + + PlaceHolderKey placeholder = new PlaceHolderKey(key, ph ); + if ( ph.getAlias() != null ) { + String aliasName = ph.getAlias().name(); + placeholder.setAliasName( aliasName ); + } + translatedPlaceHolderKeys.add( placeholder ); + } + + } + + return translatedPlaceHolderKeys; } @Override public void reloadPlaceholders() { - - // clear the class variable so they will regenerate: - translatedPlaceHolderKeys = null; - - // Regenerate the translated placeholders: - getTranslatedPlaceHolderKeys(); + + // clear the class variable so they will regenerate: + translatedPlaceHolderKeys = null; + + // Regenerate the translated placeholders: + getTranslatedPlaceHolderKeys(); } @@ -1578,10 +1483,17 @@ public String getRankByFileName(String fileName) { String results = ""; for (Rank rank : loadedRanks) { - String rankFileName = rank.filename() + ".json"; - if ( rankFileName.equalsIgnoreCase(fileName) ) { + String rankFileNameNew = rank.filenameNew() + ".json"; + if ( rankFileNameNew.equalsIgnoreCase(fileName) ) { results = rank.getName(); } + else { + String rankFileNameOld = rank.filenameOld() + ".json"; + if ( rankFileNameOld.equalsIgnoreCase(fileName) ) { + results = rank.getName(); + } + + } } return results; } @@ -1590,14 +1502,16 @@ private List getLoadedRanks() { return loadedRanks; } - private TreeMap getRanksByName() { + public TreeMap getRanksByName() { return ranksByName; } - private TreeMap getRanksById() { + public TreeMap getRanksById() { return ranksById; } - + public void setRanksById(TreeMap ranksById) { + this.ranksById = ranksById; + } public CommandCommands getRankCommandCommands() { return rankCommandCommands; @@ -1627,4 +1541,31 @@ public void setLadderCommands( LadderCommands ladderCommands ) { this.ladderCommands = ladderCommands; } + public void setLoadedRanks(List loadedRanks) { + this.loadedRanks = loadedRanks; + } + public void setRanksByName(TreeMap ranksByName) { + this.ranksByName = ranksByName; + } + + + private void resetAllRanks() { + + this.loadedRanks = new ArrayList<>(); + this.ranksByName = new TreeMap<>(); + this.ranksById = new TreeMap<>(); + } + + public void reloadAllRanks() + throws IOException { + Output.get().logInfo( "Ranks: Loading Ranks..." ); + + resetAllRanks(); + + loadRanks(); + + + Output.get().logInfo( "Ranks: Finished Loading Ranks." ); + + } } diff --git a/prison-ranks/src/main/java/tech/mcprison/prison/ranks/tasks/PlayerNewFileNameCheckAsyncTask.java b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/tasks/PlayerNewFileNameCheckAsyncTask.java new file mode 100644 index 000000000..d6a90d082 --- /dev/null +++ b/prison-ranks/src/main/java/tech/mcprison/prison/ranks/tasks/PlayerNewFileNameCheckAsyncTask.java @@ -0,0 +1,259 @@ +package tech.mcprison.prison.ranks.tasks; + +import java.io.File; +import java.util.List; + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.backups.PrisonSystemSettings; +import tech.mcprison.prison.cache.PlayerCachePlayerData; +import tech.mcprison.prison.file.JsonFileIO; +import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.ranks.PrisonRanks; +import tech.mcprison.prison.ranks.data.RankPlayer; +import tech.mcprison.prison.ranks.managers.PlayerManager; +import tech.mcprison.prison.tasks.PrisonRunnable; +import tech.mcprison.prison.tasks.PrisonTaskSubmitter; + +/** + * This task will run after the server starts up. + * If the 'prison-ranks.use-friendly-user-file-name' is set. + * + * Please note: this is no longer used. Prison now will automatically + * convert individual files as needed. This will try to convert + * everything at once, but is not required. + */ +public class PlayerNewFileNameCheckAsyncTask + implements PrisonRunnable { + + public enum ReportMode { +// status, +// run, + players, + cache; + + public static ReportMode fromString( String reportMode ) { + ReportMode results = players; + + for (ReportMode mode : values()) { + if ( reportMode != null && mode.name().equalsIgnoreCase(reportMode) ) { + results = mode; + break; + } + } + + return results; + } + } + + public PlayerNewFileNameCheckAsyncTask() { + super(); + } + + public static void submitTaskSync( long delayTicks ) { + + boolean useNewFormat = Prison.get().getPlatform() + .getConfigBooleanFalse( + PrisonSystemSettings.PRISON_SYSTEM_SETTING_FRIENDLY_PLAYER_FILE_NAMES ); + + if ( useNewFormat ) { + + Output.get().logInfo( + "&3PlayerFileNameCheck Task: &aUsing Friendly User filenames: " + + "&dConversion file check async task submitted." ); + + Output.get().logInfo( + "&PlayerFileNameCheck Task: &aChecking: " + + "&dPlayer Rank files &aand &dPlayer Cache files&a." ); + + PlayerNewFileNameCheckAsyncTask task = new PlayerNewFileNameCheckAsyncTask(); + + PrisonTaskSubmitter.runTaskLaterAsync( task, delayTicks ); + } + else { + Output.get().logInfo( + "&3layerFileNameCheck Task: &aFailed. The 'config.yml' setting '%s' " + + "is not enabled so this task cannot run.", + PrisonSystemSettings.PRISON_SYSTEM_SETTING_FRIENDLY_PLAYER_FILE_NAMES ); + + } + } + + @Override + public void run() { + + int changedPlayRankFiles = 0; + int changedCacheFiles = 0; + + PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); + List players = pm.getPlayers(); + + File dataStoragePath = new File( Prison.get().getDataFolder(), "data_storage" ); + + File playerRankpath = new File( new File( dataStoragePath, "ranksDb" ), "players"); + File playerCachePath = new File( dataStoragePath, "playerCache" ); + + for (RankPlayer player : players) { + + // Rank player file directory: + if ( playerRankpath.exists() ) + { + + String oldFilename = JsonFileIO.filenamePlayerOld( player ); + File oldPlayerFile = new File( playerRankpath, oldFilename ); + + if ( oldPlayerFile.exists() ) { + + String newFilename = JsonFileIO.filenamePlayerNew( player ); + File newPlayerFile = new File( playerRankpath, newFilename ); + + oldPlayerFile.renameTo(newPlayerFile); + + changedPlayRankFiles++; + } + } + + + // Player cache file directory: + if ( playerCachePath.exists() ) + { + + String oldFilename = JsonFileIO.filenameCacheOld( player ); + File oldCacheFile = new File( playerCachePath, oldFilename ); + + if ( oldCacheFile.exists() ) { + + String newFilename = JsonFileIO.filenameCacheNew( player ); + File newCacheFile = new File( playerCachePath, newFilename ); + + oldCacheFile.renameTo(newCacheFile); + changedCacheFiles++; + + // The player's cache data object contains a File object pointing to + // the old cache file, which needs to be replaced with the new + // cache File object, otherwise the player cache will keep trying to + // write to the old file name. + // If the player cache does not contain this player, then it will not + // be loaded. If the player is loaded later on, then it will load + // from the newly renamed files. + PlayerCachePlayerData pCache = player.getPlayerCache().getOnlinePlayerCached( player ); + if ( pCache != null ) { + pCache.setPlayerFile( newCacheFile ); + } + } + } + } + + Output.get().logInfo( + "&3PlayerFileNameCheck Task: Files updated for %d players: &aPlayer Rank files: " + + "&d%d " + + "&aPlayer Cache files: &d%d", + players.size(), + changedPlayRankFiles, + changedCacheFiles ); + + } + + + + + /** + *

    This generates a report in the console that will list all players in prison + * and their old and new file names for a given mode. + *

    + * + * @param page + */ + public void playerConverterReport( ReportMode mode, int page ) { + + PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); + List players = pm.getPlayers(); + + + int pageSize = 25; + + if ( page <= 1 ) { + page = 1; + } + + + int pageStart = (page - 1) * pageSize; + int pageEnd = pageStart + pageSize; + + + if ( pageEnd >= players.size() ) { + pageEnd = players.size() - 1; + + pageStart = pageEnd - pageSize; + + if ( pageStart < 0 ) { + pageStart = 0; + } + } + + String pattern = "%4s %-6s %-5s %-5s %-60s %-60s \n"; + + StringBuilder sb = new StringBuilder(); + + // Headers: + sb.append( String.format( pattern, "Plyr", "Report", "Using", "Using", "", "" ) ); + sb.append( String.format( pattern, "Nmbr", "Mode", "Old", "new", "Old Filename", "New Filename" ) ); + sb.append( String.format( pattern, "----", "------", "-----", "-----", + "--------- --------- --------- --------- --------- ---------", + "--------- --------- --------- --------- --------- ---------" ) ); + + File dataStoragePath = new File( Prison.get().getDataFolder(), "data_storage" ); + + File playerRankpath = new File( new File( dataStoragePath, "ranksDb" ), "players"); + File playerCachePath = new File( dataStoragePath, "playerCache" ); + + + for ( int i = pageStart; i <= pageEnd; i++ ) { + + RankPlayer player = players.get(i); + + // Rank player file directory: + if ( mode == ReportMode.players ) { + + String oldFilename = JsonFileIO.filenamePlayerOld( player ); + String newFilename = JsonFileIO.filenamePlayerNew( player ); + + File oldPlayerFile = new File( playerRankpath, oldFilename ); + File newPlayerFile = new File( playerRankpath, newFilename ); + + sb.append( String.format( pattern, + Integer.toString(i), + mode.name(), + oldPlayerFile.exists(), + newPlayerFile.exists(), + oldFilename, newFilename ) ); + } + + + // Player cache file directory: + if ( mode == ReportMode.cache ) { + + String oldFilename = JsonFileIO.filenameCacheOld( player ); + String newFilename = JsonFileIO.filenameCacheNew( player ); + + File oldCacheFile = new File( playerCachePath, oldFilename ); + File newCacheFile = new File( playerCachePath, newFilename ); + + sb.append( String.format( pattern, + Integer.toString(i), + mode.name(), + oldCacheFile.exists(), + newCacheFile.exists(), + oldFilename, newFilename ) ); + } + + + } + + Output.get().logInfo( + "&3Prison Player's new file name format report: \n" + + "%s", + sb.toString() ); + + } + +} diff --git a/prison-sellall/build.gradle b/prison-sellall/build.gradle index 4b47bc2a0..3c781eeb2 100644 --- a/prison-sellall/build.gradle +++ b/prison-sellall/build.gradle @@ -1,21 +1,3 @@ -/* - * 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' @@ -23,6 +5,10 @@ compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = "UTF-8" +ext.targetArchiveClassifier = 'Java1.8' +//ext.targetArchiveClassifier = 'Java16' + + dependencies { implementation project(':prison-core') implementation project(':prison-mines') diff --git a/prison-sellall/src/main/java/tech/mcprison/prison/sellall/PrisonSellall.java b/prison-sellall/src/main/java/tech/mcprison/prison/sellall/PrisonSellall.java index 6f7e06814..8237434f5 100644 --- a/prison-sellall/src/main/java/tech/mcprison/prison/sellall/PrisonSellall.java +++ b/prison-sellall/src/main/java/tech/mcprison/prison/sellall/PrisonSellall.java @@ -91,4 +91,25 @@ public LocaleManager getSellallMessages() { return localeManager; } + /** + * For modules that have elements, this will return the count. If a module has no + * elements, then it will return a -1. Otherwise a zero would indicate that a module + * should have elements, but it currently has none. + * + * Example would be ranks and mines. For these, if it returns a zero, then they have + * no ranks or mines defined. If it return a -1 then the module is not active. + * + * @return + */ + public int getElementCount() { + int results = isEnabled() ? 0 : -1; + + // May need to hook in to the number of shop items... but that currently is not available through this module. +// if ( isEnabled() ) { +// results = get; +// } + + return results; + } + } diff --git a/prison-sellall/src/main/java/tech/mcprison/prison/sellall/wip/data/SellallItemData.java b/prison-sellall/src/main/java/tech/mcprison/prison/sellall/wip/data/SellallItemData.java new file mode 100644 index 000000000..e181b8449 --- /dev/null +++ b/prison-sellall/src/main/java/tech/mcprison/prison/sellall/wip/data/SellallItemData.java @@ -0,0 +1,39 @@ +package tech.mcprison.prison.sellall.wip.data; + +public class SellallItemData { + + private String name; + private double price; + private int amount; + + public SellallItemData( String name, double price ) { + super(); + + this.name = name; + this.price = price; + + this.amount = 0; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + public void setPrice(double price) { + this.price = price; + } + + public int getAmount() { + return amount; + } + public void setAmount(int amount) { + this.amount = amount; + } + +} diff --git a/prison-sellall/src/main/java/tech/mcprison/prison/sellall/wip/data/ShopData.java b/prison-sellall/src/main/java/tech/mcprison/prison/sellall/wip/data/ShopData.java new file mode 100644 index 000000000..076e8ecdf --- /dev/null +++ b/prison-sellall/src/main/java/tech/mcprison/prison/sellall/wip/data/ShopData.java @@ -0,0 +1,63 @@ +package tech.mcprison.prison.sellall.wip.data; + +import java.util.List; + +public class ShopData { + + private String name; + + private int priority; + + // Connection identifies how this shop is tied to something, such + // as a rank, mine, or a perm. + private String connection; + private ConnectionType connectionType; + + private String parentName; + private transient ShopData parent; + private double parentMultiplier; +// private boolean includeParentItems; // if false, then makes no sense to have a parent + + + /** + * Added items is the "raw" list of items that should be added to this shop. + * Removed items are applied only to inherited items from the parents. + */ + private List itemsAdd; + private List itemsRemove; + + /* + * Items is the "calculated" set of items, which includes items from the parents, + * with the adjustments made to the prices. + */ + private transient List items; + + public enum ConnectionType { + RANK, + MINE, + PERM; + } + + /** + *

    The default value will be ADD, which indicates that the specified + * ShopItemData should be "added" to the shop. The REMOVE value indicates + * that this item should be removed from the current shop, as all of the + * items are pulled from the parents. It's a way to remove items from a shop + * when inheriting from parents. + *

    + * + */ + public enum ShopItemAction { + ADD, + REMOVE, + + ; + } + + public ShopData() { + super(); + + boolean a = !!true; + boolean b = !!!!!!a; + } +} diff --git a/prison-sellall/src/main/java/tech/mcprison/prison/sellall/wip/data/ShopItemData.java b/prison-sellall/src/main/java/tech/mcprison/prison/sellall/wip/data/ShopItemData.java new file mode 100644 index 000000000..a32feaa8d --- /dev/null +++ b/prison-sellall/src/main/java/tech/mcprison/prison/sellall/wip/data/ShopItemData.java @@ -0,0 +1,36 @@ +package tech.mcprison.prison.sellall.wip.data; + +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.sellall.wip.data.ShopData.ShopItemAction; + +public class ShopItemData { + + private String name; + private String description; + + + // ItemId is the text representation of the block or item. Generally it is + // an xseries name, but could also be a custom block name too, following + // prison's qualified naming convention. + private String itemId; + private double cost; + + private ShopItemAction action; + + private transient PrisonBlock prisonBlock; + + public ShopItemData() { + super(); + } + + public ShopItemData( String name, String description, String itemId, double cost ) { + super(); + + this.name = name; + this.description = description; + this.itemId = itemId; + this.cost = cost; + } + + +} diff --git a/prison-spigot-alt/build.gradle b/prison-spigot-alt/build.gradle index 255458369..02bba6dde 100644 --- a/prison-spigot-alt/build.gradle +++ b/prison-spigot-alt/build.gradle @@ -1,20 +1,3 @@ -/* - * 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' @@ -24,73 +7,17 @@ compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = "UTF-8" +ext.targetArchiveClassifier = 'Java1.8' +//ext.targetArchiveClassifier = 'Java16' + + + // NOTE: The sourceCompatibility will be removed in gradle v9.x. // Not going to worry about this, since this sub-proect is not being used. // More info: // https://docs.gradle.org/8.3/userguide/upgrading_version_8.html#java_convention_deprecation //sourceCompatibility = 17 -repositories { - mavenCentral() - - // net.luckperm.api: - maven { url = "https://hub.spigotmc.org/nexus/content/groups/public" } - - // The following houses many repos, so don't limit to just luckperms: - // net.milkbowl, be.maximvdw, org.bstats:bstats-bukkit - maven { url = "https://repo.lucko.me/" } - - maven { url = "https://oss.sonatype.org/content/repositories/snapshots/" } - maven { url = "https://nexus.hc.to/content/repositories/pub_releases" } - - maven { url = "https://repo.codemc.org/repository/maven-public/" } - //maven { url = "https://repo.inventivetalent.org/content/groups/public/" } - - -// NOTE: mvdw support has been removed from prison since PAPI works with it: -// maven { -// url = "https://repo.mvdw-software.be/content/groups/public/" -// content { -// includeGroup 'be.maximvdw' -// } -// } - maven { - url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' - content { - includeGroup 'me.clip' - } - } - maven { url = "https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/" } - - - maven { - url = 'https://mvnrepository.com/artifact/com.github.cryptomorin/XSeries' - content { - includeGroup 'com.github.cryptomorin' - } - } - - - maven { - name = "CodeMC" - url = uri("https://repo.codemc.io/repository/maven-public/") -// url = 'https://repo.codemc.io/service/rest/repository/browse/maven-public/de/tr7zw/item-nbt-api-plugin' -// url = 'https://mvnrepository.com/artifact/de.tr7zw/item-nbt-api-plugin' - content { - includeGroup 'de.tr7zw' - } - } - - - maven { url 'https://jitpack.io' } - - - // maven { url = 'https://repo.pcgamingfreaks.at/repository/maven-everything' } - // maven { url = 'https://maven.enginehub.org/repo/' } - // maven { url = "https://nexus.badbones69.com/repository/maven-releases/" } - -} - dependencies { diff --git a/prison-spigot-alt/src/main/resources/plugin.yml b/prison-spigot-alt/src/main/resources/plugin.yml index a24af7f6b..b82588dc0 100644 --- a/prison-spigot-alt/src/main/resources/plugin.yml +++ b/prison-spigot-alt/src/main/resources/plugin.yml @@ -37,6 +37,7 @@ softdepend: - PermissionsEx - GroupManagerX - GemsEconomy + - TheNewEconomy - TokenEnchant - CMI - CMILib diff --git a/prison-spigot/build.gradle b/prison-spigot/build.gradle index 2a6f8150e..c408bf98c 100644 --- a/prison-spigot/build.gradle +++ b/prison-spigot/build.gradle @@ -1,26 +1,3 @@ -/* - * 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 . - */ - - -plugins { - id 'java' - id 'base' -} base { @@ -32,32 +9,9 @@ group 'tech.mcprison' compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = "UTF-8" -//sourceCompatibility = 1.8 - -repositories { - - maven { url = "https://hub.spigotmc.org/nexus/content/groups/public" } - - maven { - name = "CodeMC" - url = uri("https://repo.codemc.io/repository/maven-public/") -// url = 'https://repo.codemc.io/service/rest/repository/browse/maven-public/de/tr7zw/item-nbt-api-plugin' -// url = 'https://mvnrepository.com/artifact/de.tr7zw/item-nbt-api-plugin' - content { - includeGroup 'de.tr7zw' - } - } - - - maven { url 'https://jitpack.io' } - - - // maven { url = 'https://repo.pcgamingfreaks.at/repository/maven-everything' } - // maven { url = 'https://maven.enginehub.org/repo/' } - // maven { url = "https://nexus.badbones69.com/repository/maven-releases/" } - -} +ext.targetArchiveClassifier = 'Java1.8' +//ext.targetArchiveClassifier = 'Java16' diff --git a/prison-spigot/lib/PrisonEnchants-API-1.0.jar b/prison-spigot/lib/PrisonEnchants-API-1.0.jar deleted file mode 100644 index a5fc3fe07..000000000 Binary files a/prison-spigot/lib/PrisonEnchants-API-1.0.jar and /dev/null differ diff --git a/prison-spigot/lib/PrisonEnchants-API-v1.0_v2.2.1___prison-misc.jar b/prison-spigot/lib/PrisonEnchants-API-v1.0_v2.2.1___prison-misc.jar new file mode 100644 index 000000000..dcb730d7d Binary files /dev/null and b/prison-spigot/lib/PrisonEnchants-API-v1.0_v2.2.1___prison-misc.jar differ diff --git a/prison-spigot/lib/TheNewEconomy_prisonBuild_v0.1.3.0.jar b/prison-spigot/lib/TheNewEconomy_prisonBuild_v0.1.3.0.jar new file mode 100644 index 000000000..366ce0d12 Binary files /dev/null and b/prison-spigot/lib/TheNewEconomy_prisonBuild_v0.1.3.0.jar differ diff --git a/prison-spigot/lib/TokenEnchantAPI-23.9.0.jar b/prison-spigot/lib/TokenEnchantAPI-23.9.0.jar new file mode 100644 index 000000000..a5556d034 Binary files /dev/null and b/prison-spigot/lib/TokenEnchantAPI-23.9.0.jar differ diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotCommand.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotCommand.java index c1be0120a..2a8537721 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotCommand.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotCommand.java @@ -1,10 +1,26 @@ package tech.mcprison.prison.spigot; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.TreeMap; + +import org.bukkit.configuration.file.YamlConfiguration; + import tech.mcprison.prison.Prison; +import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; +import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; +import tech.mcprison.prison.commands.Arg; import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.internal.block.PrisonBlock; +import tech.mcprison.prison.mines.PrisonMines; +import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.sellall.PrisonSellall; import tech.mcprison.prison.spigot.customblock.PrisonItemsAdder; +import tech.mcprison.prison.spigot.sellall.SellAllUtil; public class SpigotCommand { @@ -14,37 +30,624 @@ public SpigotCommand() { // Register these commands: Prison.get().getCommandHandler().registerCommands( this ); } + + + + @Command( + identifier = "prison support troubleshoot autosell", + description = "Prison support troubleshooting: autosell. " + + "This command can be ran at any time. It does not make " + + "any changes to any configs. This will help identify if " + + "autosell is properly configured, and if not, then it " + + "will suggest changes.", + onlyPlayers = false, + permissions = "ranks.set" ) + public void supportTroubleshootAutosellCmd( CommandSender sender ) { + + List msgs = new ArrayList<>(); + + List perms = new ArrayList<>(); + perms.add( "prison.admin" ); + perms.add( "prison.sellall.delay" ); + perms.add( "prison.autosell.edit" ); + perms.add( "prison.sellall.toggle" ); + perms.add( "" ); + perms.add( "" ); + + msgs.add( "&3Prison support troubleshoot autosell:" ); + + msgs.add( " The following information is intended to help confirmm if " ); + msgs.add( " autosell is enabled, and if it isn't then it will identify " ); + msgs.add( " what settings need to be changed to enable it." ); + + boolean sellall = SpigotPrison.getInstance().isSellAllEnabled(); + + if ( !sellall ) { + msgs.add( "&cWarning: sellall is disabled. It needs to be turned on." ); + + YamlConfiguration modulesConf = SpigotPrison.getInstance().loadConfig( "modules.yml" ); + String sellallModuleName = PrisonSellall.MODULE_NAME.toLowerCase(); + boolean isSellallModuleDefined = modulesConf.contains( sellallModuleName ); + + if ( isSellallModuleDefined ) { + + msgs.add( " The sellall module is enabled." ); + msgs.add( "&c But sellall is disabled." ); + } + else { + msgs.add( "&c The sellall module is not enabled; please enable." ); + msgs.add( "&c Enable by editing file: '&6plugins/Prison/modules.yml&c'" ); + msgs.add( "&c Ensure '&6sellall: true&c' is set to '&6true&c' " ); + msgs.add( "&c Use '&2/prison reload sellall&c' to load the autosell settings." ); + + } + perms.add( "" ); + + msgs.add( " Note: In the 'plugins/Prison/config.yml' there is an older setting " ); + msgs.add( " 'sellall: true' which is no longer used. Do not add it, or enable it, " ); + msgs.add( " since it will be ignored." ); + + perms.add( "" ); + + } + else { + SellAllUtil saUtils = SellAllUtil.get(); + + // Options.Sell_Permission_Enabled: 'false' + // Options.Sell_Permission: prison.admin + // Options.Full_Inv_AutoSell: true + // Options.Full_Inv_AutoSell_Notification: 'true' + // Options.Full_Inv_AutoSell_perUserToggleable: true + // Options.Full_Inv_AutoSell_perUserToggleable_Need_Perm: 'false' + // Options.Full_Inv_AutoSell_PerUserToggleable_Permission: prison.sellall.toggle + // Options.Sell_Per_Block_Permission_Enabled: 'false' + // Options.Sell_Per_Block_Permission: prison.sellall. + // Options.SellAll_ignoreCustomNames: false + + boolean saFullInvAutosell = SellAllUtil.isAutoSellEnabled(); + boolean saPermsEnabled = saUtils.isSellAllSellPermissionEnabled; + String saPermsStr = saUtils.permissionSellAllSell; + boolean saUserToggle = saUtils.isAutoSellPerUserToggleable; + boolean saUserTogglePermEnable = saUtils.isAutoSellPerUserToggleablePermEnabled; + String saUserTogglePermStr = saUtils.permissionAutoSellPerUserToggleable; + + + msgs.add( " SellAll is enabled." ); + + msgs.add( " Perms enabled: " + Boolean.toString( saPermsEnabled ) ); + msgs.add( " 'Options.Sell_Permission_Enabled: " + Boolean.toString( saPermsEnabled ) + "'" ); + if ( saPermsEnabled ) { + + msgs.add( " Perm: 'Options.Sell_Permission: " + saPermsStr + "'" ); + } + msgs.add( " SellAll autosell on full inventory: " + Boolean.toString( saFullInvAutosell ) ); + msgs.add( " 'Options.Full_Inv_AutoSell: " + Boolean.toString( saFullInvAutosell ) + "'" ); + + msgs.add( " SellAll user controlled autosell toggle enabled: " + + Boolean.toString( saUserToggle ) ); + msgs.add( " 'Options.Full_Inv_AutoSell_perUserToggleable: " + Boolean.toString( saUserToggle ) + "'" ); + msgs.add( " SellAll user toggle perms enabled: " + Boolean.toString( saUserTogglePermEnable ) ); + if ( saUserTogglePermEnable ) { + + msgs.add( " 'Options.Full_Inv_AutoSell_PerUserToggleable_Permission: " + saUserTogglePermStr + "'" ); + } + msgs.add( " " ); + + if ( !saFullInvAutosell ) { + + msgs.add( "&c To get auto sell to work, you must enable the SellAll autosell on full inventory." ); + msgs.add( "&c See the above setting on what needs to be changed in the autosell configs." ); + } + + msgs.add( " " ); + + + AutoFeaturesWrapper afWrap = AutoFeaturesWrapper.getInstance(); + + boolean afAutoManagerEnabled = afWrap.isBoolean( AutoFeatures.isAutoManagerEnabled ); + + if ( !afAutoManagerEnabled ) { + + msgs.add( "&c AutoManager is disabled. This needs to be enabled." ); + msgs.add( "&c Config file: '&6plugins/Prison/autoFeaturesConfig.yml&c'" ); + msgs.add( "&c Set '&6autoManager.isAutoManagerEnabled: true&c' to a value of '&6true&c'." ); + msgs.add( "&c Use '&2/prison reload autofeatures&c' to reload the auto features settings." ); + msgs.add( " " ); + } + else { + + boolean afAutoSellIfInventoryIsFull = afWrap.isBoolean( AutoFeatures.isAutoSellIfInventoryIsFull ); + boolean afAutoSellPerBlock = afWrap.isBoolean( AutoFeatures.isAutoSellPerBlockBreakEnabled ); + + String afAutoSellPerBlockPerm = afWrap.getMessage( AutoFeatures.permissionAutoSellPerBlockBreakEnabled ); + boolean afAutoSellPerBlockPermIsEnabled = !afAutoSellPerBlockPerm.equalsIgnoreCase( "disable" ) && + !afAutoSellPerBlockPerm.equalsIgnoreCase( "disabled" ) && + !afAutoSellPerBlockPerm.equalsIgnoreCase( "false" ); + + boolean afAutoSellForceCheck = afWrap.isBoolean( AutoFeatures.isForceSellAllOnInventoryWhenBukkitBlockBreakEventFires ); + boolean afAutoSellForceDelayedCheck = afWrap.isBoolean( AutoFeatures.isEnabledDelayedSellAllOnInventoryWhenBukkitBlockBreakEventFires ); + long afAutoSellForceDelayedCheckTicks = afWrap.getInteger( AutoFeatures.isEnabledDelayedSellAllOnInventoryDelayInTicks ); + + boolean afAutoSellForceDebugLoggin = afWrap.isBoolean( AutoFeatures.isAutoSellLeftoversForceDebugLogging ); + + msgs.add( " AutoManager is enabled. This is required to use autosell features." ); + msgs.add( " AutoSell on full inventory: " + Boolean.toString( afAutoSellIfInventoryIsFull ) ); + msgs.add( " Note: This setting applies only to the processing of block breakage events. Other " ); + msgs.add( " ways blocks get in to the player's inventory will not trigger this autosell." ); + if ( !afAutoSellIfInventoryIsFull ) { + + msgs.add( " To enable set: 'options.inventory.isAutoSellIfInventoryIsFull: true' to a value of true." ); + } + msgs.add( " AutoSell per block breakage: " + Boolean.toString( afAutoSellPerBlock ) ); + if ( !afAutoSellPerBlock ) { + + msgs.add( " To enable set: 'options.inventory.isAutoSellPerBlockBreakEnabled: true' to a value of true." ); + } + msgs.add( " Per block perms enabled: " + afAutoSellPerBlockPerm + " (" + + ( afAutoSellPerBlockPermIsEnabled ? "is enabled" : "is disabled" ) + + ")" ); + msgs.add( " Perm: 'options.inventory.permissionAutoSellPerBlockBreakEnabled: '" + afAutoSellPerBlockPerm + "'" ); + msgs.add( " To disable perms, use either 'disable' or 'false' instead of an actual perm." ); + + msgs.add( " " ); + + + msgs.add( " MineBombs: Since sellall is enabled, the minebomb's autosell feature can be use." ); + msgs.add( " MineBomb's autosell does not require autosell to be enabled since it can " ); + msgs.add( " force an autosell. Autosell is useful for when the mine bomb's drops would " ); + msgs.add( " be far too large for a player's inventory to handle, and may even cause server " ); + msgs.add( " lag." ); + msgs.add( " " ); + + + if ( afAutoSellPerBlock && afAutoSellIfInventoryIsFull ) { + + msgs.add( "Autosell is enabled in autoFeatures for both per block and full inventory. " ); + msgs.add( "Since per block autosell is enabled, Prison will never use the full inventory autosell " ); + msgs.add( "through autoFeatures. " ); + msgs.add( "Per block autosell will sell the items that were just mined, and will not place those items" ); + msgs.add( "in the player's inventory prior to selling them. Per block autosell will only sell what is " ); + msgs.add( "being mined, and will not sell anything that is already in the player's inventory." ); + msgs.add( " " ); + } + else if ( afAutoSellPerBlock ) { + + msgs.add( "Autosell is enabled in autoFeatures for just per block autosell. You do not need to " ); + msgs.add( "enable full inventory autosell since it will never be used anyway; per block autosell " ); + msgs.add( "overrides the full inventory autosell within the autoFeatures. " ); + msgs.add( "Per block autosell will sell the items that were just mined, and will not place those items" ); + msgs.add( "in the player's inventory prior to selling them. Per block autosell will only sell what is " ); + msgs.add( "being mined, and will not sell anything that is already in the player's inventory." ); + msgs.add( " " ); + } + else if ( afAutoSellIfInventoryIsFull ) { + + msgs.add( "Autosell is enabled in autoFeatures only when handling block break events, and a player's " ); + msgs.add( "inventory becomes full. Other actions outside of handling block break events will not trigger " ); + msgs.add( "an autosell event even though the player's inventory may fill up." ); + msgs.add( " " ); + } + else { + + msgs.add( "Autosell has not been enabled in autoFeatures. " ); + msgs.add( "Please see the above settings to enable it. " ); + msgs.add( " " ); + } + + msgs.add( " " ); + msgs.add( "Additonal auto sell capabilities that can be enabled within Prison's auto features: " ); + msgs.add( " " ); + + msgs.add( "The player can turn off autosell by using the `/sellall autoSellToggle` command, if that " ); + msgs.add( "been enabled. See settings above. " ); + + msgs.add( " " ); + msgs.add( "&cPlease note that if autosell is working for other players, but some are complaining " ); + msgs.add( "&cthat it is not working for them, then please have them check their toggle status: " ); + msgs.add( "&c`&2/sellall autoSellToggle&c` " ); + msgs.add( " " ); + + + msgs.add( " " ); + msgs.add( "Note: The following property is not enabled: 'options.inventory.isAutoSellIfInventoryIsFullForBLOCKEVENTSPriority: '" ); + msgs.add( " Since it is not enabled, examples on how to use it is moot and will not be provided." ); + msgs.add( " " ); + msgs.add( "Prison is very flexible because the configuration of many servers can be very complex and involve " ); + msgs.add( "the use of many different plugins, somme of which may conflict with Prison, or it is preferred by " ); + msgs.add( "admins to use another plugin to handle Prison's functions, such as handling the block breakage. " ); + msgs.add( "Therefore, acknowledging the complexity of the plugin mix, Prison has a couple of autosell " ); + msgs.add( "features that can help handle some edge cases. These features generally are not used, but they " ); + msgs.add( "can solve some complex issues. Thease features are listed below..." ); + msgs.add( "" ); + msgs.add( " Check player's inventory for full inventory autosell: " + + ( afAutoSellForceCheck ? "is enabled" : "is disabled" ) ); + msgs.add( " Setting: 'options.inventory.isForceSellAllOnInventoryWhenBukkitBlockBreakEventFires: " + + Boolean.toString( afAutoSellForceCheck ) + " '" ); + msgs.add( " Prison's autoFeature's autosell does not inspect the player's inventory since it is selling " ); + msgs.add( " the blocks that are being mined. Bypassing the player's inventory save a lot of processing " ); + msgs.add( " overhead that could contribute to lag. Therefore this option, which only is tied to " ); + msgs.add( " the 'org.bukkit.BlockBreakEvent' handling, can check the player's inventory to see if it is " ); + msgs.add( " full so a sellall can be fired. This is useful if you have to use another plugins block " ); + msgs.add( " handling but you're using prison's sellall. This could be used in conjunction with a " ); + msgs.add( " event priority of MONITOR, BLOCKEVENTS, ACESS, ACCESSBLOCKEVENTS, and ACCESSMONITOR." ); + msgs.add( " NOTE: This can be applied without enabling autosell directly." ); + msgs.add( " " ); + msgs.add( " Delayed player inventory autosell: " + + ( afAutoSellForceDelayedCheck ? "is enabled" : "is disabled" ) ); + msgs.add( " Delayed for: " + Long.toString( afAutoSellForceDelayedCheckTicks ) + " ticks." ); + msgs.add( " Setting: 'options.inventory.isEnabledDelayedSellAllOnInventoryWhenBukkitBlockBreakEventFires: " + + Boolean.toString( afAutoSellForceDelayedCheck ) + " '" ); + msgs.add( " Setting: 'options.inventory.isEnabledDelayedSellAllOnInventoryDelayInTicks: " + + Long.toString( afAutoSellForceDelayedCheckTicks ) + " '" ); + msgs.add( " This option is similar to the check player's inventory for full inventory with autosell, except " ); + msgs.add( " that each time this task runs, it will sell everything in the player's inventory that is sellable." ); + msgs.add( " This process is the same as if the player used `/sellall sell` but on a delay." ); + msgs.add( " " ); + + msgs.add( " How this setting is different, is that it will submit a task to run in 'n' ticks to check " ); + msgs.add( " the player's inventory and then performm an autosell if needed. " ); + msgs.add( " This is very useful for when another plugin is handling the block breaks, and the " ); + msgs.add( " blocks are not yet placed in the player's inventory by the time prison is handling the " ); + msgs.add( " MONITOR (or other) priorities." ); + msgs.add( " Valid tick values are 0 and higher, with 2 ticks being the default. Setting this value to " ); + msgs.add( " one second (20 ticks) or higher is reasonable, and can reduce server load, but the player will " ); + msgs.add( " see a slight delay from when their inventoy becommes full and when it is sold. " ); + msgs.add( " This submits a player task to check their inventory in the future, as defined by " ); + msgs.add( " the number of ticks. While this submitted task is waiting to run, or is running, " ); + msgs.add( " addtional mining by the player will not submit more of these tasks. One task per player " ); + msgs.add( " can be submitted at time, since the task will handle all prior mining activiies." ); + msgs.add( " " ); + msgs.add( " " ); + + + msgs.add( " Force debug logging on autosell overflow conditions: " + + ( afAutoSellForceDebugLoggin ? "is enabled" : "is disabled" ) ); + msgs.add( " Setting: 'options.inventory.isAutoSellLeftoversForceDebugLogging: " + + Boolean.toString( afAutoSellForceDebugLoggin ) + " '" ); + msgs.add( " It would be a VERY rare condition for blocks not autoselling, and could be a sign that the " ); + msgs.add( " block has not been setup in the Prison sellall shop." ); + msgs.add( " Therefore, if this situation is identified, where there are leftover blocks that have not been " ); + msgs.add( " auto sold, then this will trigger a block break debug logging even for that transaction so it's " ); + msgs.add( " added to the console. This will make it easier to track down configuration issues with sellall." ); + msgs.add( " The block break debuging informmation is being shown in full since it can help provide " ); + msgs.add( " more information which would help address other possible issues." ); + msgs.add( " This only works when prison debug mode is turned off, and it will only log just that one" ); + msgs.add( " transaction (it will not turn on prison debug mode)." ); + msgs.add( " This condition will be logged every time the issue happens, which can result in many logged messages." ); + + msgs.add( " " ); + + } + msgs.add( " " ); + + + } + + // msgs.add( "" ); + + + sender.sendMessage( msgs ); + } + + + + + + @Command( + identifier = "prison support troubleshoot sellallMines", + description = "Prison support troubleshooting: sellall for Mines. " + + "This command can be ran at any time. It does not make " + + "any changes to any configs. This will help identify if " + + "sellall is properly setup for all mines. This will " + + "check all mines to confirm that all blocks are represented " + + "within sellall.", + onlyPlayers = false, + permissions = "ranks.set" ) + public void supportTroubleshootSellallMinesCmd( CommandSender sender, + @Arg( + name = "action", + description = "Perform different actions related to this comand. " + + "The default action will show only the blocks that are not " + + "setup in sellall." + + "The action 'all' will show all of the blocks, including which " + + "mines are using that block, including the chance. ", + def = "notInSellall" ) String action ) { + + List msgs = new ArrayList<>(); + + boolean reportAllblocks = action != null && action.trim().equalsIgnoreCase( "all" ); + + boolean sellallEnabled = SpigotPrison.getInstance().isSellAllEnabled(); + + if ( !sellallEnabled ) { + msgs.add( "&cWarning: sellall is disabled. It needs to be turned on." ); + + msgs.add( "" ); + msgs.add( "This support commmand cannot validate if the blocks used within the mines " ); + msgs.add( "are within sellall if sellall is not even enabled." ); + msgs.add( "" ); + msgs.add( "If you are not wanting to use Prison's sellall ,then do not use this command " ); + msgs.add( "since it will not help you configure, or troubleshoot, other plugins that " ); + msgs.add( "are handling the selling of the blocks players are getting from mining." ); + msgs.add( "" ); + + } + else { + SellAllUtil saUtils = SellAllUtil.get(); + + int sellallItemCount = saUtils.getSellAllItems().size(); + + msgs.add( " SellAll is enabled." ); + + msgs.add( " Items in sellall: " + sellallItemCount ); + + msgs.add( "" ); + + boolean minesEnabled = PrisonMines.getInstance().isEnabled(); + + if ( !minesEnabled ) { + msgs.add( "&cWarning: mines are disabled. It needs to be turned on." ); + + msgs.add( "" ); + msgs.add( "This support commmand cannot validate if the blocks used within the mines " ); + msgs.add( "are supported within sellall if the Prison Mines's module isn't even enabled." ); + msgs.add( "" ); + + } + else { + PrisonMines pMines = PrisonMines.getInstance(); + List mines = pMines.getMines(); + + TreeMap blocksInMines = new TreeMap<>(); + + + msgs.add( " Mines are enabled." ); + + msgs.add( " Total mines: " + mines.size() ); + + + for ( Mine mine : mines ) { + + List blocks = mine.getPrisonBlocks(); + + for ( PrisonBlock block : blocks ) { + + if ( !blocksInMines.containsKey( block.getBlockName() ) ) { + SupportBlockMines blockMines = new SupportBlockMines( block ); + blocksInMines.put( blockMines.getKey(), blockMines ); + } + + SupportBlockMines blockMines = blocksInMines.get( block.getBlockName() ); + + blockMines.addMine( mine ); + + } + + } + + msgs.add( " Unique blocks within all mines: " + blocksInMines.size() ); + msgs.add( "" ); + + + Set keys = blocksInMines.keySet(); + + int validBlocks = 0; + int invalidBlocks = 0; + + + // validate all blocks with sellall: + for ( String key : keys ) { + SupportBlockMines blockMines = blocksInMines.get( key ); + + // saUtils.getSellAllItems().get( ) + + PrisonBlock saPrisonBlock = saUtils.getSellallItem( + blockMines.getBlock() ); + + if ( saPrisonBlock != null ) { + + blockMines.setBlockInSellall( true ); + validBlocks++; + } + else { + + blockMines.setBlockInSellall( false ); + invalidBlocks++; + } + + } + + + msgs.add( "Total blocks in all mines: " + ( validBlocks + invalidBlocks ) ); + msgs.add( " Total valid blocks: " + validBlocks ); + msgs.add( " Total invalid blocks: " + invalidBlocks ); + msgs.add( " " ); + + if ( reportAllblocks ) { + + msgs.add( "All valid and invalid blocks: " ); + } + else { + + msgs.add( "Only invalid blocks. Rerun with 'all' to view all blocks." ); + } + msgs.add( " " ); + + + // Print block lists: + SupportBlockMines headers = new SupportBlockMines(); + msgs.add( headers.header1() ); + msgs.add( headers.header2() ); + for ( String key : keys ) { + SupportBlockMines blockMines = blocksInMines.get( key ); + + if ( !reportAllblocks && !blockMines.isBlockInSellall() || + reportAllblocks ) { + + String msg = blockMines.toString(); + + msgs.add( msg ); + } + } + + + } + + msgs.add( "" ); + msgs.add( "" ); + msgs.add( "" ); + + } + + + sender.sendMessage( msgs ); + } + + public class SupportBlockMines { + private PrisonBlock block; + + private boolean blockInSellall; + + private TreeMap mines; + + public SupportBlockMines() { + + super(); + + this.block = null; + this.blockInSellall = false; + this.mines = new TreeMap<>(); + } + + public SupportBlockMines( PrisonBlock block ) { + + this(); + + this.block = block; + } + + public String getKey() { + + return block.getBlockName(); + } + + public void addMine( Mine mine ) { + + String key = mine.getName(); + if ( !getMines().containsKey( key ) ) { + getMines().put( key, mine ); + } + } + + public String header1() { + + return " Block: mine (chance), ..."; + } + + public String header2() { + + return " ------ -------------- ..."; + } + + + public String toString() { + + StringBuilder sb = new StringBuilder(); + + DecimalFormat dFmt = Prison.getDecimalFormatStaticDouble(); + + sb.append( " " ).append( getKey() ) + .append( ": " ); + + if ( getMines() != null ) { + + Set keys = getMines().keySet(); + + int len = sb.length(); + for ( String key : keys ) { + if ( sb.length() != len ) { + sb.append( ", " ); + } + Mine mine = getMines().get( key ); + + // Must get the mine's PrisonBlock since that will contain the chance: + PrisonBlock mineBlock = mine.getPrisonBlock( getKey() ); + sb.append( mine.getName() ) + .append( " (" ) + .append( dFmt.format( mineBlock.getChance() ) ) + .append( ")" ); + + } + } + + return sb.toString(); + } + + public PrisonBlock getBlock() { + + return block; + } + + public void setBlock( PrisonBlock block ) { + + this.block = block; + } + + public boolean isBlockInSellall() { + + return blockInSellall; + } + + public void setBlockInSellall( boolean blockInSellall ) { + + this.blockInSellall = blockInSellall; + } + + public TreeMap getMines() { + + return mines; + } + + public void setMines( TreeMap mines ) { + + this.mines = mines; + } + } + + - @Command(identifier = "prison support test itemsAdder", - description = "Initial test of accessing ItemsAdder.", - onlyPlayers = false, permissions = "prison.admin" ) - public void testItemAdderCommand(CommandSender sender ) { - - - PrisonItemsAdder pia = new PrisonItemsAdder(); - - - Output.get().logInfo( "Prison Support: Starting to access ItemsAdder:" ); - Output.get().logInfo( " This is just a preliminary test just to identify if prison can access the " - + "ItemsAddr list of custom blocks. Once this can be verified, along with the format that " - + "they are using, then Prison can be setup to utilize those items as custom blocks within " - + "Prison. Please copy and past these results to the discord server to the attention " - + "of Blue." ); - Output.get().logInfo( " Will list all custom blocks: ItemsAdder.getAllItems() with only isBlock():" ); - - pia.integrate(); - - - if ( pia.hasIntegrated() ) { - - pia.testCustomBlockRegistry(); - } - else { - Output.get().logInfo( "Warning: Prison has not been able to establish a connection to " - + "ItemsAdder. Make sure it has been installed and is loading successfully." ); - } - - - Output.get().logInfo( "Prison Support: Compleated tests with access to ItemsAdder:" ); - } + @Command( + identifier = "prison support test itemsAdder", + description = "Initial test of accessing ItemsAdder.", + onlyPlayers = false, + permissions = "prison.admin" ) + public void testItemAdderCommand( CommandSender sender ) { + + + PrisonItemsAdder pia = new PrisonItemsAdder(); + + + Output.get().logInfo( "Prison Support: Starting to access ItemsAdder:" ); + Output.get().logInfo( " This is just a preliminary test just to identify if prison can access the " + + "ItemsAddr list of custom blocks. Once this can be verified, along with the format that " + + "they are using, then Prison can be setup to utilize those items as custom blocks within " + + "Prison. Please copy and past these results to the discord server to the attention " + + "of Blue." ); + Output.get().logInfo( " Will list all custom blocks: ItemsAdder.getAllItems() with only isBlock():" ); + + pia.integrate(); + + + if ( pia.hasIntegrated() ) { + + pia.testCustomBlockRegistry(); + } + else { + Output.get().logInfo( "Warning: Prison has not been able to establish a connection to " + + "ItemsAdder. Make sure it has been installed and is loading successfully." ); + } + + + Output.get().logInfo( "Prison Support: Compleated tests with access to ItemsAdder:" ); + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java index 632d15fc5..a4fa52f52 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/SpigotListener.java @@ -78,50 +78,50 @@ public SpigotListener() { initialize(); } - public void initialize() { - - // Check to see if the class BlockBreakEvent even exists: - try { - - Output.get().logInfo( "SpigotListener: Trying to register events" ); - - SpigotPrison prison = SpigotPrison.getInstance(); - PluginManager pm = Bukkit.getServer().getPluginManager(); - - - String chatEventPriorityString = Prison.get().getPlatform().getConfigString( - "prison-events.AsyncPlayerChatEvent.priority", BlockBreakPriority.NORMAL.name() ); - - - BlockBreakPriority chatEventPriority = BlockBreakPriority.fromString( chatEventPriorityString ); - - if ( chatEventPriority != BlockBreakPriority.DISABLED ) { - - EventPriority ePriority = EventPriority.valueOf( chatEventPriority.name().toUpperCase() ); - - OnPlayerChatListener chatListener = new OnPlayerChatListener(); - // onPlayerChat - - pm.registerEvent(AsyncPlayerChatEvent.class, chatListener, ePriority, - new EventExecutor() { - public void execute(Listener l, Event e) { - if ( l instanceof OnPlayerChatListener && - e instanceof AsyncPlayerChatEvent ) { - ((OnPlayerChatListener)l) - .onPlayerChat( (AsyncPlayerChatEvent) e ); - } - } - }, - prison); - //prison.getRegisteredListeners().add( chatListener ); - - } - - } - catch ( Exception e ) { - Output.get().logInfo( "AutoManager: BlockBreakEvent failed to load. [%s]", e.getMessage() ); - } - } + public void initialize() { + + // Check to see if the class BlockBreakEvent even exists: + try { + + Output.get().logInfo( "SpigotListener: Trying to register events" ); + + SpigotPrison prison = SpigotPrison.getInstance(); + PluginManager pm = Bukkit.getServer().getPluginManager(); + + + String chatEventPriorityString = Prison.get().getPlatform().getConfigString( + "prison-events.AsyncPlayerChatEvent.priority", BlockBreakPriority.NORMAL.name() ); + + + BlockBreakPriority chatEventPriority = BlockBreakPriority.fromString( chatEventPriorityString ); + + if ( chatEventPriority != BlockBreakPriority.DISABLED ) { + + EventPriority ePriority = EventPriority.valueOf( chatEventPriority.name().toUpperCase() ); + + OnPlayerChatListener chatListener = new OnPlayerChatListener(); + // onPlayerChat + + pm.registerEvent( AsyncPlayerChatEvent.class, chatListener, ePriority, + new EventExecutor() { + public void execute( Listener l, Event e ) { + + if ( l instanceof OnPlayerChatListener && + e instanceof AsyncPlayerChatEvent ) { + ( (OnPlayerChatListener) l ) + .onPlayerChat( (AsyncPlayerChatEvent) e ); + } + } + }, + prison ); + // prison.getRegisteredListeners().add( chatListener ); + + } + + } catch ( Exception e ) { + Output.get().logInfo( "AutoManager: BlockBreakEvent failed to load. [%s]", e.getMessage() ); + } + } // Do not use this init() function since it is non-standard in how @@ -215,44 +215,41 @@ public void onWorldLoadEvent( WorldLoadEvent e ) { Prison.get().getEventBus().post(pwlEvent); } - @EventHandler - public void onPlayerInteract(PlayerInteractEvent e) { - // TODO Accept air events (block is null when air is clicked...) + @EventHandler + public void onPlayerInteract( PlayerInteractEvent e ) { + // TODO Accept air events (block is null when air is clicked...) - // Check to see if we support the Action + // Check to see if we support the Action // PrisonPlayerInteractEvent.Action[] values = PrisonPlayerInteractEvent.Action.values(); - + // boolean has = false; - - Action action = Action.fromString( e.getAction().name() ); - if ( action == null ) { - // We don't support this action: - return; - } - + + Action action = Action.fromString( e.getAction().name() ); + if ( action == null ) { + // We don't support this action: + return; + } + // for ( PrisonPlayerInteractEvent.Action value : PrisonPlayerInteractEvent.Action.values() ) { // if(value.name().equals(e.getAction().name())) has = true; // } // if(!has) return; // we don't support this Action - // This one's a workaround for the double-interact event glitch. - // The wand can only be used in the main hand - if ( SpigotCompatibility.getInstance().getHand(e) != - Compatibility.EquipmentSlot.HAND) { - return; - } + // This one's a workaround for the double-interact event glitch. + // The wand can only be used in the main hand + if ( SpigotCompatibility.getInstance().getHand( e ) != Compatibility.EquipmentSlot.HAND ) { return; } - org.bukkit.Location block = e.getClickedBlock().getLocation(); - PrisonPlayerInteractEvent event = new PrisonPlayerInteractEvent( - new SpigotPlayer(e.getPlayer()), - SpigotUtil.bukkitItemStackToPrison( - SpigotCompatibility.getInstance().getItemInMainHand(e)), - action, - new Location(new SpigotWorld(block.getWorld()), block.getX(), block.getY(), - block.getZ())); - Prison.get().getEventBus().post(event); - doCancelIfShould(event, e); - } + org.bukkit.Location block = e.getClickedBlock().getLocation(); + PrisonPlayerInteractEvent event = new PrisonPlayerInteractEvent( + new SpigotPlayer( e.getPlayer() ), + SpigotUtil.bukkitItemStackToPrison( + SpigotCompatibility.getInstance().getItemInMainHand( e ) ), + action, + new Location( new SpigotWorld( block.getWorld() ), block.getX(), block.getY(), + block.getZ() ) ); + Prison.get().getEventBus().post( event ); + doCancelIfShould( event, e ); + } @EventHandler public void onPlayerDropItem(PlayerDropItemEvent e) { @@ -301,7 +298,6 @@ public class OnPlayerChatListener @EventHandler(priority=EventPriority.NORMAL) public void onPlayerChat(AsyncPlayerChatEvent e) { -// String message = e.getMessage(); String format = e.getFormat(); SpigotPlayer p = new SpigotPlayer( e.getPlayer() ); @@ -313,15 +309,6 @@ public void onPlayerChat(AsyncPlayerChatEvent e) { String translated = Text.translateAmpColorCodes( results + "&r" ); e.setFormat( translated ); -// PlayerChatEvent event = -// new PlayerChatEvent(new SpigotPlayer(e.getPlayer()), message, format); -// -// Prison.get().getEventBus().post(event); - -// e.setFormat(ChatColor.translateAlternateColorCodes('&', event.getFormat() + "&r")); -// e.setMessage(event.getMessage()); -// -// doCancelIfShould(event, e); } } 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 9b4f5bf6b..40d9d4dd2 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 @@ -68,6 +68,7 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; import tech.mcprison.prison.backpacks.BackpackEnums.BackpackType; import tech.mcprison.prison.backpacks.PlayerBackpack; +import tech.mcprison.prison.bombs.MineBombEffectsData; import tech.mcprison.prison.chat.FancyMessage; import tech.mcprison.prison.commands.PluginCommand; import tech.mcprison.prison.convert.ConversionManager; @@ -90,7 +91,7 @@ import tech.mcprison.prison.mines.PrisonMines; import tech.mcprison.prison.mines.commands.MinesCommands; import tech.mcprison.prison.mines.data.Mine; -import tech.mcprison.prison.mines.data.MineData.MineNotificationMode; +import tech.mcprison.prison.mines.data.Mine.MineNotificationMode; import tech.mcprison.prison.mines.features.MineLinerBuilder.LinerPatterns; import tech.mcprison.prison.mines.managers.MineManager; import tech.mcprison.prison.modules.Module; @@ -116,6 +117,7 @@ import tech.mcprison.prison.ranks.managers.RankManager; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerBlockBreakEvents; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerCrazyEnchants; +import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerEntityExplodeEvents; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerPrisonEnchants; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerPrisonsExplosiveBlockBreakEvents; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerRevEnchantsExplosiveEvent; @@ -140,11 +142,12 @@ import tech.mcprison.prison.spigot.scoreboard.SpigotScoreboardManager; import tech.mcprison.prison.spigot.sellall.SellAllBlockData; import tech.mcprison.prison.spigot.sellall.SellAllUtil; -import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; import tech.mcprison.prison.spigot.util.ActionBarUtil; import tech.mcprison.prison.spigot.util.SpigotYamlFileIO; +import tech.mcprison.prison.spigot.utils.PrisonUtilsMineBombs; import tech.mcprison.prison.spigot.utils.tasks.PlayerAutoRankupTask; import tech.mcprison.prison.store.Storage; +import tech.mcprison.prison.util.BluesSemanticVersionComparator; import tech.mcprison.prison.util.Bounds.Edges; import tech.mcprison.prison.util.Location; import tech.mcprison.prison.util.PrisonJarReporter; @@ -188,20 +191,21 @@ protected SpigotPlatform() { //ActionBarUtil.init(plugin); } - public SpigotPlatform(SpigotPrison plugin) { - super(); - - this.plugin = plugin; - this.scoreboardManager = new SpigotScoreboardManager(); - - - this.storage = null; + public SpigotPlatform( SpigotPrison plugin ) { + + super(); + + this.plugin = plugin; + this.scoreboardManager = new SpigotScoreboardManager(); + + + this.storage = null; // this.storage = initStorage(); - - this.placeholders = new SpigotPlaceholders(); - ActionBarUtil.init(plugin); - } + this.placeholders = new SpigotPlaceholders(); + + ActionBarUtil.init( plugin ); + } public Storage initStorage() { @@ -221,9 +225,10 @@ public Storage initStorage() { } - public org.bukkit.World getBukkitWorld(String name ) { - return Bukkit.getWorld(name); - } + public org.bukkit.World getBukkitWorld( String name ) { + + return Bukkit.getWorld( name ); + } @Override public Optional getWorld(String name) { @@ -254,171 +259,183 @@ public Optional getWorld(String name) { @Override public void getWorldLoadErrors( ChatDisplay display ) { - Module prisonMinesModule = Prison.get().getModuleManager().getModule( PrisonMines.MODULE_NAME ); - - if ( prisonMinesModule != null ) { - MineManager mineManager = ((PrisonMines) prisonMinesModule).getMineManager(); - - // When finished loading the mines, then if there are any worlds that - // could not be loaded, dump the details: - List unavailableWorlds = mineManager.getUnavailableWorldsListings(); - for ( String uWorld : unavailableWorlds ) { - - display.addText( uWorld ); - } - - } - + Module prisonMinesModule = Prison.get().getModuleManager().getModule( PrisonMines.MODULE_NAME ); + + if ( prisonMinesModule != null ) { + MineManager mineManager = ((PrisonMines) prisonMinesModule).getMineManager(); + + // When finished loading the mines, then if there are any worlds that + // could not be loaded, dump the details: + List unavailableWorlds = mineManager.getUnavailableWorldsListings(); + for ( String uWorld : unavailableWorlds ) { + + display.addText( uWorld ); + } + + } + } - @Override public Optional getPlayer(String name) { - - org.bukkit.entity.Player playerBukkit = Bukkit.getPlayer(name); - - if ( name != null && playerBukkit != null && !playerBukkit.getName().equalsIgnoreCase( name ) ) { - playerBukkit = null; - } - - return Optional.ofNullable( playerBukkit == null ? null : new SpigotPlayer(playerBukkit) ); + @Override + public Player getPlatformPlayer( RankPlayer rankPlayer) { + Player sPlayer = SpigotPlayer.getSpigotPlayer( rankPlayer ); -// return Optional.ofNullable( -// players.stream().filter(player -> player.getName().equalsIgnoreCase( name)).findFirst() -// .orElseGet(() -> { -// -// // ### getting the bukkit player here! -// org.bukkit.entity.Player playerBukkit = Bukkit.getPlayer(name); -// if (playerBukkit == null) { -// return null; -// } -// SpigotPlayer player = new SpigotPlayer(playerBukkit); -// players.add(player); -// return player; -// })); + return sPlayer; + } + + @Override + public RankPlayer getRankPlayer( UUID uuid, String name ) { + RankPlayer rPlayer = null; + + if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { + PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); + + rPlayer = pm.getPlayer( uuid, name ); + + } + + return rPlayer; + } + + @Override + public boolean saveRankPlayer( RankPlayer rPlayer ) { + boolean results = false; + + if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { + PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); + + results = pm.savePlayer(rPlayer); + + } + + return results; + } + + @Override + public Optional getPlayer(String name) { + SpigotPlayer player = null; + + if ( !"CONSOLE".equalsIgnoreCase( name ) ) { + + org.bukkit.entity.Player playerBukkit = Bukkit.getPlayer(name); + + if ( name != null && playerBukkit != null && !playerBukkit.getName().equalsIgnoreCase( name ) ) { + playerBukkit = null; + } + + if ( playerBukkit != null ) { + player = new SpigotPlayer( playerBukkit ); + } + } + + return Optional.ofNullable( player ); } - @Override public Optional getPlayer(UUID uuid) { - org.bukkit.entity.Player playerBukkit = Bukkit.getPlayer(uuid); + @Override + public Optional getPlayer( UUID uuid ) { - return Optional.ofNullable( playerBukkit == null ? null : new SpigotPlayer(playerBukkit) ); - -// return Optional.ofNullable( -// players.stream().filter(player -> player.getUUID().equals(uuid)).findFirst() -// .orElseGet(() -> { -// -// -// // ### getting the bukkit player here! -// org.bukkit.entity.Player playerBukkit = Bukkit.getPlayer(uuid); -// if (playerBukkit == null) { -// return null; -// } -// SpigotPlayer player = new SpigotPlayer(playerBukkit); -// players.add(player); -// return player; -// })); - } + org.bukkit.entity.Player playerBukkit = Bukkit.getPlayer( uuid ); - @Override public List getOnlinePlayers() { + return Optional.ofNullable( playerBukkit == null ? null : new SpigotPlayer( playerBukkit ) ); + } + + public Player getPlayer( org.bukkit.entity.Player playerBukkit ) { + + return new SpigotPlayer( playerBukkit ); + } + + /** + *

    If there are a lot of players on a server, getting bukkit's online players should be + * a fairly low cost operation since they all should have been loaded in to memory and there + * shouldn't be any disk access to load all of the players. + *

    + * + *

    The functions that are using this list of players, are either teleporting players out of + * a mine before resetting the mine, or broadcasting messages to the players. So they do need + * to be online. + *

    + * + */ + @Override + public List getOnlinePlayers() { return Bukkit.getOnlinePlayers().stream() - .map(player -> getPlayer(player.getUniqueId()).get()) + .map( player -> getPlayer( player )) .collect(Collectors.toList()); } - @Override - public Optional getOfflinePlayer(String name) { - return getOfflinePlayer(name, null); - } + /** + *

    + * Warning: Do not use because the Bukkit.getOfflinePlayer( name ) is deprecated. Use instead, the getRankPlayer() and + * if they exist, which means they are setup in prison, then you will have their UUID to use the + * Bukkit.getOfflinePlayer( uuid ) function. + *

    + */ + @Override + public Optional getOfflinePlayer( String name ) { + + Player player = null; + + try { + OfflinePlayer oPlayer = Bukkit.getOfflinePlayer( name ); + player = ( oPlayer == null ? null : new SpigotOfflinePlayer( oPlayer ) ); + } catch ( Exception e ) { + Output.get().logWarn( "SpigotPlatform.getOfflinePlayer(name) failed (is deprecated): " + e.getMessage() ); + } + + return Optional.ofNullable( player ); + +// return getOfflinePlayer(name, null); + } + + @Override + public Optional getOfflinePlayer( UUID uuid ) { + + OfflinePlayer oPlayer = Bukkit.getOfflinePlayer( uuid ); + Player player = ( oPlayer == null ? null : new SpigotOfflinePlayer( oPlayer ) ); + + return Optional.ofNullable( player ); + +// return getOfflinePlayer(null, uuid); + } - @Override - public Optional getOfflinePlayer(UUID uuid) { - return getOfflinePlayer(null, uuid); - } + /** + *

    + * This function will return all players that are setup in prison. This function cannot use bukkit's getOffLinePlayers() + * because for servers with a lot of players, that will force bukkit to read a ton of files, which will lag the server + * big time. + *

    + * + *

    + * Using the PlayerManger to get the registered players makes the most sense. + *

    + * + */ @Override - public List getOfflinePlayers() { - List players = new ArrayList<>(); - - for ( OfflinePlayer oPlayer : Bukkit.getOfflinePlayers() ) { - if ( oPlayer != null ) { - - players.add( new SpigotOfflinePlayer( oPlayer ) ); + public List getOfflinePlayers() { + + List players = new ArrayList<>(); + + if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { + PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); + + for ( RankPlayer rPlayer : pm.getPlayers() ) { + players.add( rPlayer ); } - } - - return players; - } + + } + + +// for ( OfflinePlayer oPlayer : Bukkit.getOfflinePlayers() ) { +// if ( oPlayer != null ) { +// +// players.add( new SpigotOfflinePlayer( oPlayer ) ); +// } +// } + + return players; + } - private Optional getOfflinePlayer(String name, UUID uuid) { - Player player = null; - - if ( uuid != null ) { - OfflinePlayer oPlayer = Bukkit.getOfflinePlayer( uuid ); - player = (oPlayer == null ? null : new SpigotOfflinePlayer( oPlayer ) ); - - } - - if ( player == null && name != null && name.trim().length() > 0 ) { - - // No hits on uuid so only compare names: - for ( OfflinePlayer oPlayer : Bukkit.getOfflinePlayers() ) { - if ( oPlayer != null && oPlayer.getName() != null && - oPlayer.getName().equalsIgnoreCase( name.trim() ) ) { - - player = new SpigotOfflinePlayer( oPlayer ); - break; - } - else if ( oPlayer == null || oPlayer.getName() == null ) { - Output.get().logWarn( "SpigotPlatform.getOfflinePlayer: Bukkit return a " + - "bad player: OfflinePlayer == null? " + (oPlayer == null) + - ( oPlayer == null ? "" : - " name= " + (oPlayer.getName() == null ? "null" : - oPlayer.getName()))); - - } - } - } - - // If player is not available, then try to get a RankPlayer instance of the player: - if ( player == null ) { - if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { - PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); - - RankPlayer rankPlayer = pm.getPlayer( uuid, name ); - if ( rankPlayer != null ) { - if ( uuid != null && rankPlayer.getUUID().equals( uuid ) || - uuid == null && name != null && rankPlayer.getName() != null && - rankPlayer.getName().equalsIgnoreCase( name )) { - - player = rankPlayer; - } - } - } - } - - return Optional.ofNullable( player ); - - -// for ( OfflinePlayer offP : Bukkit.getOfflinePlayers() ) { -// if ( name != null && offP.getName().equalsIgnoreCase( name) || -// uuid != null && offP.getUniqueId().equals(uuid) ) { -// -// // ### getting the offline bukkit player here! -// player = new SpigotOfflinePlayer( offP ); -// players.add(player); -// break; -// } -// } -// -// List olPlayers = Arrays.asList( Bukkit.getOfflinePlayers() ); -// for ( OfflinePlayer offlinePlayer : olPlayers ) { -// if ( name != null && offlinePlayer.getName().equals(name) || -// uuid != null && offlinePlayer.getUniqueId().equals(uuid) ) { -// player = new SpigotPlayer(offlinePlayer.getPlayer()); -// players.add(player); -// break; -// } -// } -// return Optional.ofNullable( player ); - } @Override public String getPluginVersion() { return plugin.getDescription().getVersion(); @@ -429,65 +446,65 @@ public File getPluginDirectory() { return plugin.getDataFolder(); } - @Override - public void registerCommand(PluginCommand command) { - try { - Command cmd = new Command( - command.getLabel(), - command.getDescription(), - command.getUsage(), - Collections.emptyList() ) { - - /** - *

    This is the entry point where bukkit passes control over to prison for the - * commands to be executed. - *

    - * - *

    This will prevent any command that a player is using from being ran in the - * the excluded worlds. See config.yml file and the section: - * `prisonCommandHandler.exclude-worlds` - *

    - * - *

    There are two types of players that run commands... The primary one is - * an online player. Otherwise it's a CommandSender. - *

    - * - *

    When the command is actually resolved and the onCommmand() is ran, the - * first thing it checks is to ensure that the command is not within the - * `prisonCommandHander.exclude-non-ops.commands` list of commands, and if it is, then - * it will check all perms agains the CommandSender. The perms it checks are - * the perms tied to the command and the perms listed under the - * `prisonCommandHandler.exclude-non-ops.commands`. - *

    - */ - @Override - public boolean execute(CommandSender sender, String commandLabel, String[] args) { - if (sender instanceof org.bukkit.entity.Player) { - - org.bukkit.World bWorld = ((org.bukkit.entity.Player) sender).getLocation().getWorld(); - if ( isWorldExcluded( bWorld.getName() ) ) { - return false; - } - - return Prison.get().getCommandHandler() - .onCommand(new SpigotPlayer((org.bukkit.entity.Player) sender), - command, commandLabel, args); - } - - return Prison.get().getCommandHandler() - .onCommand(new SpigotCommandSender(sender), command, commandLabel, args); - } - - - @Override + @Override + public void registerCommand( PluginCommand command ) { + + try { + Command cmd = new Command( + command.getLabel(), + command.getDescription(), + command.getUsage(), + Collections.emptyList() ) { + + /** + *

    + * This is the entry point where bukkit passes control over to prison for the commands to be executed. + *

    + * + *

    + * This will prevent any command that a player is using from being ran in the the excluded worlds. See config.yml file + * and the section: `prisonCommandHandler.exclude-worlds` + *

    + * + *

    + * There are two types of players that run commands... The primary one is an online player. Otherwise it's a + * CommandSender. + *

    + * + *

    + * When the command is actually resolved and the onCommmand() is ran, the first thing it checks is to ensure that the + * command is not within the `prisonCommandHander.exclude-non-ops.commands` list of commands, and if it is, then it will + * check all perms agains the CommandSender. The perms it checks are the perms tied to the command and the perms listed + * under the `prisonCommandHandler.exclude-non-ops.commands`. + *

    + */ + @Override + public boolean execute( CommandSender sender, String commandLabel, String[] args ) { + + if ( sender instanceof org.bukkit.entity.Player ) { + + org.bukkit.World bWorld = ( (org.bukkit.entity.Player) sender ).getLocation().getWorld(); + if ( isWorldExcluded( bWorld.getName() ) ) { return false; } + + return Prison.get().getCommandHandler() + .onCommand( new SpigotPlayer( (org.bukkit.entity.Player) sender ), + command, commandLabel, args ); + } + + return Prison.get().getCommandHandler() + .onCommand( new SpigotCommandSender( sender ), command, commandLabel, args ); + } + + + @Override public List tabComplete( CommandSender sender, String alias, String[] args ) - throws IllegalArgumentException - { - SpigotCommandSender pSender = new SpigotCommandSender( sender ); - - List results = Prison.get().getCommandHandler().getTabCompleaterData().check( pSender, alias, args ); - - + throws IllegalArgumentException { + + SpigotCommandSender pSender = new SpigotCommandSender( sender ); + + List results = Prison.get().getCommandHandler().getTabCompleaterData().check( pSender, alias, args ); + + // StringBuilder sb = new StringBuilder(); // for ( String arg : args ) { // sb.append( "[" ).append( arg ).append( "] " ); @@ -501,42 +518,41 @@ public List tabComplete( CommandSender sender, String alias, String[] ar // plugin.logDebug( "### registerCommand: Command.tabComplete() : alias= %s args= %s results= %s", // alias, sb.toString(), sbR.toString() ); - - return results; + + return results; } - //@Override - public List tabComplete( CommandSender sender, String alias, String[] args, - org.bukkit.Location location ) - throws IllegalArgumentException - { - return tabComplete( sender, alias, args ); + // @Override + public List tabComplete( CommandSender sender, String alias, String[] args, + org.bukkit.Location location ) + throws IllegalArgumentException { + + return tabComplete( sender, alias, args ); } - }; - - @SuppressWarnings( "unused" ) - boolean success = - ((SimpleCommandMap) plugin.commandMap.get(Bukkit.getServer())) - .register(command.getLabel(), "prison", cmd ); - - // Always record the registered label: - if ( cmd != null ) { - command.setLabelRegistered( cmd.getLabel() ); - } - - getCommands().add(command); - + }; + + @SuppressWarnings( "unused" ) + boolean success = ( (SimpleCommandMap) plugin.commandMap.get( Bukkit.getServer() ) ) + .register( command.getLabel(), "prison", cmd ); + + // Always record the registered label: + if ( cmd != null ) { + command.setLabelRegistered( cmd.getLabel() ); + } + + getCommands().add( command ); + // if ( !success ) { // Output.get().logInfo( "SpigotPlatform.registerCommand: %s " + // "Duplicate command. Fall back to Prison: [%s] ", command.getLabel(), // cmd.getLabel() ); // } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } + } catch ( IllegalAccessException e ) { + e.printStackTrace(); + } + } @SuppressWarnings("unchecked") @Override public void unregisterCommand(String command) { @@ -550,29 +566,31 @@ public void unregisterCommand(String command) { } - @Override - public void unregisterAllCommands() { - List cmds = new ArrayList<>(); - for ( PluginCommand pluginCommand : getCommands() ) { - cmds.add( pluginCommand.getLabel() ); + @Override + public void unregisterAllCommands() { + + List cmds = new ArrayList<>(); + for ( PluginCommand pluginCommand : getCommands() ) { + cmds.add( pluginCommand.getLabel() ); } - - for ( String lable : cmds ) { - unregisterCommand( lable ); + + for ( String lable : cmds ) { + unregisterCommand( lable ); } - } + } - public PluginCommand findCommand( String label ) { - PluginCommand results = null; - - for ( PluginCommand command : getCommands() ) { - if (command.getLabel().equalsIgnoreCase(label)) { - results = command; - break; - } + public PluginCommand findCommand( String label ) { + + PluginCommand results = null; + + for ( PluginCommand command : getCommands() ) { + if ( command.getLabel().equalsIgnoreCase( label ) ) { + results = command; + break; + } } - return results; - } + return results; + } @Override public List getCommands() { @@ -584,23 +602,23 @@ public void dispatchCommand(String cmd) { Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), cmd); } - @Override - public void dispatchCommand(tech.mcprison.prison.internal.CommandSender sender, String cmd) { - - if ( sender instanceof SpigotCommandSender ) { - SpigotCommandSender cmdSender = (SpigotCommandSender) sender; - - Bukkit.getServer().dispatchCommand( cmdSender.getWrapper(), cmd); - } - else { - - Player player = getPlayer( sender.getName() ).orElse( null ); - if ( player != null ) { - player.dispatchCommand( cmd ); - } - } - - } + @Override + public void dispatchCommand( tech.mcprison.prison.internal.CommandSender sender, String cmd ) { + + if ( sender instanceof SpigotCommandSender ) { + SpigotCommandSender cmdSender = (SpigotCommandSender) sender; + + Bukkit.getServer().dispatchCommand( cmdSender.getWrapper(), cmd ); + } + else { + + Player player = getPlayer( sender.getName() ).orElse( null ); + if ( player != null ) { + player.dispatchCommand( cmd ); + } + } + + } @Override public Scheduler getScheduler() { @@ -642,104 +660,105 @@ public void log(String message, Object... format) { logCore( message ); } - @Override - public void logCore( String message ) - { - ConsoleCommandSender sender = Bukkit.getConsoleSender(); + @Override + public void logCore( String message ) { + + ConsoleCommandSender sender = Bukkit.getConsoleSender(); if ( message.contains( "U+0026" ) ) { - message = message.replace("U+0026", "&"); + message = message.replace( "U+0026", "&" ); } - - String[] msgs = message.split( "\\{br\\}" ); - for ( String msg : msgs ) { - - if (sender == null) { - Bukkit.getLogger().info(ChatColor.stripColor(msg)); - } - else { - sender.sendMessage(msg); - } + String[] msgs = message.split( "\\{br\\}" ); + + for ( String msg : msgs ) { + + if ( sender == null ) { + Bukkit.getLogger().info( ChatColor.stripColor( msg ) ); + } + else { + sender.sendMessage( msg ); + } } - + } - /** - * This does not translate any color codes. - */ - @Override - public void logPlain( String message ) - { - ConsoleCommandSender sender = Bukkit.getConsoleSender(); - - String[] msgs = message.split( "\\{br\\}" ); - - for ( String msg : msgs ) { - - if (sender == null) { - Bukkit.getLogger().info(msg); - } - else { - sender.sendMessage(msg); - } - } - } + /** + * This does not translate any color codes. + */ + @Override + public void logPlain( String message ) { - @Override public void debug(String message, Object... format) { - if (!plugin.debug) { - return; - } + ConsoleCommandSender sender = Bukkit.getConsoleSender(); - log( Output.get().format( message, LogLevel.DEBUG), format ); - } + String[] msgs = message.split( "\\{br\\}" ); - @Override public String runConverter() { - File file = new File(plugin.getDataFolder().getParent(), "Prison.old"); - if (!file.exists()) { - return Output.get().format( - "Could not find a 'Prison.old' folder to convert. Prison 2 may not have been installed " + - "before, so there is nothing that can be converted :)", - LogLevel.WARNING); - } + for ( String msg : msgs ) { - List results = ConversionManager.getInstance().runConversion(); + if ( sender == null ) { + Bukkit.getLogger().info( msg ); + } + else { + sender.sendMessage( msg ); + } + } + } - if (results.size() == 0) { - return Text - .translateAmpColorCodes("&7There are no conversions to be run at this time."); - } + @Override + public void debug( String message, Object... format ) { - BulletedListComponent.BulletedListBuilder builder = - new BulletedListComponent.BulletedListBuilder(); - for (ConversionResult result : results) { - String status = - result.getStatus() == ConversionResult.Status.Success ? "&aSuccess" : "&cFailure"; - builder.add( - result.getAgentName() + " &8- " + status + " &7(" + result.getReason() + "&7)"); - } + if ( !plugin.debug ) { return; } - return builder.build().text(); - } + log( Output.get().format( message, LogLevel.DEBUG ), format ); + } -// @SuppressWarnings( "deprecation" ) - @Override public void showTitle(Player player, String title, String subtitle, int fade) { - org.bukkit.entity.Player play = Bukkit.getPlayer(player.getName()); -// play.sendTitle(title, subtitle); - - Titles.sendTitle( play, title, subtitle ); - } + @Override + public String runConverter() { + + File file = new File( plugin.getDataFolder().getParent(), "Prison.old" ); + if ( !file.exists() ) { + return Output.get().format( + "Could not find a 'Prison.old' folder to convert. Prison 2 may not have been installed " + + "before, so there is nothing that can be converted :)", + LogLevel.WARNING ); + } + + List results = ConversionManager.getInstance().runConversion(); + + if ( results.size() == 0 ) { return Text + .translateAmpColorCodes( "&7There are no conversions to be run at this time." ); } - @Override public void showActionBar(Player player, String text, int duration) { + BulletedListComponent.BulletedListBuilder builder = new BulletedListComponent.BulletedListBuilder(); + for ( ConversionResult result : results ) { + String status = result.getStatus() == ConversionResult.Status.Success ? "&aSuccess" : "&cFailure"; + builder.add( + result.getAgentName() + " &8- " + status + " &7(" + result.getReason() + "&7)" ); + } + + return builder.build().text(); + } + + @Override + public void showTitle( Player player, String title, String subtitle, int fade ) { + + org.bukkit.entity.Player play = Bukkit.getPlayer( player.getName() ); + + Titles.sendTitle( play, title, subtitle ); + } + + @Override + public void showActionBar(Player player, String text, int duration) { org.bukkit.entity.Player play = Bukkit.getPlayer(player.getName()); ActionBarUtil.sendActionBar(play, Text.translateAmpColorCodes(text), duration); } - @Override public ScoreboardManager getScoreboardManager() { + @Override + public ScoreboardManager getScoreboardManager() { return scoreboardManager; } - @Override public Storage getStorage() { + @Override + public Storage getStorage() { return storage; } @@ -748,26 +767,26 @@ public boolean shouldShowAlerts() { return plugin.getConfig().getBoolean("show-alerts", true); } - private boolean isDoor(Material block) { - - Material acaciaDoor = Material.matchMaterial( "ACACIA_DOOR" ); - Material birchDoor = Material.matchMaterial( "BIRCH_DOOR" ); - Material darkOakDoor = Material.matchMaterial( "DARK_OAK_DOOR" ); - Material ironDoor = Material.matchMaterial( "IRON_DOOR_BLOCK" ); - Material jungleDoor = Material.matchMaterial( "JUNGLE_DOOR" ); - Material woodenDoor = Material.matchMaterial( "WOODEN_DOOR" ); - Material spruceDoor = Material.matchMaterial( "SPRUCE_DOOR" ); - + private boolean isDoor( Material block ) { + + Material acaciaDoor = Material.matchMaterial( "ACACIA_DOOR" ); + Material birchDoor = Material.matchMaterial( "BIRCH_DOOR" ); + Material darkOakDoor = Material.matchMaterial( "DARK_OAK_DOOR" ); + Material ironDoor = Material.matchMaterial( "IRON_DOOR_BLOCK" ); + Material jungleDoor = Material.matchMaterial( "JUNGLE_DOOR" ); + Material woodenDoor = Material.matchMaterial( "WOODEN_DOOR" ); + Material spruceDoor = Material.matchMaterial( "SPRUCE_DOOR" ); + // return block == Material.ACACIA_DOOR || block == Material.BIRCH_DOOR // || block == Material.DARK_OAK_DOOR || block == Material.IRON_DOOR_BLOCK // || block == Material.JUNGLE_DOOR || block == Material.WOODEN_DOOR // || block == Material.SPRUCE_DOOR; - - return block == acaciaDoor || block == birchDoor || - block == darkOakDoor || block == ironDoor || - block == jungleDoor || block == woodenDoor || - block == spruceDoor; - } + + return block == acaciaDoor || block == birchDoor || + block == darkOakDoor || block == ironDoor || + block == jungleDoor || block == woodenDoor || + block == spruceDoor; + } @Override public Map getCapabilities() { Map capabilities = new HashMap<>(); @@ -776,84 +795,88 @@ private boolean isDoor(Material block) { return capabilities; } - /** - *

    This can be useful to see if a given plugin is active. The returned - * data, RegisteredPluginData, has additional information pertaining to the - * plugin. If the plugin is not found, then this will return a null value. - *

    - * - * @param pluginName - * @return - */ - public RegisteredPluginsData identifyRegisteredPlugin( String pluginName ) { - identifyRegisteredPlugins( false ); - - RegisteredPluginsData plugin = Prison.get().getPrisonCommands().getRegisteredPluginData().get( pluginName ); - - return plugin; - } + /** + *

    + * This can be useful to see if a given plugin is active. The returned data, RegisteredPluginData, has additional + * information pertaining to the plugin. If the plugin is not found, then this will return a null value. + *

    + * + * @param pluginName + * @return + */ + public RegisteredPluginsData identifyRegisteredPlugin( String pluginName ) { + + identifyRegisteredPlugins( false ); + + RegisteredPluginsData plugin = Prison.get().getPrisonCommands().getRegisteredPluginData().get( pluginName ); + + return plugin; + } - @Override + @Override public void identifyRegisteredPlugins() { - identifyRegisteredPlugins( true ); - } + + identifyRegisteredPlugins( true ); + } public void identifyRegisteredPlugins( boolean checkForWarnings ) { - PrisonCommand cmdVersion = Prison.get().getPrisonCommands(); - - // reset so it will reload cleanly: - cmdVersion.getRegisteredPlugins().clear(); + + PrisonCommand cmdVersion = Prison.get().getPrisonCommands(); + + // reset so it will reload cleanly: + cmdVersion.getRegisteredPlugins().clear(); // cmdVersion.getRegisteredPluginData().clear(); - - Server server = SpigotPrison.getInstance().getServer(); - - // Scan the existing jar files: - PrisonJarReporter jarReporter = new PrisonJarReporter(); - jarReporter.scanForJars(); - // jarReporter.dumpJarDetails(); // temp! - - // Finally print the version after loading the prison plugin: + + Server server = SpigotPrison.getInstance().getServer(); + + // Scan the existing jar files: + PrisonJarReporter jarReporter = new PrisonJarReporter(); + jarReporter.scanForJars(); + // jarReporter.dumpJarDetails(); // temp! + + // Finally print the version after loading the prison plugin: // PrisonCommand cmdVersion = Prison.get().getPrisonCommands(); - - boolean isPlugManPresent = false; - - // Store all loaded plugins within the PrisonCommand for later inclusion: - for ( Plugin plugin : server.getPluginManager().getPlugins() ) { - String name = plugin.getName(); - String version = plugin.getDescription().getVersion(); - JarFileData pluginJarFile = jarReporter.getJarsByPluginName().get( name ); - - String value = " " + name + " (" + version + - ( pluginJarFile == null ? "" : " " + pluginJarFile.getJavaVersion().name() ) + - ")"; - cmdVersion.getRegisteredPlugins().add( value ); - - cmdVersion.addRegisteredPlugin( name, version ); - - if ( "PlugMan".equalsIgnoreCase( name ) ) { - isPlugManPresent = true; - } + + boolean isPlugManPresent = false; + + // Store all loaded plugins within the PrisonCommand for later inclusion: + for ( Plugin plugin : server.getPluginManager().getPlugins() ) { + String name = plugin.getName(); + String version = plugin.getDescription().getVersion(); + JarFileData pluginJarFile = jarReporter.getJarsByPluginName().get( name ); + + String value = " " + name + " (" + version + + ( pluginJarFile == null ? "" : " " + pluginJarFile.getJavaVersion().name() ) + + ")"; + cmdVersion.getRegisteredPlugins().add( value ); + + cmdVersion.addRegisteredPlugin( name, version ); + + if ( "PlugMan".equalsIgnoreCase( name ) ) { + isPlugManPresent = true; + } } - - if ( checkForWarnings && isPlugManPresent ) { - ChatDisplay chatDisplay = new ChatDisplay("&d* *&5 WARNING: &d PlugMan &5 Detected! &d* *"); - chatDisplay.addText( "&7The use of PlugMan on this Prison server will corrupt internals" ); - chatDisplay.addText( "&7of Prison and may lead to a non-functional state, or even total" ); - chatDisplay.addText( "&7corruption of the internal settings, the saved files, and maybe" ); - chatDisplay.addText( "&7even the mines and surrounding areas too." ); - chatDisplay.addText( "&7The only safe way to restart Prison is through a server restart." ); - chatDisplay.addText( "&7Use of PlugMan at your own risk. You have been warned. " ); - chatDisplay.addText( "&7Prison support team has no obligation to help recover, or repair," ); - chatDisplay.addText( "&7any troubles that may result of the use of PlugMan." ); - chatDisplay.addText( "&bPlease Note: &3The &7/prison reload&3 commands are safe to use anytime." ); - chatDisplay.addText( "&d* *&5 WARNING &d* *&5 WARNING &d* *&5 WARNING &d* *" ); - - chatDisplay.sendtoOutputLogInfo();; - } - // NOTE: The following code does not actually get all of the commands that have been - // registered with the bukkit plugin registry. So commenting this out and may revisit - // in the future. Only tested with 1.8.8 so may work better with more recent version. + if ( checkForWarnings && isPlugManPresent ) { + ChatDisplay chatDisplay = new ChatDisplay( "&d* *&5 WARNING: &d PlugMan &5 Detected! &d* *" ); + chatDisplay.addText( "&7The use of PlugMan on this Prison server will corrupt internals" ); + chatDisplay.addText( "&7of Prison and may lead to a non-functional state, or even total" ); + chatDisplay.addText( "&7corruption of the internal settings, the saved files, and maybe" ); + chatDisplay.addText( "&7even the mines and surrounding areas too." ); + chatDisplay.addText( "&7The only safe way to restart Prison is through a server restart." ); + chatDisplay.addText( "&7Use of PlugMan at your own risk. You have been warned. " ); + chatDisplay.addText( "&7Prison support team has no obligation to help recover, or repair," ); + chatDisplay.addText( "&7any troubles that may result of the use of PlugMan." ); + chatDisplay.addText( "&bPlease Note: &3The &7/prison reload&3 commands are safe to use anytime." ); + chatDisplay.addText( "&d* *&5 WARNING &d* *&5 WARNING &d* *&5 WARNING &d* *" ); + + chatDisplay.sendtoOutputLogInfo(); + ; + } + + // NOTE: The following code does not actually get all of the commands that have been + // registered with the bukkit plugin registry. So commenting this out and may revisit + // in the future. Only tested with 1.8.8 so may work better with more recent version. // SimplePluginManager spm = (SimplePluginManager) Bukkit.getPluginManager(); // // try { @@ -901,8 +924,8 @@ public void identifyRegisteredPlugins( boolean checkForWarnings ) { // catch ( NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e ) { // e.printStackTrace(); // } - - + + } @@ -917,7 +940,7 @@ public SpigotPlaceholders getPlaceholders() { public YamlFileIO getYamlFileIO( File yamlFile ) { boolean supportsDropsCanceling = - ( new BluesSpigetSemVerComparator().compareMCVersionTo("1.12.0") >= 0 ); + ( new BluesSemanticVersionComparator().compareMCVersionTo("1.12.0") >= 0 ); return new SpigotYamlFileIO( yamlFile, supportsDropsCanceling ); @@ -975,33 +998,6 @@ public boolean getConfigBooleanFalse( String key ) { return ( val != null && val.trim().equalsIgnoreCase( "true" ) ); } -// /** -// *

    Prison is now automatically enabling the new prison block model. -// * The old block model still exists, but it has to be explicitly -// * enabled in config.yml. -// *

    -// * -// *

    No one should ever use the old block model. If there is an issue with -// * the new model then it should be fixed and not avoided. But if they -// * must, then the following must be added to the `plugins/Prison/config.yml`. -// *

    -// * -// *
    -//	 * # Warning: The use of the OLD prison block model will be removed
    -//	 * #          from future releases in the near future.  This old
    -//	 * #          model is to be used only on an emergency basis 
    -//	 * #          until any issues with the new model have been resolved.
    -//	 * use-old-prison-block-model: true
    -//	 * 
    -// * -// * @return -// */ -// @Override -// public boolean isUseNewPrisonBlockModel() { -// -//// return getConfigBooleanFalse( "use-new-prison-block-model" ); -// return !getConfigBooleanFalse( "use-old-prison-block-model" ); -// } /** *

    This returns the boolean value that is associated with the key. @@ -1108,6 +1104,17 @@ public List getConfigHashKeys( String hashPrefix ) { return keys; } + + @Override + public boolean isConfigSection( String section ) { + boolean results = false; + + results = SpigotPrison.getInstance().getConfig().isConfigurationSection( section ); + + return results; + } + + @Override public boolean isWorldExcluded( String worldName ) { boolean exclude = false; @@ -1157,25 +1164,13 @@ public TreeSet getExcludedWorlds() public PrisonBlockTypes getPrisonBlockTypes() { return SpigotPrison.getInstance().getPrisonBlockTypes(); } -// /** -// * This listing that is returned, should be the XMaterial enum name -// * for the blocks that are valid on the server. -// * -// * @return -// */ -// @Override -// public void getAllPlatformBlockTypes( List blockTypes ) { -// -// SpigotUtil.getAllPlatformBlockTypes( blockTypes ); -// -// SpigotUtil.getAllCustomBlockTypes( blockTypes ); -// } + + @Override public PrisonBlock getPrisonBlock( String blockName ) { return getPrisonBlockTypes().getBlockTypesByName( blockName ); -// return SpigotUtil.getPrisonBlock( blockName ); } @@ -1242,7 +1237,9 @@ public boolean linkModuleElements( ModuleElement sourceElement, } else if ( sourceElement.getModuleElementType() == ModuleElementType.RANK && - sourceElement instanceof Rank ) { + sourceElement instanceof Rank && + PrisonRanks.getInstance().isEnabled() + ) { // If we have an instance of a mine, then we know that module has been // enabled. @@ -1251,6 +1248,7 @@ else if ( sourceElement.getModuleElementType() == ModuleElementType.RANK && // name. If found, then link. if ( targetElementType != null && targetElementType == ModuleElementType.MINE && PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled() ) { + MineManager mm = PrisonMines.getInstance().getMineManager(); if ( mm != null ) { Mine mine = mm.getMine( name ); @@ -1300,7 +1298,8 @@ private boolean unlinkModuleElement( ModuleElement elementA, ModuleElement eleme // We need to confirm targetElementType is ranks, then we need to check to // ensure the rank module is active, then search for a rank with the given // name. If found, then link. - if ( elementB != null && elementB.getModuleElementType() == ModuleElementType.RANK ) { + if ( elementB != null && elementB.getModuleElementType() == ModuleElementType.RANK && + PrisonRanks.getInstance().isEnabled() ) { RankManager rm = PrisonRanks.getInstance().getRankManager(); if ( rm != null ) { @@ -1437,27 +1436,28 @@ else if ( elementType == ModuleElementType.RANK && return results; } + /** - *

    This function takes a CommandSender for a player, and tries to find a mine - * that would be associated with that player. This is a very complex process - * since mines don't have to be associated with mines, and you can have multiple - * mines per rank. This only processes ranks on the default ladder. Both - * the Ranks and Mines modules must be enabled too. + *

    + * This function takes a CommandSender for a player, and tries to find a mine that would be associated with that player. + * This is a very complex process since mines don't have to be associated with mines, and you can have multiple mines + * per rank. This only processes ranks on the default ladder. Both the Ranks and Mines modules must be enabled too. *

    * - *

    First, the CommandSender has to be converted to a Player object, then - * mapped to a RankPlayer. This process can only happen with a RankPlayer object - * since that is where a Player is associated with ranks. + *

    + * First, the CommandSender has to be converted to a Player object, then mapped to a RankPlayer. This process can only + * happen with a RankPlayer object since that is where a Player is associated with ranks. *

    * - *

    If the player has a rank on the default ladder, then that rank will be - * used to continue the search for the mine. If there is more than one mine - * associated with the rank, then it tries to find a mine with the same name. - * Otherwise it will take the first mine in the list. + *

    + * If the player has a rank on the default ladder, then that rank will be used to continue the search for the mine. If + * there is more than one mine associated with the rank, then it tries to find a mine with the same name. Otherwise it + * will take the first mine in the list. *

    * - *

    The result, if not null, is the best mine that can be found. It is recognized - * that if multiple mines exist, then it may not always be the one intended. + *

    + * The result, if not null, is the best mine that can be found. It is recognized that if multiple mines exist, then it + * may not always be the one intended. *

    * * @param sender @@ -1465,55 +1465,73 @@ else if ( elementType == ModuleElementType.RANK && */ @Override public ModuleElement getPlayerDefaultMine( tech.mcprison.prison.internal.CommandSender sender ) { + Mine results = null; - + if ( PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled() && - PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() - ) { - + PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { + // PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); // Player player = sender.getPlatformPlayer(); - RankPlayer rankPlayer = sender.getRankPlayer(); - - RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); - - if ( rankPlayer != null && rankPlayerFactory.getRank( rankPlayer, "default" ) != null ) { - PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, "default" ); - - Rank rank = pRank.getRank(); - - if ( rank != null ) { - - // First check to see if there are any mines linked to a rank: - if ( rank.getMines() != null && rank.getMines().size() > 0 ) { - - for ( ModuleElement mineME : rank.getMines() ) { - if ( mineME.getName().equalsIgnoreCase( rank.getName() )) { + RankPlayer rankPlayer = sender.getRankPlayer(); + + RankPlayerFactory rankPlayerFactory = new RankPlayerFactory(); + + if ( rankPlayer != null && rankPlayerFactory.getRank( rankPlayer, "default" ) != null ) { + PlayerRank pRank = rankPlayerFactory.getRank( rankPlayer, "default" ); + + // Reset the miscText field: + sender.setMiscText( null ); + + Rank rank = pRank.getRank(); + + while ( rank != null && results == null ) { + + // First check to see if there are any mines linked to a rank: + if ( rank.getMines() != null && rank.getMines().size() > 0 ) { + + for ( ModuleElement mineME : rank.getMines() ) { + if ( mineME.getName().equalsIgnoreCase( rank.getName() ) ) { // Found a mine with the same name as the rank. Give high priority: - + results = (Mine) mineME; break; } } - - if ( results == null ) { - results = (Mine) rank.getMines().get(0); - } - } - - if ( results == null ) { - // Check to see if there are any mines with the same name: - - MineManager mm = PrisonMines.getInstance().getMineManager(); - results = mm.getMine( rank.getName() ); - } - - } - - } - + + if ( results == null ) { + results = (Mine) rank.getMines().get( 0 ); + } + } + + if ( results == null ) { + // Check to see if there are any mines with the same name: + + MineManager mm = PrisonMines.getInstance().getMineManager(); + results = mm.getMine( rank.getName() ); + } + + if ( results == null ) { + // The current rank did not have any mines tied to the rank, nor was there + // a mine with the name of the current rank. + // Therefore, try the prior rank: + rank = rank.getRankPrior(); + } + + } + + if ( rank != null && rank.compareTo( pRank.getRank() ) != 0 ) { + String msg = String.format( + "&3No mines are connected to current rank %s&3. Mine %s&3 is the next " + + "highest rank that has a mine.", + pRank.getRank().getTag(), + rank.getTag() ); + sender.setMiscText( msg ); + } + } + } - + return results; } @@ -1538,37 +1556,30 @@ public ModuleElement getPlayerDefaultMine( tech.mcprison.prison.internal.Command * @return */ @Override - public boolean isMineAccessibleByRank( Player player, ModuleElement mine ) { + public boolean isMineAccessibleByRank( Player player, ModuleElement mineModule ) { boolean isAccessible = false; if ( PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled() && PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() && player != null && - mine != null && mine instanceof Mine && ((Mine) mine).getRank() != null + mineModule != null && + mineModule instanceof Mine ) { + Mine mine = (Mine) mineModule; - Rank targetRank = (Rank) ((Mine) mine).getRank(); + if ( mine.getRank() != null ) { + + Rank targetRank = (Rank) mine.getRank(); + + RankPlayer rankPlayer = player.getRankPlayer(); + + if ( rankPlayer != null ) { + + isAccessible = rankPlayer.hasAccessToRank( targetRank ); + + } + } - PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); - RankPlayer rankPlayer = pm.getPlayer( player ); - - if ( rankPlayer != null ) { - - isAccessible = rankPlayer.hasAccessToRank( targetRank ); - -// Rank rank = rankPlayer.getRank( "default" ); -// if ( rank != null ) { -// -// isAccessible = rank.equals( targetRank ); -// Rank priorRank = rank.getRankPrior(); -// -// while ( !isAccessible && priorRank != null ) { -// -// isAccessible = priorRank.equals( targetRank ); -// priorRank = priorRank.getRankPrior(); -// } -// } - } } return isAccessible; @@ -1728,8 +1739,9 @@ else if ( hasBlocks && forceKeepBlocks ) { double total = 0; for ( int i = 0; i < mBlocks.size(); i++ ) { + String blockName = mBlocks.get( i ); - PrisonBlock prisonBlock = Prison.get().getPlatform().getPrisonBlock( mBlocks.get( i ) ); + PrisonBlock prisonBlock = Prison.get().getPlatform().getPrisonBlock( blockName ); if ( prisonBlock != null ) { double chance = percents.size() > i ? percents.get( i ) : 0; @@ -1752,7 +1764,7 @@ else if ( hasBlocks && forceKeepBlocks ) { Output.get().logInfo( String.format( "AutoConfigure block assignment failure: New Block Model: " + "Unable to map to a valid PrisonBlock for this version of mc. [%s]", - mBlocks.get( i ) ) ); + blockName ) ); } @@ -1770,7 +1782,6 @@ public void autoCreateMineLinerAssignment( List rankMineNames, boolean forceLinersBottom, boolean forceLinersWalls ) { MineManager mm = PrisonMines.getInstance().getMineManager(); -// List mines = mm.getMines(); for ( String mineName : rankMineNames ) { @@ -1794,7 +1805,6 @@ public String autoCreateMineLinerAssignment( ModuleElement eMine, if ( eMine instanceof Mine ) { MineManager mm = PrisonMines.getInstance().getMineManager(); -// List mines = mm.getMines(); Mine mine = (Mine) eMine; @@ -1824,18 +1834,6 @@ private LinerPatterns getRandomLinerType() { // Get a random pattern, filtered for this version of spigot: LinerPatterns results = LinerPatterns.getRandomLinerPattern(); -// LinerPatterns[] liners = LinerPatterns.values(); -// -// // Exclude the last 3 LinerPatterns since they are "repair", "remove" and "removeAll". -// int pos = new Random().nextInt( liners.length - 3 ); -// LinerPatterns liner = liners[pos]; -// -// // Just in case any of these are selected, choose another: -// if ( liner ==LinerPatterns.remove || liner == LinerPatterns.removeAll || liner == LinerPatterns.repair ) { -// liner = getRandomLinerType(); -// } -// return liner; - return results; } @@ -1862,31 +1860,31 @@ protected List mineBlockList( List blockList, int startPos, int return results; } -// /** -// * This function grabs a rolling sub set of blocks from the startPos and working backwards -// * up to the specified length. The result set will be less than the specified length if at -// * the beginning of the list, or at the end. -// * -// * @param startPos -// * @param length -// * @param blockList -// * @return -// */ -// protected List mineBlockList( int startPos, int length, List blockList ) { -// -// List results = new ArrayList<>(); -// int iStart = (startPos >= blockList.size() ? blockList.size() - 1 : startPos); -// -// for (int i = iStart; i >= 0 && i >= startPos - length + 1; i--) { -// results.add( blockList.get( i ).getBlock().name() ); -// } -// -// return results; -// } - /** - * This listing of blocks is based strictly upon XMaterial. + *

    This listing of blocks is based strictly upon XMaterial. + *

    + * + *

    Please note: First part of this list is used in the mine's block list + * for the command `/ranks autoConfigure'. + * These should be listed in ascending order as far as values for the blocks + * that are included in the mines. + *

    + * + *

    In the source code are comments listing which blocks are assigned to each + * along with the percentages. + *

    + * + *

    Before each block is added, it is confirmed that it's valid for the + * version of Spigot that is being ran. If it's not valid, it will be + * ignored. + *

    + * + *

    It should be noted the blocks in this list need to be fully compatible with + * Spigot 1.8 through 1.21 +, otherwise invalid blocks will be omitted and + * the last few mines could be messed up. + *

    + * * This is the preferred list to use with the new block model. * * @return @@ -1894,381 +1892,428 @@ protected List mineBlockList( List blockList, int startPos, int public List buildBlockListXMaterial() { List blockList = new ArrayList<>(); - blockList.add( new SellAllBlockData( XMaterial.COBBLESTONE, 4, true) ); - blockList.add( new SellAllBlockData( XMaterial.ANDESITE, 5, true) ); - blockList.add( new SellAllBlockData( XMaterial.DIORITE, 6, true) ); - blockList.add( new SellAllBlockData( XMaterial.COAL_ORE, 13, true) ); - blockList.add( new SellAllBlockData( XMaterial.GRANITE, 8, true) ); - blockList.add( new SellAllBlockData( XMaterial.STONE, 9, true) ); - blockList.add( new SellAllBlockData( XMaterial.IRON_ORE, 18, true) ); - blockList.add( new SellAllBlockData( XMaterial.POLISHED_ANDESITE, 7, true) ); +// Mine A: [minecraft: andesite 5.0, minecraft: cobblestone 95.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.ANDESITE, 5, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.COBBLESTONE, 4, true), blockList ); + +// Mine B: [minecraft: diorite 5.0, minecraft: andesite 10.0, minecraft: cobblestone 85.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.DIORITE, 6, true), blockList ); + +// Mine C: [minecraft: coal_ore 5.0, minecraft: diorite 10.0, minecraft: andesite 20.0, minecraft: cobblestone 65.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.COAL_ORE, 13, true), blockList ); + +// Mine D: [minecraft: granite 5.0, minecraft: coal_ore 10.0, minecraft: diorite 20.0, minecraft: andesite 20.0, minecraft: cobblestone 45.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.GRANITE, 8, true), blockList ); + +// Mine E: [minecraft: stone 5.0, minecraft: granite 10.0, minecraft: coal_ore 20.0, minecraft: diorite 20.0, minecraft: andesite 20.0, minecraft: cobblestone 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.STONE, 9, true), blockList ); + +// Mine F: [minecraft: iron_ore 5.0, minecraft: stone 10.0, minecraft: granite 20.0, minecraft: coal_ore 20.0, minecraft: diorite 20.0, minecraft: andesite 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.IRON_ORE, 18, true), blockList ); + +// Mine G: [minecraft: polished_andesite 5.0, minecraft: iron_ore 10.0, minecraft: stone 20.0, minecraft: granite 20.0, minecraft: coal_ore 20.0, minecraft: diorite 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.POLISHED_ANDESITE, 7, true), blockList ); + +// Mine H: [minecraft: gold_ore 5.0, minecraft: polished_andesite 10.0, minecraft: iron_ore 20.0, minecraft: stone 20.0, minecraft: granite 20.0, minecraft: coal_ore 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.GOLD_ORE, 45, true), blockList ); - blockList.add( new SellAllBlockData( XMaterial.GOLD_ORE, 45, true) ); - blockList.add( new SellAllBlockData( XMaterial.MOSSY_COBBLESTONE, 29, true) ); +// Mine I: [minecraft: mossy_cobblestone 5.0, minecraft: gold_ore 10.0, minecraft: polished_andesite 20.0, minecraft: iron_ore 20.0, minecraft: stone 20.0, minecraft: granite 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.MOSSY_COBBLESTONE, 29, true), blockList ); + +// Mine J: [minecraft: coal_block 5.0, minecraft: mossy_cobblestone 10.0, minecraft: gold_ore 20.0, minecraft: polished_andesite 20.0, minecraft: iron_ore 20.0, minecraft: stone 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.COAL_BLOCK, 135, true), blockList ); - blockList.add( new SellAllBlockData( XMaterial.COAL_BLOCK, 135, true) ); +// Mine K: [minecraft: nether_quartz_ore 5.0, minecraft: coal_block 10.0, minecraft: mossy_cobblestone 20.0, minecraft: gold_ore 20.0, minecraft: polished_andesite 20.0, minecraft: iron_ore 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.NETHER_QUARTZ_ORE, 34, true), blockList ); +// Mine L: [minecraft: lapis_ore 5.0, minecraft: nether_quartz_ore 10.0, minecraft: coal_block 20.0, minecraft: mossy_cobblestone 20.0, minecraft: gold_ore 20.0, minecraft: polished_andesite 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.LAPIS_ORE, 100, true), blockList ); - blockList.add( new SellAllBlockData( XMaterial.NETHER_QUARTZ_ORE, 34, true) ); - blockList.add( new SellAllBlockData( XMaterial.LAPIS_ORE, 100, true) ); +// Mine M: [minecraft: end_stone 5.0, minecraft: lapis_ore 10.0, minecraft: nether_quartz_ore 20.0, minecraft: coal_block 20.0, minecraft: mossy_cobblestone 20.0, minecraft: gold_ore 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.END_STONE, 14, true ), blockList ); - - blockList.add( new SellAllBlockData( XMaterial.END_STONE, 14, true ) ); - blockList.add( new SellAllBlockData( XMaterial.IRON_BLOCK, 190, true) ); +// Mine N: [minecraft: iron_block 5.0, minecraft: end_stone 10.0, minecraft: lapis_ore 20.0, minecraft: nether_quartz_ore 20.0, minecraft: coal_block 20.0, minecraft: mossy_cobblestone 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.IRON_BLOCK, 190, true), blockList ); + +// Mine O: [minecraft: redstone_ore 5.0, minecraft: iron_block 10.0, minecraft: end_stone 20.0, minecraft: lapis_ore 20.0, minecraft: nether_quartz_ore 20.0, minecraft: coal_block 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.REDSTONE_ORE, 45, true), blockList ); - blockList.add( new SellAllBlockData( XMaterial.REDSTONE_ORE, 45, true) ); - blockList.add( new SellAllBlockData( XMaterial.DIAMOND_ORE, 200, true) ); +// Mine P: [minecraft: diamond_ore 5.0, minecraft: redstone_ore 10.0, minecraft: iron_block 20.0, minecraft: end_stone 20.0, minecraft: lapis_ore 20.0, minecraft: nether_quartz_ore 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.DIAMOND_ORE, 222, true), blockList ); - blockList.add( new SellAllBlockData( XMaterial.QUARTZ_BLOCK, 136, true) ); - blockList.add( new SellAllBlockData( XMaterial.EMERALD_ORE, 250, true) ); +// Mine Q: [minecraft: quartz_block 5.0, minecraft: diamond_ore 10.0, minecraft: redstone_ore 20.0, minecraft: iron_block 20.0, minecraft: end_stone 20.0, minecraft: lapis_ore 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.QUARTZ_BLOCK, 136, true), blockList ); + +// Mine R: [minecraft: emerald_ore 5.0, minecraft: quartz_block 10.0, minecraft: diamond_ore 20.0, minecraft: redstone_ore 20.0, minecraft: iron_block 20.0, minecraft: end_stone 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.EMERALD_ORE, 250, true), blockList ); - blockList.add( new SellAllBlockData( XMaterial.GOLD_BLOCK, 450, true) ); - blockList.add( new SellAllBlockData( XMaterial.PRISMARINE, 52, true ) ); +// Mine S: [minecraft: gold_block 5.0, minecraft: emerald_ore 10.0, minecraft: quartz_block 20.0, minecraft: diamond_ore 20.0, minecraft: redstone_ore 20.0, minecraft: iron_block 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.GOLD_BLOCK, 450, true), blockList ); + +// Mine T: [minecraft: prismarine 5.0, minecraft: gold_block 10.0, minecraft: emerald_ore 20.0, minecraft: quartz_block 20.0, minecraft: diamond_ore 20.0, minecraft: redstone_ore 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.PRISMARINE, 52, true ), blockList ); + +// Mine U: [minecraft: dark_prismarine 5.0, minecraft: prismarine 10.0, minecraft: gold_block 20.0, minecraft: emerald_ore 20.0, minecraft: quartz_block 20.0, minecraft: diamond_ore 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.DARK_PRISMARINE, 54, true ), blockList ); +// Mine V: [minecraft: lapis_block 5.0, minecraft: dark_prismarine 10.0, minecraft: prismarine 20.0, minecraft: gold_block 20.0, minecraft: emerald_ore 20.0, minecraft: quartz_block 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.LAPIS_BLOCK, 900, true), blockList ); - blockList.add( new SellAllBlockData( XMaterial.DARK_PRISMARINE, 54, true ) ); +// Mine W: [minecraft: redstone_block 5.0, minecraft: lapis_block 10.0, minecraft: dark_prismarine 20.0, minecraft: prismarine 20.0, minecraft: gold_block 20.0, minecraft: emerald_ore 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.REDSTONE_BLOCK, 405, true), blockList ); - blockList.add( new SellAllBlockData( XMaterial.LAPIS_BLOCK, 950, true) ); - blockList.add( new SellAllBlockData( XMaterial.REDSTONE_BLOCK, 405, true) ); +// Mine X: [minecraft: obsidian 5.0, minecraft: redstone_block 10.0, minecraft: lapis_block 20.0, minecraft: dark_prismarine 20.0, minecraft: prismarine 20.0, minecraft: gold_block 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.OBSIDIAN, 450, true ), blockList ); + +// Mine Y: [minecraft: diamond_block 5.0, minecraft: obsidian 10.0, minecraft: redstone_block 20.0, minecraft: lapis_block 20.0, minecraft: dark_prismarine 20.0, minecraft: prismarine 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.DIAMOND_BLOCK, 1998, true), blockList ); + +// Mine Z: [minecraft: emerald_block 5.0, minecraft: diamond_block 10.0, minecraft: obsidian 20.0, minecraft: redstone_block 20.0, minecraft: lapis_block 20.0, minecraft: dark_prismarine 25.0] + addBlockToSellallList( new SellAllBlockData( XMaterial.EMERALD_BLOCK, 2250, true), blockList ); + - blockList.add( new SellAllBlockData( XMaterial.OBSIDIAN, 450, true ) ); - blockList.add( new SellAllBlockData( XMaterial.DIAMOND_BLOCK, 2000, true) ); - blockList.add( new SellAllBlockData( XMaterial.EMERALD_BLOCK, 2250, true) ); +// addBlockToSellallList( XMaterial.SLIME_BLOCK.name(), blockList ); + + + // The following blocks are not used to generate the mine blocks: -// blockList.add( XMaterial.SLIME_BLOCK.name() ); + addBlockToSellallList( new SellAllBlockData( XMaterial.CHARCOAL, 13, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.COAL, 13, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DEEPSLATE_COAL_ORE, 13, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.IRON_NUGGET, 2, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.IRON_INGOT, 18, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.RAW_IRON, 18, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.RAW_IRON_BLOCK, 162, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DEEPSLATE_IRON_ORE, 18, true), blockList ); + + + addBlockToSellallList( new SellAllBlockData( XMaterial.GOLD_NUGGET, 5, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.GOLD_INGOT, 45, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.RAW_GOLD, 45, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.RAW_GOLD_BLOCK, 405, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DEEPSLATE_GOLD_ORE, 45, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.NETHER_GOLD_ORE, 45, true), blockList ); - // these are not used to generate the mine blocks: - blockList.add( new SellAllBlockData( XMaterial.CLAY, 12 ) ); - blockList.add( new SellAllBlockData( XMaterial.GRAVEL, 3 ) ); - blockList.add( new SellAllBlockData( XMaterial.SAND, 6 ) ); - blockList.add( new SellAllBlockData( XMaterial.DIRT, 4 ) ); - blockList.add( new SellAllBlockData( XMaterial.COARSE_DIRT, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.PODZOL, 6 ) ); - blockList.add( new SellAllBlockData( XMaterial.RED_SAND, 9 ) ); - blockList.add( new SellAllBlockData( XMaterial.BEDROCK, 500 ) ); - blockList.add( new SellAllBlockData( XMaterial.SANDSTONE, 3 ) ); - blockList.add( new SellAllBlockData( XMaterial.POLISHED_ANDESITE, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.POLISHED_DIORITE, 8 ) ); - blockList.add( new SellAllBlockData( XMaterial.POLISHED_GRANITE, 9 ) ); - blockList.add( new SellAllBlockData( XMaterial.CHISELED_NETHER_BRICKS, 39 ) ); - blockList.add( new SellAllBlockData( XMaterial.CHISELED_RED_SANDSTONE, 11 ) ); - blockList.add( new SellAllBlockData( XMaterial.CHISELED_STONE_BRICKS, 11 ) ); - blockList.add( new SellAllBlockData( XMaterial.CUT_RED_SANDSTONE, 13 ) ); - blockList.add( new SellAllBlockData( XMaterial.CUT_SANDSTONE, 10 ) ); + addBlockToSellallList( new SellAllBlockData( XMaterial.COPPER_ORE, 22, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.RAW_COPPER, 22, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.RAW_COPPER_BLOCK, 198, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.COPPER_BLOCK, 198, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DEEPSLATE_COPPER_ORE, 22, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.REDSTONE, 45, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DEEPSLATE_REDSTONE_ORE, 45, true), blockList ); + - blockList.add( new SellAllBlockData( XMaterial.QUARTZ, 34 ) ); - blockList.add( new SellAllBlockData( XMaterial.QUARTZ_SLAB, 68) ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DIAMOND, 222, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DEEPSLATE_DIAMOND_ORE, 222, true), blockList ); - blockList.add( new SellAllBlockData( XMaterial.CHISELED_QUARTZ_BLOCK, 136 ) ); - blockList.add( new SellAllBlockData( XMaterial.QUARTZ_BRICKS, 136 ) ); - blockList.add( new SellAllBlockData( XMaterial.QUARTZ_PILLAR, 136 ) ); - blockList.add( new SellAllBlockData( XMaterial.SMOOTH_QUARTZ, 136 ) ); + + addBlockToSellallList( new SellAllBlockData( XMaterial.EMERALD, 250, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DEEPSLATE_EMERALD_ORE, 250, true), blockList ); + + addBlockToSellallList( new SellAllBlockData( XMaterial.PRISMARINE_SHARD, 13, true ), blockList ); + + + addBlockToSellallList( new SellAllBlockData( XMaterial.LAPIS_LAZULI, 100, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DEEPSLATE_LAPIS_ORE, 100, true), blockList ); - blockList.add( new SellAllBlockData( XMaterial.SMOOTH_RED_SANDSTONE, 14 ) ); - blockList.add( new SellAllBlockData( XMaterial.SMOOTH_SANDSTONE, 14 ) ); - blockList.add( new SellAllBlockData( XMaterial.SMOOTH_STONE, 14 ) ); + + addBlockToSellallList( new SellAllBlockData( XMaterial.QUARTZ, 34, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.CHISELED_QUARTZ_BLOCK, 136, true), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SMOOTH_QUARTZ, 136, true), blockList ); + - blockList.add( new SellAllBlockData( XMaterial.CHARCOAL, 16 ) ); - blockList.add( new SellAllBlockData( XMaterial.CRACKED_NETHER_BRICKS, 16 ) ); - blockList.add( new SellAllBlockData( XMaterial.CRACKED_STONE_BRICKS, 14 ) ); - blockList.add( new SellAllBlockData( XMaterial.EMERALD, 14 ) ); - blockList.add( new SellAllBlockData( XMaterial.END_STONE_BRICKS, 14 ) ); - blockList.add( new SellAllBlockData( XMaterial.FLINT, 9 ) ); - // BLUE_DYE is used as LAPIS_LAZULI for bukkit v1.8.x etc... - blockList.add( new SellAllBlockData( XMaterial.LAPIS_LAZULI, 14 ) ); - blockList.add( new SellAllBlockData( XMaterial.BLUE_DYE, 14 ) ); - blockList.add( new SellAllBlockData( XMaterial.MOSSY_STONE_BRICKS, 14 ) ); - blockList.add( new SellAllBlockData( XMaterial.PRISMARINE_SHARD, 13 ) ); - blockList.add( new SellAllBlockData( XMaterial.PRISMARINE_BRICKS, 52 ) ); - blockList.add( new SellAllBlockData( XMaterial.PRISMARINE_BRICK_SLAB, 52 ) ); - blockList.add( new SellAllBlockData( XMaterial.PRISMARINE_CRYSTALS, 37 ) ); - blockList.add( new SellAllBlockData( XMaterial.DARK_PRISMARINE_SLAB, 52 ) ); - blockList.add( new SellAllBlockData( XMaterial.PURPUR_BLOCK, 14 ) ); - blockList.add( new SellAllBlockData( XMaterial.PURPUR_PILLAR, 14 ) ); + addBlockToSellallList( new SellAllBlockData( XMaterial.CLAY, 12 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.GRAVEL, 3 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SAND, 6 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DIRT, 4 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.COARSE_DIRT, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.PODZOL, 6 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.RED_SAND, 9 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.BEDROCK, 500 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SANDSTONE, 3 ), blockList ); + + addBlockToSellallList( new SellAllBlockData( XMaterial.POLISHED_ANDESITE, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.POLISHED_DIORITE, 8 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.POLISHED_GRANITE, 9 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.CHISELED_NETHER_BRICKS, 39 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.CHISELED_RED_SANDSTONE, 11 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.CHISELED_STONE_BRICKS, 11 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.CUT_RED_SANDSTONE, 13 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.CUT_SANDSTONE, 10 ), blockList ); -// blockList.add( new SellAllBlockData( XMaterial.SEA_LANTERN, 98 ) ); +// addBlockToSellallList( new SellAllBlockData( XMaterial.QUARTZ, 34 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.QUARTZ_SLAB, 68), blockList ); + +// addBlockToSellallList( new SellAllBlockData( XMaterial.CHISELED_QUARTZ_BLOCK, 136 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.QUARTZ_BRICKS, 136 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.QUARTZ_PILLAR, 136 ), blockList ); +// addBlockToSellallList( new SellAllBlockData( XMaterial.SMOOTH_QUARTZ, 136 ), blockList ); - blockList.add( new SellAllBlockData( XMaterial.TERRACOTTA, 10 ) ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SMOOTH_RED_SANDSTONE, 14 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SMOOTH_SANDSTONE, 14 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SMOOTH_STONE, 14 ), blockList ); + + +// addBlockToSellallList( new SellAllBlockData( XMaterial.CHARCOAL, 16 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.CRACKED_NETHER_BRICKS, 16 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.CRACKED_STONE_BRICKS, 14 ), blockList ); + +// addBlockToSellallList( new SellAllBlockData( XMaterial.EMERALD, 14 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.END_STONE_BRICKS, 14 ), blockList ); + + + addBlockToSellallList( new SellAllBlockData( XMaterial.FLINT, 9 ), blockList ); + - blockList.add( new SellAllBlockData( XMaterial.ACACIA_LOG, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.BIRCH_LOG, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.DARK_OAK_LOG, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.JUNGLE_LOG, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.OAK_LOG, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.SPRUCE_LOG, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.ACACIA_PLANKS, 28 ) ); - blockList.add( new SellAllBlockData( XMaterial.BIRCH_PLANKS, 28 ) ); - blockList.add( new SellAllBlockData( XMaterial.DARK_OAK_PLANKS, 28 ) ); - blockList.add( new SellAllBlockData( XMaterial.JUNGLE_PLANKS, 28 ) ); - blockList.add( new SellAllBlockData( XMaterial.OAK_PLANKS, 28 ) ); - blockList.add( new SellAllBlockData( XMaterial.SPRUCE_PLANKS, 28 ) ); + // BLUE_DYE is used as LAPIS_LAZULI for bukkit v1.8.x etc... +// addBlockToSellallList( new SellAllBlockData( XMaterial.LAPIS_LAZULI, 14 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.BLUE_DYE, 14 ), blockList ); + + addBlockToSellallList( new SellAllBlockData( XMaterial.MOSSY_STONE_BRICKS, 14 ), blockList ); + + + addBlockToSellallList( new SellAllBlockData( XMaterial.PRISMARINE_SHARD, 13 ), blockList ); - blockList.add( new SellAllBlockData( XMaterial.ACACIA_WOOD, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.BIRCH_WOOD, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.DARK_OAK_WOOD, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.JUNGLE_WOOD, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.OAK_WOOD, 7 ) ); - blockList.add( new SellAllBlockData( XMaterial.SPRUCE_WOOD, 7 ) ); + addBlockToSellallList( new SellAllBlockData( XMaterial.PRISMARINE_BRICKS, 52 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.PRISMARINE_BRICK_SLAB, 52 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.PRISMARINE_CRYSTALS, 37 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DARK_PRISMARINE_SLAB, 52 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.PURPUR_BLOCK, 14 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.PURPUR_PILLAR, 14 ), blockList ); + + + +// addBlockToSellallList( new SellAllBlockData( XMaterial.SEA_LANTERN, 98 ), blockList ); + + addBlockToSellallList( new SellAllBlockData( XMaterial.TERRACOTTA, 10 ), blockList ); - blockList.add( new SellAllBlockData( XMaterial.IRON_NUGGET, 3 ) ); - blockList.add( new SellAllBlockData( XMaterial.IRON_INGOT, 27 ) ); + addBlockToSellallList( new SellAllBlockData( XMaterial.ACACIA_LOG, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.BIRCH_LOG, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DARK_OAK_LOG, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.JUNGLE_LOG, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.OAK_LOG, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SPRUCE_LOG, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.ACACIA_PLANKS, 28 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.BIRCH_PLANKS, 28 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DARK_OAK_PLANKS, 28 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.JUNGLE_PLANKS, 28 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.OAK_PLANKS, 28 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SPRUCE_PLANKS, 28 ), blockList ); - blockList.add( new SellAllBlockData( XMaterial.GOLD_NUGGET, 12 ) ); - blockList.add( new SellAllBlockData( XMaterial.GOLD_INGOT, 108 ) ); + addBlockToSellallList( new SellAllBlockData( XMaterial.ACACIA_WOOD, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.BIRCH_WOOD, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.DARK_OAK_WOOD, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.JUNGLE_WOOD, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.OAK_WOOD, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SPRUCE_WOOD, 7 ), blockList ); - blockList.add( new SellAllBlockData( XMaterial.REDSTONE, 45 ) ); + + +// addBlockToSellallList( new SellAllBlockData( XMaterial.IRON_NUGGET, 3 ), blockList ); +// addBlockToSellallList( new SellAllBlockData( XMaterial.IRON_INGOT, 27 ), blockList ); +// +// addBlockToSellallList( new SellAllBlockData( XMaterial.GOLD_NUGGET, 12 ), blockList ); +// addBlockToSellallList( new SellAllBlockData( XMaterial.GOLD_INGOT, 108 ), blockList ); +// +// addBlockToSellallList( new SellAllBlockData( XMaterial.REDSTONE, 45 ), blockList ); - blockList.add( new SellAllBlockData( XMaterial.GLOWSTONE, 52 ) ); - blockList.add( new SellAllBlockData( XMaterial.GLOWSTONE_DUST, 14 ) ); + addBlockToSellallList( new SellAllBlockData( XMaterial.GLOWSTONE, 52 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.GLOWSTONE_DUST, 14 ), blockList ); - blockList.add( new SellAllBlockData( XMaterial.COAL, 15 ) ); - blockList.add( new SellAllBlockData( XMaterial.DIAMOND, 200 ) ); +// addBlockToSellallList( new SellAllBlockData( XMaterial.COAL, 15 ), blockList ); +// addBlockToSellallList( new SellAllBlockData( XMaterial.DIAMOND, 200 ), blockList ); - blockList.add( new SellAllBlockData( XMaterial.SUGAR_CANE, 13 ) ); - blockList.add( new SellAllBlockData( XMaterial.SUGAR, 13 ) ); - blockList.add( new SellAllBlockData( XMaterial.PAPER, 13 ) ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SUGAR_CANE, 13 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SUGAR, 13 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.PAPER, 13 ), blockList ); - 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 ) ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SOUL_SAND, 25 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.BROWN_MUSHROOM, 5 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.BROWN_MUSHROOM_BLOCK, 5 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.RED_MUSHROOM, 5 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.RED_MUSHROOM_BLOCK, 5 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SLIME_BALL, 7 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.SLIME_BLOCK, 63 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.PACKED_ICE, 7 ), blockList ); - blockList.add( new SellAllBlockData( XMaterial.BRICK, 4 ) ); - blockList.add( new SellAllBlockData( XMaterial.BRICKS, 16 ) ); // 1 bricks = 4 brick + addBlockToSellallList( new SellAllBlockData( XMaterial.BRICK, 4 ), blockList ); + addBlockToSellallList( new SellAllBlockData( XMaterial.BRICKS, 16 ), blockList ); // 1 bricks = 4 brick + return blockList; } -// /** -// * This listing of blocks is based strictly upon the old prison's block -// * model. -// * -// * Please note, that right now these names match exactly with XMaterial only -// * because I renamed a few of them to make them match. But if more are added -// * in the future, then there may be mismatches. -// * -// * @return -// */ -// protected List buildBlockListBlockType() { -// List blockList = new ArrayList<>(); -// -// blockList.add( BlockType.COBBLESTONE.name() ); -// blockList.add( BlockType.ANDESITE.name() ); -// blockList.add( BlockType.DIORITE.name() ); -// blockList.add( BlockType.COAL_ORE.name() ); -// -// blockList.add( BlockType.GRANITE.name() ); -// blockList.add( BlockType.STONE.name() ); -// blockList.add( BlockType.IRON_ORE.name() ); -// blockList.add( BlockType.POLISHED_ANDESITE.name() ); -// -//// blockList.add( BlockType.POLISHED_DIORITE.name() ); -//// blockList.add( BlockType.POLISHED_GRANITE.name() ); -// blockList.add( BlockType.GOLD_ORE.name() ); -// -// -// blockList.add( BlockType.MOSSY_COBBLESTONE.name() ); -// blockList.add( BlockType.COAL_BLOCK.name() ); -// blockList.add( BlockType.NETHER_QUARTZ_ORE.name() ); -// blockList.add( BlockType.LAPIS_ORE.name() ); -// -// -// blockList.add( BlockType.END_STONE.name() ); -// blockList.add( BlockType.IRON_BLOCK.name() ); -// -// blockList.add( BlockType.REDSTONE_ORE.name() ); -// blockList.add( BlockType.DIAMOND_ORE.name() ); -// -// blockList.add( BlockType.QUARTZ_BLOCK.name() ); -// blockList.add( BlockType.EMERALD_ORE.name() ); -// -// blockList.add( BlockType.GOLD_BLOCK.name() ); -// blockList.add( BlockType.PRISMARINE.name() ); -// blockList.add( BlockType.LAPIS_BLOCK.name() ); -// blockList.add( BlockType.REDSTONE_BLOCK.name() ); -// -// blockList.add( BlockType.OBSIDIAN.name() ); -// blockList.add( BlockType.DIAMOND_BLOCK.name() ); -// blockList.add( BlockType.DARK_PRISMARINE.name() ); -// blockList.add( BlockType.EMERALD_BLOCK.name() ); -// -// return blockList; -// } + private void addBlockToSellallList( SellAllBlockData saBlockData, List blockList ) { + + org.bukkit.inventory.ItemStack itemStack = saBlockData.getBlock().parseItem(); + + // Exclude invalid blocks since the sellall list includes block names from 1.8 through 1.21+ + if ( itemStack != null ) { + blockList.add( saBlockData ); + } + + } + @Override public List getActiveFeatures( boolean showLaddersAndRanks ) { + List results = new ArrayList<>(); - - + + if ( showLaddersAndRanks ) { - + // Log rank related items first: if ( Prison.get().getModuleManager().isModuleActive( PrisonRanks.MODULE_NAME ) ) { - + PrisonRanks pRanks = PrisonRanks.getInstance(); - - results.add( - pRanks.prisonRanksStatusLoadedLaddersMsg( + + results.add( + pRanks.prisonRanksStatusLoadedLaddersMsg( pRanks.getladderCount() ) ); - + int totalRanks = pRanks.getRankCount(); int defaultRanks = pRanks.getDefaultLadderRankCount(); int prestigesRanks = pRanks.getPrestigesLadderRankCount(); int otherRanks = totalRanks - defaultRanks - prestigesRanks; - - results.add( - pRanks.prisonRanksStatusLoadedRanksMsg( + + results.add( + pRanks.prisonRanksStatusLoadedRanksMsg( totalRanks, defaultRanks, prestigesRanks, otherRanks ) ); - - results.add( - pRanks.prisonRanksStatusLoadedPlayersMsg( + + results.add( + pRanks.prisonRanksStatusLoadedPlayersMsg( pRanks.getPlayersCount() ) ); - - + + // Display all Ranks in each ladder: results.addAll( PrisonRanks.getInstance().getRankManager().ranksByLadders() ); - + results.add( " " ); } - else { - results.add( "&7Ranks: &9Not Enabled." ); - } + else { + results.add( "&7Ranks: &9Not Enabled." ); + } } - - - Module minesModule = Prison.get().getModuleManager().getModule( "Mines" ); //.orElseGet( null ); - if ( minesModule != null && - minesModule.getStatus().getStatus() == ModuleStatus.Status.ENABLED ) { - - DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); - - int minesEnabled = 0; - int minesVirtual = 0; - int minesDeleted = 0; - int minesBlocks = 0; - - List mines = PrisonMines.getInstance().getMines(); - for (Mine mine : mines) { - - minesEnabled += mine.isEnabled() ? 1 : 0; + + + Module minesModule = Prison.get().getModuleManager().getModule( "Mines" ); // .orElseGet( null ); + if ( minesModule != null && + minesModule.getStatus().getStatus() == ModuleStatus.Status.ENABLED ) { + + DecimalFormat dFmt = Prison.get().getDecimalFormatInt(); + + int minesEnabled = 0; + int minesVirtual = 0; + int minesDeleted = 0; + int minesBlocks = 0; + + List mines = PrisonMines.getInstance().getMines(); + for ( Mine mine : mines ) { + + minesEnabled += mine.isEnabled() ? 1 : 0; minesVirtual += mine.isVirtual() ? 1 : 0; minesDeleted += mine.isDeleted() ? 1 : 0; - + minesBlocks += mine.isEnabled() ? mine.getBounds().getTotalBlockCount() : 0; } - - double blksPerMine = minesEnabled == 0 ? 0 : minesBlocks / (double) minesEnabled; - - String mineDetails = String.format( - "&7Mines Info: &9Enabled: &b%d &9Virtual: &b%d &9Deleted: &b%d &9AvgBlocks/Mine: &b%s", - minesEnabled, minesVirtual, minesDeleted, - dFmt.format(blksPerMine) ); - - results.add( mineDetails ); - } - else { - results.add( "&7Mines: &9Not Enabled." ); - } - - - + + double blksPerMine = minesEnabled == 0 ? 0 : minesBlocks / (double) minesEnabled; + + String mineDetails = String.format( + "&7Mines Info: &9Enabled: &b%d &9Virtual: &b%d &9Deleted: &b%d &9AvgBlocks/Mine: &b%s", + minesEnabled, minesVirtual, minesDeleted, + dFmt.format( blksPerMine ) ); + + results.add( mineDetails ); + } + else { + results.add( "&7Mines: &9Not Enabled." ); + } + + // Load the autoFeaturesConfig.yml and blockConvertersConfig.json files: - AutoFeaturesWrapper afw = AutoFeaturesWrapper.getInstance(); -// afw.reloadConfigs(); - -// AutoFeaturesWrapper.getBlockConvertersInstance(); - - - - - - boolean isAutoManagerEnabled = afw.isBoolean( AutoFeatures.isAutoManagerEnabled ); - - String autoMangerHeader = "&7AutoManager: " + - ( isAutoManagerEnabled ? - "&9Enabled" : - "&9Not Enabled" ); - - results.add( autoMangerHeader ); - - if ( isAutoManagerEnabled ) { - - - - boolean bbeAbbtst = afw.isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ); - results.add( String.format(". Apply Block Breaks through Sync Tasks:&b %s", - Boolean.toString( bbeAbbtst ) ) ); - - - boolean bbeCabbe = afw.isBoolean( AutoFeatures.cancelAllBlockBreakEvents ); - results.add( String.format(". Cancel all Block Break Events:&b %s", - Boolean.toString( bbeCabbe ) ) ); - - - boolean bbeCabebd = afw.isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ); - results.add( String.format(". Cancel All Block Break Events Block Drops:&b %s", - 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 ) ); - - - + AutoFeaturesWrapper afw = AutoFeaturesWrapper.getInstance(); + + + boolean isAutoManagerEnabled = afw.isBoolean( AutoFeatures.isAutoManagerEnabled ); + + String autoMangerHeader = "&7AutoManager: " + + ( isAutoManagerEnabled ? "&9Enabled" : "&9Not Enabled" ); + + results.add( autoMangerHeader ); + + if ( isAutoManagerEnabled ) { + + + boolean bbeAbbtst = afw.isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ); + results.add( String.format( ". Apply Block Breaks through Sync Tasks:&b %s", + Boolean.toString( bbeAbbtst ) ) ); + + + boolean bbeCabbe = afw.isBoolean( AutoFeatures.cancelAllBlockBreakEvents ); + results.add( String.format( ". Cancel all Block Break Events:&b %s", + Boolean.toString( bbeCabbe ) ) ); + + + boolean bbeCabebd = afw.isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ); + results.add( String.format( ". Cancel All Block Break Events Block Drops:&b %s", + 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 ); @@ -2277,8 +2322,8 @@ public List getActiveFeatures( boolean showLaddersAndRanks ) { // pebbeEventPriority.name(), // (isPebbeEnabled ? "&2Enabled" : "&cDisabled") // ) ); - - + + // String peeePriority = afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); // boolean isPeeeEnabled = peeePriority != null && !"DISABLED".equalsIgnoreCase( peeePriority ); // BlockBreakPriority peeeEventPriority = BlockBreakPriority.fromString( peeePriority ); @@ -2296,8 +2341,8 @@ public List getActiveFeatures( boolean showLaddersAndRanks ) { // tebEventPriority.name(), // (isTebeEnabled ? "&2Enabled" : "&cDisabled") // ) ); - - + + // String reeePriority = afw.getMessage( AutoFeatures.RevEnchantsExplosiveEventPriority ); // boolean isReeeEnabled = reeePriority != null && !"DISABLED".equalsIgnoreCase( reeePriority ); // BlockBreakPriority reeEventPriority = BlockBreakPriority.fromString( reeePriority ); @@ -2315,8 +2360,8 @@ public List getActiveFeatures( boolean showLaddersAndRanks ) { // rejhEventPriority.name(), // (isRejheEnabled ? "&2Enabled" : "&cDisabled") // ) ); - - + + // String cebuePriority = afw.getMessage( AutoFeatures.CrazyEnchantsBlastUseEventPriority ); // boolean isCebueEnabled = cebuePriority != null && !"DISABLED".equalsIgnoreCase( cebuePriority ); // BlockBreakPriority cebuEventPriority = BlockBreakPriority.fromString( cebuePriority ); @@ -2335,206 +2380,202 @@ public List getActiveFeatures( boolean showLaddersAndRanks ) { // (isZbseEnabled ? "&2Enabled" : "&cDisabled") // ) ); - - - - -// String peeePriority = afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); -// boolean isPeeeeEnabled = afw.isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); -// BlockBreakPriority peeEventPriority = BlockBreakPriority.fromString( peeePriority ); -// results.add( String.format("%s. PrisonEnchants BlockExplodeEvent Priority:&b %s %s", -// (isPeeeeEnabled ? "" : "+" ), -// peeEventPriority.name(), -// (isPeeeeEnabled ? "&2Enabled" : "&cDisabled") -// ) ); -// -// results.add( " " ); - - - boolean isAutoFeaturesEnabled = afw.isBoolean( AutoFeatures.isAutoFeaturesEnabled ); - if ( !isAutoFeaturesEnabled ) { - results.add( ". AutoFeatures are disabled:" ); - } - - boolean isAutoPickup = afw.isBoolean( AutoFeatures.autoPickupEnabled ); - results.add( String.format(". Auto Pickup:&b %s", (!isAutoFeaturesEnabled ? "disabled" : - isAutoPickup )) ); - - results.add( String.format(". Auto Smelt:&b %s", (!isAutoFeaturesEnabled ? "disabled" : - afw.isBoolean( AutoFeatures.autoSmeltEnabled ))) ); - - results.add( String.format(". Auto Block:&b %s", (!isAutoFeaturesEnabled ? "disabled" : - afw.isBoolean( AutoFeatures.autoBlockEnabled ))) ); - - - results.add( String.format("%s. Handle Normal Drops:&b %s %s", - (isAutoFeaturesEnabled ? "+" : ""), - (afw.isBoolean( AutoFeatures.handleNormalDropsEvents ) ? "&2Enabled" : "&cDisabled" ), - (isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "") ) ); - results.add( String.format("%s. Normal Drop Smelt:&b %s", - (isAutoFeaturesEnabled ? "+" : ""), - (afw.isBoolean( AutoFeatures.normalDropSmelt ) ? "&2Enabled" : "&cDisabled" ), - (isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "") ) ); - - results.add( String.format("%s. Normal Drop Block:&b %s", - (isAutoFeaturesEnabled ? "+" : ""), - (afw.isBoolean( AutoFeatures.normalDropBlock ) ? "&2Enabled" : "&cDisabled" ), - (isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "") ) ); - - results.add( String.format("%s. Normal Drop Check for Full Inventory:&b %s", - (isAutoFeaturesEnabled ? "+" : ""), - (afw.isBoolean( AutoFeatures.normalDropCheckForFullInventory ) ? "&2Enabled" : "&cDisabled" ), - (isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "") ) ); - - - - results.add( " " ); - - boolean isDurabilityEnabled = afw.isBoolean( AutoFeatures.isCalculateDurabilityEnabled ); - results.add( String.format("%s. Calculate Durability:&b %s", - (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) ); - - 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", - isExtendedBukkitFortune) ); - - results.add( String.format("+. . Extended Bukkit Fortune Factor Percent Range Low:&b %s", - afw.getInteger( AutoFeatures.extendBukkitFortuneFactorPercentRangeLow )) ); - results.add( String.format("+. . Extended Bukkit Fortune Factor Percent Range High:&b %s", - 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", - (isExtendedBukkitFortune ? "+" : "" ), - ( isAltFortune ? "&2Enabled" : "&cDisabled") - ) ); - results.add( String.format("%s. . Calculate Alt Fortune on all Blocks:&b %s", - (isExtendedBukkitFortune ? "+" : "" ), - ( 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( " " ); - - - boolean isXpEnabled = afw.isBoolean( AutoFeatures.isCalculateXPEnabled ); - results.add( String.format("%s. Calculate XP:&b %s", - (isXpEnabled ? "" : "+"), - isXpEnabled ) ); - results.add( String.format("%s. Drop XP as Orbs:&b %s", - (isXpEnabled ? "" : "+"), - afw.isBoolean( AutoFeatures.givePlayerXPAsOrbDrops )) ); - - boolean isFoodExhustionEnabled = afw.isBoolean( AutoFeatures.isCalculateFoodExhustion ); - results.add( String.format("%s. Calculate Food Exhustion:&b %s", - (isFoodExhustionEnabled ? "" : "+"), - isFoodExhustionEnabled ) ); - - boolean isCalcAdditionalItemsEnabled = afw.isBoolean( AutoFeatures.isCalculateDropAdditionsEnabled ); - results.add( String.format("%s. Calculate Additional Items in Drop:&b %s (like flint in gravel)", - (isCalcAdditionalItemsEnabled ? "" : "+"), - isCalcAdditionalItemsEnabled ) ); - - - - - - } - - - results.add( String.format("Prestiges Enabled:&b %s", - getConfigBooleanFalse( "prestige.enabled" )) ); - results.add( String.format(". Reset Money:&b %s", - getConfigBooleanFalse( "prestige.resetMoney" )) ); - results.add( String.format(". Reset Default Ladder:&b %s", - getConfigBooleanFalse( "prestige.resetDefaultLadder" )) ); +// String peeePriority = afw.getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); +// boolean isPeeeeEnabled = afw.isBoolean( AutoFeatures.isProcessPrisonEnchantsExplosiveEvents ); +// BlockBreakPriority peeEventPriority = BlockBreakPriority.fromString( peeePriority ); +// results.add( String.format("%s. PrisonEnchants BlockExplodeEvent Priority:&b %s %s", +// (isPeeeeEnabled ? "" : "+" ), +// peeEventPriority.name(), +// (isPeeeeEnabled ? "&2Enabled" : "&cDisabled") +// ) ); +// +// results.add( " " ); + + + boolean isAutoFeaturesEnabled = afw.isBoolean( AutoFeatures.isAutoFeaturesEnabled ); + if ( !isAutoFeaturesEnabled ) { + results.add( ". AutoFeatures are disabled:" ); + } + + boolean isAutoPickup = afw.isBoolean( AutoFeatures.autoPickupEnabled ); + results.add( String.format( ". Auto Pickup:&b %s", ( !isAutoFeaturesEnabled ? "disabled" : isAutoPickup ) ) ); + + results.add( String.format( ". Auto Smelt:&b %s", ( !isAutoFeaturesEnabled ? "disabled" : afw.isBoolean( AutoFeatures.autoSmeltEnabled ) ) ) ); + + results.add( String.format( ". Auto Block:&b %s", ( !isAutoFeaturesEnabled ? "disabled" : afw.isBoolean( AutoFeatures.autoBlockEnabled ) ) ) ); + + + results.add( String.format( "%s. Handle Normal Drops:&b %s %s", + ( isAutoFeaturesEnabled ? "+" : "" ), + ( afw.isBoolean( AutoFeatures.handleNormalDropsEvents ) ? "&2Enabled" : "&cDisabled" ), + ( isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "" ) ) ); + results.add( String.format( "%s. Normal Drop Smelt:&b %s", + ( isAutoFeaturesEnabled ? "+" : "" ), + ( afw.isBoolean( AutoFeatures.normalDropSmelt ) ? "&2Enabled" : "&cDisabled" ), + ( isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "" ) ) ); + + results.add( String.format( "%s. Normal Drop Block:&b %s", + ( isAutoFeaturesEnabled ? "+" : "" ), + ( afw.isBoolean( AutoFeatures.normalDropBlock ) ? "&2Enabled" : "&cDisabled" ), + ( isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "" ) ) ); + + results.add( String.format( "%s. Normal Drop Check for Full Inventory:&b %s", + ( isAutoFeaturesEnabled ? "+" : "" ), + ( afw.isBoolean( AutoFeatures.normalDropCheckForFullInventory ) ? "&2Enabled" : "&cDisabled" ), + ( isAutoFeaturesEnabled ? "&d[Overridden by AutoPickup]" : "" ) ) ); + + + results.add( " " ); + results.add( String.format( ". Include player inventory when smelting:&b%s", + ( afw.isBoolean( AutoFeatures.includePlayerInventoryWhenSmelting ) ? "&2Enabled" : "&cDisabled" ) ) ); + results.add( String.format( ". Include player inventory when blocking:&b%s", + ( afw.isBoolean( AutoFeatures.includePlayerInventoryWhenBlocking ) ? "&2Enabled" : "&cDisabled" ) ) ); + + + results.add( " " ); + + boolean isDurabilityEnabled = afw.isBoolean( AutoFeatures.isCalculateDurabilityEnabled ); + results.add( String.format( "%s. Calculate Durability:&b %s", + ( 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 ) ); + + boolean isUseTEFortuneLevel = afw.isBoolean( AutoFeatures.isUseTokenEnchantsFortuneLevel ); + results.add( String.format( "%s. . Use TokenEnchants Fortune Level:&b %b", + ( isUseTEFortuneLevel ? "" : "+" ), + isUseTEFortuneLevel ) ); + + boolean isUseRevFortuneLevel = afw.isBoolean( AutoFeatures.isUseRevEnchantsFortuneLevel ); + results.add( String.format( "%s. . Use RevEnchants Fortune Level:&b %b", + ( isUseRevFortuneLevel ? "" : "+" ), + isUseRevFortuneLevel ) ); + + 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", + isExtendedBukkitFortune ) ); + + results.add( String.format( "+. . Extended Bukkit Fortune Factor Percent Range Low:&b %s", + afw.getInteger( AutoFeatures.extendBukkitFortuneFactorPercentRangeLow ) ) ); + results.add( String.format( "+. . Extended Bukkit Fortune Factor Percent Range High:&b %s", + 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", + ( isExtendedBukkitFortune ? "+" : "" ), + ( isAltFortune ? "&2Enabled" : "&cDisabled" ) ) ); + results.add( String.format( "%s. . Calculate Alt Fortune on all Blocks:&b %s", + ( isExtendedBukkitFortune ? "+" : "" ), + ( 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( " " ); + + + boolean isXpEnabled = afw.isBoolean( AutoFeatures.isCalculateXPEnabled ); + results.add( String.format( "%s. Calculate XP:&b %s", + ( isXpEnabled ? "" : "+" ), + isXpEnabled ) ); + results.add( String.format( "%s. Drop XP as Orbs:&b %s", + ( isXpEnabled ? "" : "+" ), + afw.isBoolean( AutoFeatures.givePlayerXPAsOrbDrops ) ) ); + + boolean isFoodExhustionEnabled = afw.isBoolean( AutoFeatures.isCalculateFoodExhustion ); + results.add( String.format( "%s. Calculate Food Exhustion:&b %s", + ( isFoodExhustionEnabled ? "" : "+" ), + isFoodExhustionEnabled ) ); + + boolean isCalcAdditionalItemsEnabled = afw.isBoolean( AutoFeatures.isCalculateDropAdditionsEnabled ); + results.add( String.format( "%s. Calculate Additional Items in Drop:&b %s (like flint in gravel)", + ( isCalcAdditionalItemsEnabled ? "" : "+" ), + isCalcAdditionalItemsEnabled ) ); + + + } + + + results.add( String.format( "Prestiges Enabled:&b %s", + getConfigBooleanFalse( "prestige.enabled" ) ) ); + results.add( String.format( ". Reset Money:&b %s", + getConfigBooleanFalse( "prestige.resetMoney" ) ) ); + results.add( String.format( ". Reset Default Ladder:&b %s", + getConfigBooleanFalse( "prestige.resetDefaultLadder" ) ) ); + + + results.add( "" ); + + + boolean delayedPrisonStartup = getConfigBooleanFalse( "delayedCMIStartup" ); + if ( delayedPrisonStartup ) { + + results.add( String.format( "Prison Delayed Start:&b %s", delayedPrisonStartup ) ); + } + + + results.add( String.format( "GUI Enabled:&b %s", + getConfigBooleanFalse( "prison-gui-enabled" ) ) ); + + + results.add( String.format( "Sellall Enabled:&b %s", + Boolean.toString( SpigotPrison.getInstance().isSellAllEnabled() ) ) ); + + + results.add( String.format( "Backpacks Enabled:&b %s", + getConfigBooleanFalse( "backpacks" ) ) ); - results.add( "" ); - - - boolean delayedPrisonStartup = getConfigBooleanFalse( "delayedCMIStartup" ); - if ( delayedPrisonStartup ) { - - results.add( String.format("Prison Delayed Start:&b %s", delayedPrisonStartup) ); - } - - - results.add( String.format("GUI Enabled:&b %s", - getConfigBooleanFalse( "prison-gui-enabled" )) ); - - - results.add( String.format("Sellall Enabled:&b %s", - Boolean.toString( SpigotPrison.getInstance().isSellAllEnabled() )) ); - - - results.add( String.format("Backpacks Enabled:&b %s", - getConfigBooleanFalse( "backpacks" )) ); - - return results; } @@ -2559,58 +2600,55 @@ private String formatAFEvent(String description, AutoFeatures autoFeature ) { } @Override - public void prisonVersionFeatures( ChatDisplay display, boolean isBasic, + public void prisonVersionFeatures( ChatDisplay display, boolean isBasic, boolean showLaddersAndRanks ) { - - - - List features = getActiveFeatures( showLaddersAndRanks ); - if ( features.size() > 0 ) { - - display.addText(""); - for ( String feature : features ) { - - if ( !feature.startsWith( "+" ) ) { - - display.addText( feature ); - } - else if ( !isBasic ) { - - display.addText( feature.substring( 1 ) ); - } - } - } - - - display.addText(""); - - // Active Modules:x's root Command: &3/prison"); - - for ( Module module : Prison.get().getModuleManager().getModules() ) { - - display.addText( "&7Module: %s : %s %s", module.getName(), - module.getStatus().getStatusText(), - (module.getStatus().getStatus() == ModuleStatus.Status.FAILED ? - "[" + module.getStatus().getMessage() + "]" : "") - ); - // display.addText( ". &7Base Commands: %s", module.getBaseCommands() ); - } - - List disabledModules = Prison.get().getModuleManager().getDisabledModules(); - if ( disabledModules.size() > 0 ) { - display.addText( "&7Disabled Module%s:", (disabledModules.size() > 1 ? "s" : "")); - for ( String disabledModule : Prison.get().getModuleManager().getDisabledModules() ) { - display.addText( ". &cDisabled Module:&7 %s. Related commands and placeholders are non-functional. ", - disabledModule ); - } - } - - display.addText(""); - display.addText("&7Integrations:"); - IntegrationManager im = Prison.get().getIntegrationManager(); - + List features = getActiveFeatures( showLaddersAndRanks ); + if ( features.size() > 0 ) { + + display.addText( "" ); + for ( String feature : features ) { + + if ( !feature.startsWith( "+" ) ) { + + display.addText( feature ); + } + else if ( !isBasic ) { + + display.addText( feature.substring( 1 ) ); + } + } + } + + + display.addText( "" ); + + + // Active Modules:x's root Command: &3/prison"); + + for ( Module module : Prison.get().getModuleManager().getModules() ) { + + display.addText( "&7Module: %s : %s %s", module.getName(), + module.getStatus().getStatusText(), + ( module.getStatus().getStatus() == ModuleStatus.Status.FAILED ? "[" + module.getStatus().getMessage() + "]" : "" ) ); + // display.addText( ". &7Base Commands: %s", module.getBaseCommands() ); + } + + List disabledModules = Prison.get().getModuleManager().getDisabledModules(); + if ( disabledModules.size() > 0 ) { + display.addText( "&7Disabled Module%s:", ( disabledModules.size() > 1 ? "s" : "" ) ); + for ( String disabledModule : Prison.get().getModuleManager().getDisabledModules() ) { + display.addText( ". &cDisabled Module:&7 %s. Related commands and placeholders are non-functional. ", + disabledModule ); + } + } + + display.addText( "" ); + display.addText( "&7Integrations:" ); + + IntegrationManager im = Prison.get().getIntegrationManager(); + // Set inTypeKeys = im.getIntegrations().keySet(); // for (IntegrationType inTypeKey : inTypeKeys ) { // List integrations = im.getIntegrations().get( inTypeKey ); @@ -2621,62 +2659,54 @@ else if ( !isBasic ) { // // } // } - - String permissions = - (im.hasForType(IntegrationType.PERMISSION) ? - " " + im.getForType(IntegrationType.PERMISSION).get().getDisplayName() : - "None"); - display.addText(". . &7Permissions: " + permissions); + String permissions = ( im.hasForType( IntegrationType.PERMISSION ) ? " " + im.getForType( IntegrationType.PERMISSION ).get().getDisplayName() : "None" ); - String economy = - (im.hasForType(IntegrationType.ECONOMY) ? - " " + im.getForType(IntegrationType.ECONOMY).get().getDisplayName() : - "None"); + display.addText( ". . &7Permissions: " + permissions ); - display.addText(". . &7Economy: " + economy); - - - List integrationRows = im.getIntegrationComponents( isBasic ); - for ( DisplayComponent component : integrationRows ) - { - display.addComponent( component ); + String economy = ( im.hasForType( IntegrationType.ECONOMY ) ? " " + im.getForType( IntegrationType.ECONOMY ).get().getDisplayName() : "None" ); + + display.addText( ". . &7Economy: " + economy ); + + + List integrationRows = im.getIntegrationComponents( isBasic ); + for ( DisplayComponent component : integrationRows ) { + display.addComponent( component ); } - - - display.addText(""); - display.addText( TopNPlayers.getInstance().getTopNStats() ); - - - display.addText(""); - display.addText("&7Locale Settings:"); - - for ( String localeInfo : Prison.get().getLocaleLoadInfo() ) { + + display.addText( "" ); + display.addText( TopNPlayers.getInstance().getTopNStats() ); + + + display.addText( "" ); + display.addText( "&7Locale Settings:" ); + + for ( String localeInfo : Prison.get().getLocaleLoadInfo() ) { display.addText( ". . " + localeInfo ); } - - - identifyRegisteredPlugins(); - - List registeredPlugins = Prison.get().getPrisonCommands().getRegisteredPlugins(); - - - // NOTE: This list of plugins is good enough and the detailed does not have all the info. - // Display all loaded plugins: - if ( registeredPlugins.size() > 0 ) { - display.addText(""); - display.addText( "&7Registered Plugins: " ); - + + + identifyRegisteredPlugins(); + + List registeredPlugins = Prison.get().getPrisonCommands().getRegisteredPlugins(); + + + // NOTE: This list of plugins is good enough and the detailed does not have all the info. + // Display all loaded plugins: + if ( registeredPlugins.size() > 0 ) { + display.addText( "" ); + display.addText( "&7Registered Plugins: " ); + // List plugins = getRegisteredPlugins(); - Collections.sort( registeredPlugins ); - List plugins2Cols = Text.formatColumnsFromList( registeredPlugins, 2 ); - - for ( String rp : plugins2Cols ) { - - display.addText( rp ); + Collections.sort( registeredPlugins ); + List plugins2Cols = Text.formatColumnsFromList( registeredPlugins, 2 ); + + for ( String rp : plugins2Cols ) { + + display.addText( rp ); } - + // StringBuilder sb = new StringBuilder(); // for ( String plugin : getRegisteredPlugins() ) { // if ( sb.length() == 0) { @@ -2692,9 +2722,9 @@ else if ( !isBasic ) { // if ( sb.length() > 0 ) { // display.addText( sb.toString()); // } - } - - // This version of plugins does not have all the registered commands: + } + + // This version of plugins does not have all the registered commands: // // The new plugin listings: // if ( getRegisteredPluginData().size() > 0 ) { // display.text( "&7Registered Plugins Detailed: " ); @@ -2718,36 +2748,39 @@ else if ( !isBasic ) { // display.text( sb.toString()); // } // } - - + + // RegisteredPluginsData plugin = getRegisteredPluginData().get( "Prison" ); // String pluginDetails = plugin.getdetails(); // // display.text( pluginDetails ); - + // if ( !isBasic ) { // Prison.get().getPlatform().dumpEventListenersBlockBreakEvents(); // } - - - Prison.get().getPlatform().getWorldLoadErrors( display ); - if ( !isBasic && Prison.get().getPrisonCommands().getPrisonStartupDetails().size() > 0 ) { - display.addText(""); - - for ( String msg : Prison.get().getPrisonCommands().getPrisonStartupDetails() ) { + + Prison.get().getPlatform().getWorldLoadErrors( display ); + + if ( !isBasic && Prison.get().getPrisonCommands().getPrisonStartupDetails().size() > 0 ) { + display.addText( "" ); + + for ( String msg : Prison.get().getPrisonCommands().getPrisonStartupDetails() ) { display.addText( msg ); } - } + } - - // 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 + + // 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(); + + } + @Override public PlayerUtil getPlayerUtil( UUID playerUuid ) { return new SpigotPlayerUtil( playerUuid ); @@ -2772,14 +2805,12 @@ public String dumpEventListenersBlockBreakEvents() { // NOTE: the use of '..==..' prevents these packages from being shortened. See end of this function. sb.append( "\n" ); - sb.append( "&2NOTE: Prison Block Event Listeners:\n" ); + sb.append( "&2NOTE: Prison's Block-Event Listeners:\n" ); - sb.append( "&2. . Prison Internal BlockBreakEvents: " + + sb.append( "&2. . Prison Internal BlockBreakEvents (non-auto features): " + "tmps.SpigotListener\n" ); sb.append( "&2. . Auto Features: " + - "tmps.ae.AutoManagerBlockBreakEvents$AutoManagerBlockBreakEventListener\n" ); - sb.append( "&2. . Prison's multi-block explosions (bombs): " + - "tmpsae.AutoManagerPrisonsExplosiveBlockBreakEvents$AutoManagerExplosiveBlockBreakEventListener\n" ); + "tmps.ae.AutoManagerBlockBreakEvents$*]\n" ); sb.append( "&2. . Prison Abbrv: '&3tmps.&2' = '&3tech..==..mcprison.prison.spigot.&2' & " + "'&3tmps.ae.&2' = '&3tmps..==..autofeatures.events.&2'\n" ); @@ -2801,6 +2832,12 @@ public String dumpEventListenersBlockBreakEvents() { AutoManagerPrisonsExplosiveBlockBreakEvents prisonExplosiveEnchants = new AutoManagerPrisonsExplosiveBlockBreakEvents(); prisonExplosiveEnchants.dumpEventListeners( sb ); + + // Bukkit's EntityExplodeEvent... used by creepers and enchantment plugins like ExcellentEnchants. + AutoManagerEntityExplodeEvents bukkitEntityExplodeEvent = new AutoManagerEntityExplodeEvents(); + bukkitEntityExplodeEvent.dumpEventListeners( sb ); + + AutoManagerCrazyEnchants crazyEnchants = new AutoManagerCrazyEnchants(); crazyEnchants.dumpEventListeners( sb ); @@ -2853,7 +2890,7 @@ public String dumpEventListenersPlayerChatEvents() { sb.append( eventDisplay.toStringBuilder() ); } - if ( new BluesSpigetSemVerComparator().compareMCVersionTo("1.17.0") < 0 ) { + if ( new BluesSemanticVersionComparator().compareMCVersionTo("1.17.0") < 0 ) { eventDisplay = dumpEventListenersChatDisplay( "PlayerChatEvent", @@ -3038,7 +3075,6 @@ public void reloadAutoFeaturesEventListeners() { @Override public void traceEventListenersBlockBreakEvents( tech.mcprison.prison.internal.CommandSender sender ) { - // TODO Auto-generated method stub Output.get().logInfo( "This feature is not enabled yet." ); } @@ -3113,73 +3149,70 @@ public boolean isMineNameValid( String mineName ) { @Override public String getMinesListString() { + String results = ""; - + if ( PrisonMines.getInstance().isEnabled() ) { - + MinesCommands mc = PrisonMines.getInstance().getMinesCommands(); - - - ChatDisplay display = new ChatDisplay("Mines"); - + + + 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 results; -// return Text.stripColor( sb.toString() ); + + return results; } @Override public String getRanksListString() { + StringBuilder sb = new StringBuilder(); - + if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { - - LadderCommands lc = - PrisonRanks.getInstance().getRankManager().getLadderCommands(); - - RanksCommands rc = - PrisonRanks.getInstance().getRankManager().getRanksCommands(); - + + LadderCommands lc = PrisonRanks.getInstance().getRankManager().getLadderCommands(); + + RanksCommands rc = PrisonRanks.getInstance().getRankManager().getRanksCommands(); + sb.append( "\n\n" ); - + ChatDisplay displayLadders = lc.getLadderList(); - + sb.append( displayLadders.toStringBuilder() ); sb.append( "\n" ); - - + + RankPlayer rPlayer = null; - - ChatDisplay displayRanks = new ChatDisplay("Ranks"); + + 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() ); + + + return sb.toString(); } @@ -3241,7 +3274,7 @@ public void setActionBar( Player player, String actionBar ) { @Override public int compareServerVerisonTo( String comparisonVersion ) { - return new BluesSpigetSemVerComparator().compareMCVersionTo( comparisonVersion ); + return new BluesSemanticVersionComparator().compareMCVersionTo( comparisonVersion ); } @Override @@ -3252,49 +3285,54 @@ public void checkPlayerDefaultRank( RankPlayer rPlayer ) { @Override - public void listAllMines(tech.mcprison.prison.internal.CommandSender sender, Player player) { + public void listAllMines( tech.mcprison.prison.internal.CommandSender sender, Player player ) { - RankPlayer rPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer(player); List mines = new ArrayList<>(); - + + RankPlayer rPlayer = null; + + if ( PrisonRanks.getInstance().isEnabled() ) { + rPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer( player ); + } + if ( rPlayer != null ) { - + Set keys = rPlayer.getLadderRanks().keySet(); for ( RankLadder key : keys ) { - PlayerRank pRank = rPlayer.getLadderRanks().get(key); - + PlayerRank pRank = rPlayer.getLadderRanks().get( key ); + listMines( sender, player, pRank, mines ); } - - + + if ( mines.size() > 0 ) { - + // String builder will be used to track what the "real" text width is: StringBuilder sb = new StringBuilder(); - + RowComponent row = new RowComponent(); row.addTextComponent( "&3Mines: " ); sb.append( "&3Mines: " ); for ( Mine mine : mines ) { - - FancyMessage msgMine = new FancyMessage( String.format( "%s", mine.getTag() ) ) - .suggest( "/mines tp " + mine.getName() ) - .tooltip("Click to teleport to mine"); - - row.addFancy( msgMine ); - sb.append( mine.getTag() ); - - row.addTextComponent( " " ); - sb.append( " " ); - - String noColor = Text.stripColor( sb.toString() ); - - if ( noColor.length() > 50 ) { + + FancyMessage msgMine = new FancyMessage( String.format( "%s", mine.getTag() ) ) + .suggest( "/mines tp " + mine.getName() ) + .tooltip( "Click to teleport to mine" ); + + row.addFancy( msgMine ); + sb.append( mine.getTag() ); + + row.addTextComponent( " " ); + sb.append( " " ); + + String noColor = Text.stripColor( sb.toString() ); + + if ( noColor.length() > 50 ) { // Send the player the mines list: row.send( sender ); - + // Reset the row and sb to start on the next row of mines: row = new RowComponent(); sb.setLength( 0 ); @@ -3302,7 +3340,7 @@ public void listAllMines(tech.mcprison.prison.internal.CommandSender sender, Pla // Setup the start of the row: row.addTextComponent( "&3Mines: " ); sb.append( "&3Mines: " ); - + } } if ( sb.length() > 0 ) { @@ -3310,7 +3348,7 @@ public void listAllMines(tech.mcprison.prison.internal.CommandSender sender, Pla row.send( sender ); } } - + } } @@ -3368,7 +3406,13 @@ public void sellall( RankPlayer rankPlayer ) { @Override public RankLadder getRankLadder(String ladderName) { - RankLadder results = PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); + RankLadder results = null; + + if ( PrisonRanks.getInstance().isEnabled() ) { + results = + PrisonRanks.getInstance().getLadderManager().getLadder( ladderName ); + } + return results; } @@ -3383,7 +3427,8 @@ public List getPlayerOldBackpacks( Player player ) { getPlayer( player.getName() ).orElse(null); - if ( sPlayer != null && getConfigBooleanFalse( "backpacks" ) && BackpacksUtil.isEnabled() ) { + if ( sPlayer != null && getConfigBooleanFalse( "backpacks" ) && + BackpacksUtil.getInstance().isEnabled() ) { BackpacksUtil backpackUtil = BackpacksUtil.get(); @@ -3482,40 +3527,25 @@ public Map loadYaml( File file ) { e1.printStackTrace(); } -// try { -// Class worldClass = Class.forName( "org.bukkit.World" ); -// YamlConfiguration yaml = SpigotPrison.getInstance().loadExternalConfig( file ); -// -// if ( yaml != null ) { -// values = yaml.getValues( true ); -// -// -// if ( yaml.contains( "teleport_location" ) ) { -// -// org.bukkit.Location loc = -// (org.bukkit.Location) yaml.getObject( -// "teleport_location", org.bukkit.Location.class ); -// -// org.bukkit.World world = loc.getWorld(); -// -// if ( loc != null ) { -// values.put( "teleport_location.world", world.getName() ); -// values.put( "teleport_location.x", Double.valueOf( loc.getX()) ); -// values.put( "teleport_location.y", Double.valueOf( loc.getY()) ); -// values.put( "teleport_location.z", Double.valueOf( loc.getZ()) ); -// values.put( "teleport_location.pitch", Double.valueOf( loc.getPitch()) ); -// values.put( "teleport_location.yaw", Double.valueOf( loc.getYaw()) ); -// -// } -// } -// } -// -// } catch (ClassNotFoundException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } - - return values; } + + + /** + * This function is used when setting up mine bomb's effects. + * If first checks to see if an effect is valid for the platform's version, + * and if it is, then the effect is marked as valid. + * + * Any invalid effects are not added to the mine bombs. This eliminates and + * runtime errors using invalid effects. + * + */ + public MineBombEffectsData validateMineBombEffect(MineBombEffectsData mineBombEffect ) { + + PrisonUtilsMineBombs mbUtil = PrisonUtilsMineBombs.getInstance(); + + mbUtil.validateMineBommbEffect( mineBombEffect ); + + return mineBombEffect; + } } 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 d9710006d..1536e6c15 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 @@ -60,8 +60,10 @@ import tech.mcprison.prison.sellall.PrisonSellall; import tech.mcprison.prison.sellall.commands.SellallCommands; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; +import tech.mcprison.prison.spigot.autofeatures.PrisonDebugBlockInspectorCommand; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerBlockBreakEvents; import tech.mcprison.prison.spigot.backpacks.BackpacksListeners; +import tech.mcprison.prison.spigot.backpacks.BackpacksUtil; import tech.mcprison.prison.spigot.block.OnBlockBreakEventListener; import tech.mcprison.prison.spigot.bstats.PrisonBStats; import tech.mcprison.prison.spigot.commands.PrisonSpigotBackpackCommands; @@ -84,8 +86,11 @@ import tech.mcprison.prison.spigot.economies.EssentialsEconomy; import tech.mcprison.prison.spigot.economies.GemsEconomy; import tech.mcprison.prison.spigot.economies.SaneEconomy; +import tech.mcprison.prison.spigot.economies.TheNewEconomy; import tech.mcprison.prison.spigot.economies.VaultEconomy; import tech.mcprison.prison.spigot.gui.ListenersPrisonManager; +import tech.mcprison.prison.spigot.integrations.IntegrationBackpackAPI; +import tech.mcprison.prison.spigot.integrations.IntegrationMinepacksPlugin; import tech.mcprison.prison.spigot.permissions.LuckPermissions; import tech.mcprison.prison.spigot.permissions.LuckPerms5; import tech.mcprison.prison.spigot.permissions.VaultPermissions; @@ -118,10 +123,8 @@ public class SpigotPrison boolean debug = false; private File dataDirectory; -// private boolean doAlertAboutConvert = false; private AutoManagerFeatures autoFeatures = null; -// private FileConfiguration autoFeaturesConfig = null; private OnBlockBreakEventListener blockBreakEventListeners; @@ -143,8 +146,6 @@ public class SpigotPrison private PrisonBStats prisonBStats; -// private Metrics bStatsMetrics = null; -// private PrisonMetrics bStatsMetrics = null; public static SpigotPrison getInstance(){ @@ -196,111 +197,108 @@ public void onLoad() { } - @Override - public void onEnable() { - - - // Setup the config.yml file and set debug mode: - // config = this; - this.saveDefaultConfig(); - this.debug = getConfig().getBoolean("debug", false); + @Override + public void onEnable() { + + // Setup the config.yml file and set debug mode: + // config = this; + this.saveDefaultConfig(); + this.debug = getConfig().getBoolean( "debug", false ); - // Create the core directory structure if it is missing: - initDataDir(); + + // Create the core directory structure if it is missing: + initDataDir(); // // Setup the localManager (when instantiating Prison) and set the default language: // Prison.get().getLocaleManager().setDefaultLocale( // getConfig().getString("default-language", "en_US")); - // Setup some of the key data structures and object required to be in place - // prior to starting up: - initCommandMap(); - this.scheduler = new SpigotScheduler(this); + // Setup some of the key data structures and object required to be in place + // prior to starting up: + initCommandMap(); + this.scheduler = new SpigotScheduler( this ); - - Prison.get(); - - SpigotPlatform platform = new SpigotPlatform(this); - Prison.get().init( platform, Bukkit.getVersion() ); - - // Initialize storage after setting the platformm in the Prison.get(): - platform.initStorage(); + Prison.get(); + SpigotPlatform platform = new SpigotPlatform( this ); - // Show Prison's splash screen and setup the core components: - Prison.get().init( getDataFolder() ); + Prison.get().init( platform, Bukkit.getVersion() ); - - - // If prison version is new, then make a copy of all config files that may change on startup: - PrisonBackups backups = new PrisonBackups(); - backups.initialStartupVersionCheck(); - + // Initialize storage after setting the platformm in the Prison.get(): + platform.initStorage(); - - - // Enable the spigot locale manager: - getLocaleManager(); - - if ( debug ) { - Output.get().setDebug( debug ); - } - - // Load the Text's language configs: - Text.initialize(); - - - this.compatibility = SpigotCompatibility.getInstance(); + + // Show Prison's splash screen and setup the core components: + Prison.get().init( getDataFolder() ); + + + // If prison version is new, then make a copy of all config files that may change on startup: + PrisonBackups backups = new PrisonBackups(); + backups.initialStartupVersionCheck(); + + + // Enable the spigot locale manager: + getLocaleManager(); + + if ( debug ) { + Output.get().setDebug( debug ); + } + + // Load the Text's language configs: + Text.initialize(); + + + this.compatibility = SpigotCompatibility.getInstance(); // initCompatibility(); Obsolete... - - - initUpdater(); - - - boolean delayedPrisonStartup = getConfig().getBoolean("delayedPrisonStartup.enabled", false); - - if ( !delayedPrisonStartup ) { - - // Check to see if CMI is an active plugin. If it is, then let's enable the delayed startup. - // It should be noted that just because CMI is detected, it does not mean that the CMI Economy - // is being used. Use a flexible startup which means it will start if any vault economy - // is found. - RegisteredPluginsData cmiPlugin = platform.identifyRegisteredPlugin( "CMI" ); - if ( cmiPlugin != null ) { - String cmiMessage = String.format( - "CMI was detected and Prison's delayed startup has been enabled: %s - %s ", - cmiPlugin.getPluginName(), cmiPlugin.getPluginVersion() ); - Output.get().logInfo( cmiMessage ); - - onEnableDelayedStartFlexible(); - } - else { - - onEnableStartup(); - } - } - else { - onEnableDelayedStart(); - } - - } + + initUpdater(); + + + boolean delayedPrisonStartup = getConfig().getBoolean( "delayedPrisonStartup.enabled", false ); + + + if ( !delayedPrisonStartup ) { + + // Check to see if CMI is an active plugin. If it is, then let's enable the delayed startup. + // It should be noted that just because CMI is detected, it does not mean that the CMI Economy + // is being used. Use a flexible startup which means it will start if any vault economy + // is found. + RegisteredPluginsData cmiPlugin = platform.identifyRegisteredPlugin( "CMI" ); + if ( cmiPlugin != null ) { + String cmiMessage = String.format( + "CMI was detected and Prison's delayed startup has been enabled: %s - %s ", + cmiPlugin.getPluginName(), cmiPlugin.getPluginVersion() ); + Output.get().logInfo( cmiMessage ); + + onEnableDelayedStartFlexible(); + } + else { + + onEnableStartup(); + } + } + else { + onEnableDelayedStart(); + } + + } - protected void onEnableDelayedStartFlexible() { - - SpigotPrisonDelayedStartupTask delayedStartupTask = new SpigotPrisonDelayedStartupTask( this ); - delayedStartupTask.setUseAnyVaultEconomy( true ); - delayedStartupTask.submit(); - } + protected void onEnableDelayedStartFlexible() { + + SpigotPrisonDelayedStartupTask delayedStartupTask = new SpigotPrisonDelayedStartupTask( this ); + delayedStartupTask.setUseAnyVaultEconomy( true ); + delayedStartupTask.submit(); + } - protected void onEnableDelayedStart() { - - SpigotPrisonDelayedStartupTask delayedStartupTask = new SpigotPrisonDelayedStartupTask( this ); - delayedStartupTask.submit(); - } + protected void onEnableDelayedStart() { + + SpigotPrisonDelayedStartupTask delayedStartupTask = new SpigotPrisonDelayedStartupTask( this ); + delayedStartupTask.submit(); + } public void onEnableFail() { @@ -313,48 +311,48 @@ public void onEnableFail() { } - public void onEnableStartup() { - + public void onEnableStartup() { - - // Manually register Listeners with Bukkit: - Bukkit.getPluginManager().registerEvents(new ListenersPrisonManager(),this); - - 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); - } - - Bukkit.getPluginManager().registerEvents(new SpigotListener(), this); + // Manually register Listeners with Bukkit: + Bukkit.getPluginManager().registerEvents( new ListenersPrisonManager(), this ); - try { - isBackPacksEnabled = getConfig().getBoolean("backpacks"); - } catch (NullPointerException ignored){} - if (isBackPacksEnabled){ - Bukkit.getPluginManager().registerEvents(new BackpacksListeners(), this); - } + 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 ); + } + + Bukkit.getPluginManager().registerEvents( new SpigotListener(), this ); + + + try { + isBackPacksEnabled = getConfig().getBoolean( "backpacks" ); + } + catch ( NullPointerException ignored ) { + } + + if ( isBackPacksEnabled ) { + Bukkit.getPluginManager().registerEvents( new BackpacksListeners(), this ); + } + + initIntegrations(); + + // Sellall set to disabled since it will be set to the correct value in enableModulesAndCommands(): + isSellAllEnabled = false; - initIntegrations(); - - // 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(); + AutoFeaturesWrapper.getInstance(); + AutoFeaturesWrapper.getBlockConvertersInstance(); + + + // This is the loader for modules and commands: + enableModulesAndCommands(); + - // // NOTE: Put all commands within the initModulesAndCommands() function. // initModulesAndCommands(); // @@ -364,18 +362,18 @@ public void onEnableStartup() { // // After all the integrations have been loaded and the deferred tasks ran, // // then run the deferred Module setups: // initDeferredModules(); - - - // 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 ); - - - // These stats are displayed within the initDeferredModules(): - //Prison.get().getPlatform().getPlaceholders().printPlaceholderStats(); - - - @SuppressWarnings("unused") + + + // 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 ); + + + // These stats are displayed within the initDeferredModules(): + // Prison.get().getPlatform().getPlaceholders().printPlaceholderStats(); + + + @SuppressWarnings( "unused" ) PrisonCommand cmdVersion = Prison.get().getPrisonCommands(); // if (doAlertAboutConvert) { @@ -383,7 +381,7 @@ public void onEnableStartup() { // "&7An old installation of Prison has been detected. &3Type /prison convert to convert your old data automatically. &7If you already converted, delete the 'Prison.old' folder so that we stop nagging you."); // } - // Finally print the version after loading the prison plugin: + // Finally print the version after loading the prison plugin: // // Store all loaded plugins within the PrisonCommand for later inclusion: // for ( Plugin plugin : Bukkit.getPluginManager().getPlugins() ) { @@ -393,122 +391,122 @@ public void onEnableStartup() { // cmdVersion.getRegisteredPlugins().add( value ); // } - - ChatDisplay cdVersion = new ChatDisplay("A suppressed title"); - cdVersion.setShowTitle( false ); + + ChatDisplay cdVersion = new ChatDisplay( "A suppressed title" ); + cdVersion.setShowTitle( false ); // ChatDisplay cdVersion = cmdVersion.displayVersion("basic"); - - // This generates the module listing, the autoFeatures overview, - // the integrations listings, and the plugins listings. - // Used in the command: /prison version + + // This generates the module listing, the autoFeatures overview, + // the integrations listings, and the plugins listings. + // Used in the command: /prison version boolean isBasic = true; boolean showLaddersAndRanks = false; - Prison.get().getPlatform().prisonVersionFeatures( cdVersion, isBasic, showLaddersAndRanks ); + Prison.get().getPlatform().prisonVersionFeatures( cdVersion, isBasic, showLaddersAndRanks ); cdVersion.toLog( LogLevel.INFO ); - + // Provides a startup test of blocks available for the version of spigot that being used: - if ( getConfig().getBoolean("prison-block-compatibility-report") ) { + if ( getConfig().getBoolean( "prison-block-compatibility-report" ) ) { SpigotUtil.testAllPrisonBlockTypes(); } - - // Force a backup if prison version is new: - PrisonBackups backups = new PrisonBackups(); - backups.serverStartupVersionCheck(); - - - // Reload guiConfigs since ranks and mines have now been loaded: - guiConfig.initialize(); - - - - // Setup mine bombs and validate to spigot version: - PrisonUtilsMineBombs.getInstance().reloadPrisonMineBombs(); - PrisonUtilsMineBombs.getInstance().validateMineBombsSpigotVersion(); - - // Enable Temp spigot commands: - new SpigotCommand(); - - // Startup bStats: - prisonBStats.initMetricsOnEnable(); - - - + + // Force a backup if prison version is new: + PrisonBackups backups = new PrisonBackups(); + backups.serverStartupVersionCheck(); + + + // Reload guiConfigs since ranks and mines have now been loaded: + guiConfig.initialize(); + + + // Setup mine bombs and validate to spigot version: + PrisonUtilsMineBombs.getInstance().reloadPrisonMineBombs(); + PrisonUtilsMineBombs.getInstance().validateMineBombsSpigotVersion(); + + // Enable Temp spigot commands: + new SpigotCommand(); + + // Startup bStats: + prisonBStats.initMetricsOnEnable(); + + Output.get().logInfo( "Prison - Finished loading." ); - - + + if ( PrisonInitialStartupTask.isInitialStartup() ) { - + PrisonInitialStartupTask startupTask = new PrisonInitialStartupTask( this ); startupTask.submit(); } - } + } - @Override - public void onDisable() { - if (this.scheduler != null ) { - this.scheduler.cancelAll(); - } - - Prison.get().getPlatform().unregisterAllCommands(); - - Prison.get().deinit(); - } + @Override + public void onDisable() { + + if ( this.scheduler != null ) { + this.scheduler.cancelAll(); + } + + Prison.get().getPlatform().unregisterAllCommands(); + + Prison.get().deinit(); + } - /** - * Lazy load LocalManager which ensures Prison is already loaded so - * can get the default language to use from the plugin configs. - * - * Returns the {@link LocaleManager} for the plugin. This contains the global messages that Prison - * uses to run its command library, and the like. {@link Module}s have their own {@link - * LocaleManager}s, so that each module can have independent localization. - * - * @return The global locale manager instance. - */ - public LocaleManager getLocaleManager() { - - if ( this.localeManager == null ) { - - this.localeManager = new LocaleManager(this, "lang/spigot"); - } - return localeManager; - } + /** + * Lazy load LocalManager which ensures Prison is already loaded so can get the default language to use from the plugin + * configs. + * + * Returns the {@link LocaleManager} for the plugin. This contains the global messages that Prison uses to run its + * command library, and the like. {@link Module}s have their own {@link LocaleManager}s, so that each module can have + * independent localization. + * + * @return The global locale manager instance. + */ + public LocaleManager getLocaleManager() { - /** - * Returns this module's data folder, where all data can be stored. - * It is located in the Prison data folder, and has the name of the module. - * It is automatically generated. - * - * @return The {@link File} representing the data folder. - */ - public File getModuleDataFolder() { - - if ( moduleDataFolder == null ) { - this.moduleDataFolder = Module.setupModuleDataFolder( "spigot" ); - } - return moduleDataFolder; - } + if ( this.localeManager == null ) { + + this.localeManager = new LocaleManager( this, "lang/spigot" ); + } + return localeManager; + } + + /** + * Returns this module's data folder, where all data can be stored. It is located in the Prison data folder, and has the + * name of the module. It is automatically generated. + * + * @return The {@link File} representing the data folder. + */ + public File getModuleDataFolder() { + + if ( moduleDataFolder == null ) { + this.moduleDataFolder = Module.setupModuleDataFolder( "spigot" ); + } + return moduleDataFolder; + } - public OnBlockBreakEventListener getBlockBreakEventListeners() { - if ( blockBreakEventListeners == null ) { - this.blockBreakEventListeners = new OnBlockBreakEventListener(); - } + public OnBlockBreakEventListener getBlockBreakEventListeners() { + + if ( blockBreakEventListeners == null ) { + this.blockBreakEventListeners = new OnBlockBreakEventListener(); + } return blockBreakEventListeners; } public FileConfiguration getGuiConfig() { - if (guiConfig == null) { - guiConfig = new GuiConfig(); - } - return guiConfig.getFileGuiConfig(); - } + + if ( guiConfig == null ) { + guiConfig = new GuiConfig(); + } + return guiConfig.getFileGuiConfig(); + } public FileConfiguration getSellAllConfig(){ return sellAllConfig.getFileSellAllConfig(); @@ -517,7 +515,6 @@ public FileConfiguration getSellAllConfig(){ public FileConfiguration updateSellAllConfig() { // Let this like this or it won't update when you do /Sellall etc and will need a server restart. sellAllConfig = new SellAllConfig(); - sellAllConfig.initialize(); return sellAllConfig.getFileSellAllConfig(); } @@ -581,307 +578,11 @@ public static String format(String format){ return format == null ? "" : ChatColor.translateAlternateColorCodes('&', format); } - public static String stripColor(String format){ - return Text.stripColor(format); -// format = format(format); - -// return format == null ? null : ChatColor.stripColor(format); - } + public static String stripColor( String format ) { + + return Text.stripColor( format ); + } -// /** -// *

    bStats reporting

    -// * -// * https://github.com/Bastian/bStats-Metrics/tree/master/base/src/main/java/org/bstats/charts -// * -// */ -// private void initMetricsOnLoad() { -// if (!getConfig().getBoolean("send-metrics", true)) { -// return; // Don't check if they don't want it -// } -// -// int pluginId = 657; -// bStatsMetrics = new Metrics( this, pluginId ); -//// bStatsMetrics = new PrisonMetrics( this, pluginId ); -// -//// Metrics metrics = new Metrics( this, pluginId ); -// } -// -// private void initMetricsOnEnable() { -// if (!getConfig().getBoolean("send-metrics", true)) { -// return; // Don't check if they don't want it -// } -// -// -// if ( bStatsMetrics == null ) { -// int pluginId = 657; -// -// bStatsMetrics = new Metrics( this, pluginId ); -//// bStatsMetrics = new PrisonMetrics( this, pluginId ); -// } -// -// // Report the modules being used -// SimpleBarChart sbcModulesUsed = new SimpleBarChart("modules_used", () -> { -// Map valueMap = new HashMap<>(); -// for (Module m : PrisonAPI.getModuleManager().getModules()) { -// valueMap.put(m.getName(), 1); -// } -// return valueMap; -// }); -// bStatsMetrics.addCustomChart( sbcModulesUsed ); -// -// // Report the API level -// SimplePie spApiLevel = -// new SimplePie("api_level", () -> -// "API Level " + Prison.API_LEVEL + "." + Prison.API_LEVEL_MINOR ); -// bStatsMetrics.addCustomChart( spApiLevel ); -// -// -// Optional prisonMinesOpt = Prison.get().getModuleManager().getModule( PrisonMines.MODULE_NAME ); -// Optional prisonRanksOpt = Prison.get().getModuleManager().getModule( PrisonRanks.MODULE_NAME ); -// -// int mineCount = prisonMinesOpt.map(module -> ((PrisonMines) module).getMineManager().getMines().size()).orElse(0); -// int rankCount = prisonRanksOpt.map(module -> ((PrisonRanks) module).getRankCount()).orElse(0); -// -// int defaultRankCount = prisonRanksOpt.map(module -> ((PrisonRanks) module).getDefaultLadderRankCount()).orElse(0); -// int prestigesRankCount = prisonRanksOpt.map(module -> ((PrisonRanks) module).getPrestigesLadderRankCount()).orElse(0); -// int otherRankCount = rankCount - defaultRankCount - prestigesRankCount; -// -// int ladderCount = prisonRanksOpt.map(module -> ((PrisonRanks) module).getladderCount()).orElse(0); -// int playerCount = prisonRanksOpt.map(module -> ((PrisonRanks) module).getPlayersCount()).orElse(0); -// -// -// -// DrilldownPie mlcPrisonRanksAndLadders = new DrilldownPie("mines_ranks_and_ladders", () -> { -// Map> map = new HashMap<>(); -// -// Map ranks = new HashMap<>(); -// ranks.put( Integer.toString( mineCount ), 1 ); -// map.put( "mines", ranks ); -// -// Map defRanks = new HashMap<>(); -// defRanks.put( Integer.toString( rankCount ), 1 ); -// map.put( "ranks", defRanks ); -// -// Map prestigesRanks = new HashMap<>(); -// prestigesRanks.put( Integer.toString( ladderCount ), 1 ); -// map.put( "ladders", prestigesRanks ); -// -// Map otherRanks = new HashMap<>(); -// otherRanks.put( Integer.toString( playerCount ), 1 ); -// map.put( "players", otherRanks ); -// -// return map; -// }); -// bStatsMetrics.addCustomChart( mlcPrisonRanksAndLadders ); -// -//// MultiLineChart mlcMinesRanksAndLadders = -//// new MultiLineChart("mines_ranks_and_ladders", new Callable>() { -//// @Override -//// public Map call() throws Exception { -//// Map valueMap = new HashMap<>(); -//// valueMap.put("mines", mineCount); -//// valueMap.put("ranks", rankCount); -//// valueMap.put("ladders", ladderCount); -//// valueMap.put("players", playerCount); -//// return valueMap; -//// } -//// }); -//// bStatsMetrics.addCustomChart( mlcMinesRanksAndLadders ); -// -// -// -// DrilldownPie mlcPrisonPrisonRanks = new DrilldownPie("prison_ranks", () -> { -// Map> map = new HashMap<>(); -// -// Map ranks = new HashMap<>(); -// ranks.put( Integer.toString( rankCount ), 1 ); -// map.put( "ranks", ranks ); -// -// Map defRanks = new HashMap<>(); -// defRanks.put( Integer.toString( defaultRankCount ), 1 ); -// map.put( "defaultRanks", defRanks ); -// -// Map prestigesRanks = new HashMap<>(); -// prestigesRanks.put( Integer.toString( prestigesRankCount ), 1 ); -// map.put( "prestigesRanks", prestigesRanks ); -// -// Map otherRanks = new HashMap<>(); -// otherRanks.put( Integer.toString( otherRankCount ), 1 ); -// map.put( "otherRanks", otherRanks ); -// -// return map; -// }); -// bStatsMetrics.addCustomChart( mlcPrisonPrisonRanks ); -// -//// MultiLineChart mlcPrisonRanks = new MultiLineChart("prison_ranks", new Callable>() { -//// @Override -//// public Map call() throws Exception { -//// Map valueMap = new HashMap<>(); -//// valueMap.put("ranks", rankCount); -//// valueMap.put("defaultRanks", defaultRankCount); -//// valueMap.put("prestigesRanks", prestigesRankCount); -//// valueMap.put("otherRanks", otherRankCount); -//// return valueMap; -//// } -//// }); -//// bStatsMetrics.addCustomChart( mlcPrisonRanks ); -// -// -// DrilldownPie mlcPrisonPrisonLadders = new DrilldownPie("prison_ladders", () -> { -// Map> map = new HashMap<>(); -// -// -// PrisonRanks pRanks = (PrisonRanks) prisonRanksOpt.orElseGet( null ); -// for ( RankLadder ladder : pRanks.getLadderManager().getLadders() ) { -// -// Map entry = new HashMap<>(); -// entry.put( Integer.toString( ladder.getRanks().size() ), 1 ); -// -// map.put( ladder.getName(), entry ); -// } -// -// return map; -// }); -// bStatsMetrics.addCustomChart( mlcPrisonPrisonLadders ); -// -// -//// MultiLineChart mlcPrisonladders = new MultiLineChart("prison_ladders", new Callable>() { -//// @Override -//// public Map call() throws Exception { -//// Map valueMap = new HashMap<>(); -//// -//// PrisonRanks pRanks = (PrisonRanks) prisonRanksOpt.orElseGet( null ); -//// for ( RankLadder ladder : pRanks.getLadderManager().getLadders() ) { -//// -//// valueMap.put( ladder.getName(), ladder.getRanks().size() ); -//// } -//// -//// return valueMap; -//// } -//// }); -//// bStatsMetrics.addCustomChart( mlcPrisonladders ); -// -// TreeMap plugins = Prison.get().getPrisonCommands().getRegisteredPluginData(); -// -// TreeMap pluginsAtoE = getSubsetOfPlugins(plugins, 'a', 'f', false ); -// TreeMap pluginsFtoM = getSubsetOfPlugins(plugins, 'f', 'n', false ); -// TreeMap pluginsNtoS = getSubsetOfPlugins(plugins, 'n', 't', false ); -// TreeMap pluginsTto9 = getSubsetOfPlugins(plugins, 't', 'z', true ); -// -// DrilldownPie mlcPrisonPlugins = new DrilldownPie("plugins", () -> { -// Map> map = new HashMap<>(); -// -// for (String pluginName : plugins.keySet() ) { -// RegisteredPluginsData pluginData = plugins.get( pluginName ); -// -// Map entry = new HashMap<>(); -// entry.put( pluginData.getPluginVersion(), 1 ); -// -// map.put( pluginData.getPluginName(), entry ); -// } -// -// return map; -// }); -// bStatsMetrics.addCustomChart( mlcPrisonPlugins ); -// -// -// DrilldownPie mlcPrisonPluginsAtoE = new DrilldownPie("plugins_a_to_e", () -> { -// Map> map = new HashMap<>(); -// -// for (String pluginName : pluginsAtoE.keySet() ) { -// RegisteredPluginsData pluginData = pluginsAtoE.get( pluginName ); -// -// Map entry = new HashMap<>(); -// entry.put( pluginData.getPluginVersion(), 1 ); -// -// map.put( pluginData.getPluginName(), entry ); -// } -// -// return map; -// }); -// bStatsMetrics.addCustomChart( mlcPrisonPluginsAtoE ); -// -// -// DrilldownPie mlcPrisonPluginsFtoM = new DrilldownPie("plugins_f_to_m", () -> { -// Map> map = new HashMap<>(); -// -// for (String pluginName : pluginsFtoM.keySet() ) { -// RegisteredPluginsData pluginData = pluginsFtoM.get( pluginName ); -// -// Map entry = new HashMap<>(); -// entry.put( pluginData.getPluginVersion(), 1 ); -// -// map.put( pluginData.getPluginName(), entry ); -// } -// -// return map; -// }); -// bStatsMetrics.addCustomChart( mlcPrisonPluginsFtoM ); -// -// -// DrilldownPie mlcPrisonPluginsNtoS = new DrilldownPie("plugins_n_to_s", () -> { -// Map> map = new HashMap<>(); -// -// for (String pluginName : pluginsNtoS.keySet() ) { -// RegisteredPluginsData pluginData = pluginsNtoS.get( pluginName ); -// -// Map entry = new HashMap<>(); -// entry.put( pluginData.getPluginVersion(), 1 ); -// -// map.put( pluginData.getPluginName(), entry ); -// } -// -// return map; -// }); -// bStatsMetrics.addCustomChart( mlcPrisonPluginsNtoS ); -// -// -// DrilldownPie mlcPrisonPluginsTto9 = new DrilldownPie("plugins_t_to_z_plus_others", () -> { -// Map> map = new HashMap<>(); -// -// for (String pluginName : pluginsTto9.keySet() ) { -// RegisteredPluginsData pluginData = pluginsTto9.get( pluginName ); -// -// Map entry = new HashMap<>(); -// entry.put( pluginData.getPluginVersion(), 1 ); -// -// map.put( pluginData.getPluginName(), entry ); -// } -// -// return map; -// }); -// bStatsMetrics.addCustomChart( mlcPrisonPluginsTto9 ); -// -// -// -// } - -// private TreeMap getSubsetOfPlugins( -// TreeMap plugins, -// char rangeLow, char rangeHigh, -// boolean includeNonAlpha ) { -// TreeMap results = new TreeMap<>(); -// -// Set keys = plugins.keySet(); -// for (String key : keys) { -// char keyFirstChar = key.toLowerCase().charAt(0); -// -// if ( Character.isAlphabetic(keyFirstChar) ) { -// -// if ( Character.compare(keyFirstChar, rangeLow) >= 0 && Character.compare( keyFirstChar, rangeHigh) < 0 ) { -// -// results.put( key, plugins.get(key) ); -// } -// } -// else { -// -// // Add all non-alpha plugins to this result: -// results.put( key, plugins.get(key) ); -// } -// } -// -// return results; -// } /** * Checks to see if there is a newer version of prison that has been released. @@ -898,32 +599,6 @@ private void initUpdater() { PrisonSpigetUpdateCheckTask updateCheck = new PrisonSpigetUpdateCheckTask(); updateCheck.submit(); -//// String currentVersion = getDescription().getVersion(); -// -// SpigetUpdate updater = new SpigetUpdate(this, Prison.SPIGOTMC_ORG_PROJECT_ID); -//// SpigetUpdate updater = new SpigetUpdate(this, 1223); -// -// -// BluesSpigetSemVerComparator aRealSemVerComparator = new BluesSpigetSemVerComparator(); -// updater.setVersionComparator( aRealSemVerComparator ); -//// updater.setVersionComparator(VersionComparator.EQUAL); -// -// updater.checkForUpdate( new PrisonSpigetUpdateCallback() ); -// -//// updater.checkForUpdate(new UpdateCallback() { -//// @Override -//// public void updateAvailable(String newVersion, String downloadUrl, -//// boolean hasDirectDownload) { -//// Alerts.getInstance().sendAlert( -//// "&3%s is now available. &7Go to the &lSpigot&r&7 page to download the latest release with new features and fixes :)", -//// newVersion); -//// } -//// -//// @Override -//// public void upToDate() { -//// // Plugin is up-to-date -//// } -//// }); } private void initDataDir() { @@ -933,15 +608,24 @@ private void initDataDir() { } } + /** + * This will initialize the two fields, commandMap and knownCommands, which are from the + * Bukkit server. These will give prison's command handler the ability to easily access + * these fields, which are not normally accessible. + */ private void initCommandMap() { try { commandMap = Bukkit.getServer().getClass().getDeclaredField("commandMap"); commandMap.setAccessible(true); + knownCommands = SimpleCommandMap.class.getDeclaredField("knownCommands"); knownCommands.setAccessible(true); - } catch (NoSuchFieldException e) { + } + catch (NoSuchFieldException e) { getLogger().severe( - "&c&lReflection error: &7Ensure that you're using the latest version of Spigot and Prison."); + "&c&lReflection error: &7Ensure that you're using the latest version of Spigot and Prison. " + + "Unable to access Bukkit.getServer().commandMap field. " + + "or the org.bukkit.command.SimpleCommandMap.knownCommands field."); e.printStackTrace(); } } @@ -959,6 +643,7 @@ private void initIntegrations() { registerIntegration(new EssentialsEconomy()); registerIntegration(new SaneEconomy()); registerIntegration(new GemsEconomy()); + registerIntegration(new TheNewEconomy()); registerIntegration(new CoinsEngineEconomy()); registerIntegration(new EdPrisonEconomy()); @@ -973,13 +658,22 @@ private void initIntegrations() { registerIntegration(new CustomItems()); + + registerIntegration( IntegrationMinepacksPlugin.getInstance() ); + registerIntegration( BackpacksUtil.get() ); + + // Force the registration since IntegrationPackpackAPI is not based + // upon any other plugin: + registerIntegrationForce( IntegrationBackpackAPI.getInstance() ); + + // registerIntegration(new WorldGuard6Integration()); // registerIntegration(new WorldGuard7Integration()); } public boolean isIntegrationRegistered( Integration integration ) { - - return isPluginRegistered( integration.getProviderName() ); + + return isPluginRegistered( integration.getProviderName() ); } protected boolean isPluginRegistered( String pluginName ) { @@ -1003,25 +697,44 @@ public boolean isPluginEnabled( String pluginName ) { */ public void reloadIntegrationsPlaceholders() { -// MVdWPlaceholderIntegration ph1 = new MVdWPlaceholderIntegration(); PlaceHolderAPIIntegration ph2 = new PlaceHolderAPIIntegration(); -// registerIntegration(ph1); registerIntegration(ph2); -// ph1.deferredInitialization(); ph2.deferredInitialization(); } - public void registerIntegration(Integration integration) { + /** + * This is the normal way to register integrations that are based upon other loaded plugins. They must be active, or + * they will not be registered. + * + * @param integration + */ + public void registerIntegration( Integration integration ) { - boolean isRegistered = isIntegrationRegistered( integration ); - String version = ( isRegistered ? Bukkit.getPluginManager() - .getPlugin( integration.getProviderName() ) - .getDescription().getVersion() : null ); - - PrisonAPI.getIntegrationManager().register(integration, isRegistered, version ); - } + boolean isRegistered = isIntegrationRegistered( integration ); + String version = ( isRegistered ? Bukkit.getPluginManager() + .getPlugin( integration.getProviderName() ) + .getDescription().getVersion() : null ); + + PrisonAPI.getIntegrationManager().register( integration, isRegistered, version ); + } + + /** + * This should only be used by Integrations that are not based upon another plugin, such as the IntegrationBackpackAPI, + * which any code in any plugin, can register dynamically as a backpackAPI listener. + * + * This will always treat it as a successful registration, although that does not mean it will be active. + * + * @param integration + */ + public void registerIntegrationForce( Integration integration ) { + + boolean isRegistered = true; + String version = "api"; + + PrisonAPI.getIntegrationManager().register( integration, isRegistered, version ); + } private void enableModulesAndCommands() { @@ -1038,302 +751,305 @@ private void enableModulesAndCommands() { } - private void disableModulesAndCommands() { - - for ( Module module : Prison.get().getModuleManager().getModules() ) { - if ( module.isEnabled() ) { - module.disable(); - } - } - - Prison.get().getCommandHandler().getAllRegisteredCommands(); - } + private void disableModulesAndCommands() { + + for ( Module module : Prison.get().getModuleManager().getModules() ) { + if ( module.isEnabled() ) { + module.disable(); + } + } + + Prison.get().getCommandHandler().getAllRegisteredCommands(); + } - public void resetModulesAndCommands() { - - disableModulesAndCommands(); - - enableModulesAndCommands(); - } + public void resetModulesAndCommands() { + + disableModulesAndCommands(); + + enableModulesAndCommands(); + } - /** - * This function registers all of the modules in prison. It should also manage - * the registration of "extra" commands that are outside of the modules, such - * as gui related commands. - * - */ - private void initModulesAndCommands() { + /** + * This function registers all of the modules in prison. It should also manage the registration of "extra" commands that + * are outside of the modules, such as gui related commands. + * + */ + private void initModulesAndCommands() { - YamlConfiguration modulesConf = loadConfig("modules.yml"); - - boolean isMinesEnabled = false; - boolean isRanksEnabled = false; + YamlConfiguration modulesConf = loadConfig( "modules.yml" ); + + boolean isMinesEnabled = false; + boolean isRanksEnabled = false; + + // TO DO: This business logic needs to be moved to the Module Manager: + if ( modulesConf.getBoolean( "mines" ) ) { + isMinesEnabled = true; - // 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().getModuleManager() + .registerModule( new PrisonMines( getDescription().getVersion() ) ); - // The GUI handler for mines... cannot be hooked up here: + // 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. "); - Output.get().logInfo("&7 Prison Mines have been disabled in &2plugins/Prison/modules.yml&7."); - Prison.get().getModuleManager().getDisabledModules().add( PrisonMines.MODULE_NAME ); - } - if (modulesConf.getBoolean("ranks") ) { - PrisonRanks rankModule = new PrisonRanks(getDescription().getVersion() ); - - // Register and enable Ranks: - Prison.get().getModuleManager().registerModule( rankModule ); + } + else { + Output.get().logInfo( "&7Modules: &cPrison Mines are disabled and were not Loaded. " ); + Output.get().logInfo( "&7 Prison Mines have been disabled in &2plugins/Prison/modules.yml&7." ); + Prison.get().getModuleManager().getDisabledModules().add( PrisonMines.MODULE_NAME ); + } - if ( rankModule.isEnabled() && PrisonAPI.getIntegrationManager().hasForType(IntegrationType.ECONOMY) ) { - - isRanksEnabled = true; - } - } - else { - Output.get().logInfo("&3Modules: &cPrison Ranks, Ladders, and Players are disabled and were not Loaded. "); - Output.get().logInfo("&7 Prestiges cannot be enabled without ranks being enabled. "); - Output.get().logInfo("&7 Prison Ranks have been disabled in &2plugins/Prison/modules.yml&7."); - Prison.get().getModuleManager().getDisabledModules().add( PrisonRanks.MODULE_NAME ); - } - - - // If the sellall module is defined in modules.yml, then use that setting, otherwise - // use the sellall config setting within the config.yml file. - String sellallModuleName = PrisonSellall.MODULE_NAME.toLowerCase(); - boolean isDefined = modulesConf.contains(sellallModuleName); - - // First check to see if the module is enabled (sellall): - if ( isDefined && modulesConf.getBoolean(sellallModuleName) || - // if not, then check to see if sellall is enabled within config.yml: - !isDefined && getConfig().contains("sellall") && getConfig().isBoolean("sellall") ) { - - PrisonSellall sellallModule = new PrisonSellall(getDescription().getVersion() ); - - // Register and enable the sellall module: - Prison.get().getModuleManager().registerModule( sellallModule ); - - Prison.get().getCommandHandler().registerCommands( new SellallCommands() ); - + if ( modulesConf.getBoolean( "ranks" ) ) { + PrisonRanks rankModule = new PrisonRanks( getDescription().getVersion() ); - isSellAllEnabled = true; - - - // If sellall is enabled, then allow it to initialize. + // Register and enable Ranks: + Prison.get().getModuleManager().registerModule( rankModule ); + + if ( rankModule.isEnabled() && PrisonAPI.getIntegrationManager().hasForType( IntegrationType.ECONOMY ) ) { + + isRanksEnabled = true; + } + } + else { + Output.get().logInfo( "&3Modules: &cPrison Ranks, Ladders, and Players are disabled and were not Loaded. " ); + Output.get().logInfo( "&7 Prestiges cannot be enabled without ranks being enabled. " ); + Output.get().logInfo( "&7 Prison Ranks have been disabled in &2plugins/Prison/modules.yml&7." ); + Prison.get().getModuleManager().getDisabledModules().add( PrisonRanks.MODULE_NAME ); + } + + + // If the sellall module is defined in modules.yml, then use that setting, otherwise + // use the sellall config setting within the config.yml file. + String sellallModuleName = PrisonSellall.MODULE_NAME.toLowerCase(); + boolean isDefined = modulesConf.contains( sellallModuleName ); + + // First check to see if the module is enabled (sellall): + if ( isDefined && modulesConf.getBoolean( sellallModuleName ) || + // if not, then check to see if sellall is enabled within config.yml: + !isDefined && getConfig().contains( "sellall" ) && getConfig().isBoolean( "sellall" ) ) { + + PrisonSellall sellallModule = new PrisonSellall( getDescription().getVersion() ); + + // Register and enable the sellall module: + Prison.get().getModuleManager().registerModule( sellallModule ); + + Prison.get().getCommandHandler().registerCommands( new SellallCommands() ); + + + isSellAllEnabled = true; + + + // If sellall is enabled, then allow it to initialize. // if (isSellAllEnabled){ - SellAllUtil.get(); + SellAllUtil.get(); // } - // Load sellAll if enabled + // Load sellAll if enabled // if (isSellAllEnabled){ - Prison.get().getCommandHandler().registerCommands( new PrisonSpigotSellAllCommands() ); + Prison.get().getCommandHandler().registerCommands( new PrisonSpigotSellAllCommands() ); // } - } - else { - Output.get().logInfo("&3Modules: &cPrison sellall module is disabled and was not Loaded. "); - Prison.get().getModuleManager().getDisabledModules().add( PrisonSellall.MODULE_NAME ); - } - + } + else { + Output.get().logInfo( "&3Modules: &cPrison sellall module is disabled and was not Loaded. " ); + Prison.get().getModuleManager().getDisabledModules().add( PrisonSellall.MODULE_NAME ); + } - - // The following linkMinesAndRanks() function must be called only after the - // Module deferred tasks are ran. + + // The following linkMinesAndRanks() function must be called only after the + // Module deferred tasks are ran. // // Try to load the mines and ranks that have the ModuleElement placeholders: // // Both the mine and ranks modules must be enabled. // if (modulesConf.getBoolean("mines") && modulesConf.getBoolean("ranks")) { // linkMinesAndRanks(); // } - - // Do not enable sellall if ranks is not loaded since it uses player ranks: - if ( isRanksEnabled ) { - - // enable under GUI: + + // Do not enable sellall if ranks is not loaded since it uses player ranks: + if ( isRanksEnabled ) { + + // 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() ); // } - - - } - // Load backpacks commands if enabled - if (isBackPacksEnabled){ - Prison.get().getCommandHandler().registerCommands( new PrisonSpigotBackpackCommands() ); - } - - // 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() ); - } - } - + } + + // Load backpacks commands if enabled + if ( isBackPacksEnabled ) { + Prison.get().getCommandHandler().registerCommands( new PrisonSpigotBackpackCommands() ); + } + + + // 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: - if (modulesConf.getBoolean("utils.enabled", true)) { - Prison.get().getModuleManager() - .registerModule(new PrisonUtilsModule(getDescription().getVersion(), modulesConf)); + + // Register prison utility commands: + if ( modulesConf.getBoolean( "utils.enabled", true ) ) { + Prison.get().getModuleManager() + .registerModule( new PrisonUtilsModule( getDescription().getVersion(), modulesConf ) ); // Prison.get().getCommandHandler().registerCommands( new PrisonSpigotMinesCommands() ); - - } else { - Output.get().logInfo("&7Modules: &cPrison Utils are disabled and were not Loaded. "); - Output.get().logInfo("&7 Prison Utils have been disabled in &2plugins/Prison/modules.yml&7."); - Prison.get().getModuleManager().getDisabledModules().add( PrisonUtilsModule.MODULE_NAME ); - } - - - } + } + else { + Output.get().logInfo( "&7Modules: &cPrison Utils are disabled and were not Loaded. " ); + Output.get().logInfo( "&7 Prison Utils have been disabled in &2plugins/Prison/modules.yml&7." ); + Prison.get().getModuleManager().getDisabledModules().add( PrisonUtilsModule.MODULE_NAME ); + } - /** - * This will initialize any process that has been setup in the modules that - * needs to be ran after all of the integrations have been fully loaded and initialized. - * - */ - private void initDeferredModules() { - - for ( Module module : Prison.get().getModuleManager().getModules() ) { - - module.deferredStartup(); - } - - - // Reload placeholders: - Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); - - - // Finally link mines and ranks if both are loaded: - linkMinesAndRanks(); - } + + // Register the '/mines debugBlockBreak' command: + Prison.get().getCommandHandler().registerCommands( new PrisonDebugBlockInspectorCommand() ); + + + } + + + /** + * This will initialize any process that has been setup in the modules that needs to be ran after all of the + * integrations have been fully loaded and initialized. + * + */ + private void initDeferredModules() { + + for ( Module module : Prison.get().getModuleManager().getModules() ) { + + module.deferredStartup(); + } + + + // Reload placeholders: + Prison.get().getPlatform().getPlaceholders().reloadPlaceholders(); + + + // Finally link mines and ranks if both are loaded: + linkMinesAndRanks(); + } - /** - * Try to link the mines and ranks that have the ModuleElement placeholders: - * Both the mine and ranks modules must be enabled to try to link them all - * together. - */ - private void linkMinesAndRanks() { + /** + * Try to link the mines and ranks that have the ModuleElement placeholders: Both the mine and ranks modules must be + * enabled to try to link them all together. + */ + private void linkMinesAndRanks() { - - if (PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() && - PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled()) { - - RankManager rm = PrisonRanks.getInstance().getRankManager(); - MineManager mm = PrisonMines.getInstance().getMineManager(); - - // go through all mines and link them to the Ranks and link that - // rank back to the mine. - // So just by linking mines, will also link all of the ranks too. - // It's important to understand the primary source is within the Mine - // since a mine can only have one rank. - rm.getRanks(); - mm.getMines(); - - int count = 0; - for (Mine mine : mm.getMines()) { + + if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() && + PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled() ) { + + RankManager rm = PrisonRanks.getInstance().getRankManager(); + MineManager mm = PrisonMines.getInstance().getMineManager(); + + // go through all mines and link them to the Ranks and link that + // rank back to the mine. + // So just by linking mines, will also link all of the ranks too. + // It's important to understand the primary source is within the Mine + // since a mine can only have one rank. + rm.getRanks(); + mm.getMines(); + + int count = 0; + for ( Mine mine : mm.getMines() ) { if ( mine.getRank() == null && mine.getRankString() != null ) { String[] rParts = mine.getRankString().split( "," ); - - if (rParts.length > 2) { + + if ( rParts.length > 2 ) { ModuleElementType meType = ModuleElementType.fromString( rParts[0] ); String rankName = rParts[1]; - - if (meType == ModuleElementType.RANK) { - Rank rank = rm.getRank(rankName); - - if (rank != null) { - mine.setRank(rank); - rank.getMines().add(mine); + + if ( meType == ModuleElementType.RANK ) { + Rank rank = rm.getRank( rankName ); + + if ( rank != null ) { + mine.setRank( rank ); + rank.getMines().add( mine ); count++; } } } } } - Output.get().logInfo("A total of %s Mines and Ranks have been linked together.", Integer.toString(count)); - } + Output.get().logInfo( "A total of %s Mines and Ranks have been linked together.", Integer.toString( count ) ); + } } private void applyDeferredIntegrationInitializations() { - for ( Integration deferredIntegration : PrisonAPI.getIntegrationManager().getDeferredIntegrations() ) { - - try { - if ( deferredIntegration.isRegistered() && deferredIntegration.hasIntegrated() ) { - - deferredIntegration.deferredInitialization(); - } - } - catch ( Exception e ) { - - - PrisonAPI.getIntegrationManager().removeIntegration( deferredIntegration ); - - Output.get().logWarn( - String.format( "Warning: An integration failed during deferred integration. " + - "Disabling the integration to protect Prison: %s %s %s[%s]", - deferredIntegration.getKeyName(), deferredIntegration.getVersion(), - (deferredIntegration.getDebugInfo() == null ? - "no debug info" : deferredIntegration.getDebugInfo()) )); - - } - } - } + for ( Integration deferredIntegration : PrisonAPI.getIntegrationManager().getDeferredIntegrations() ) { + + try { + if ( deferredIntegration.isRegistered() && deferredIntegration.hasIntegrated() ) { + + deferredIntegration.deferredInitialization(); + } + } catch ( Exception e ) { + + + PrisonAPI.getIntegrationManager().removeIntegration( deferredIntegration ); + + Output.get().logWarn( + String.format( "Warning: An integration failed during deferred integration. " + + "Disabling the integration to protect Prison: %s %s %s[%s]", + deferredIntegration.getKeyName(), deferredIntegration.getVersion(), + ( deferredIntegration.getDebugInfo() == null ? "no debug info" : deferredIntegration.getDebugInfo() ) ) ); + + } + + } + } public SpigotScheduler getScheduler() { return scheduler; } public Compatibility getCompatibility() { - return compatibility; - } + + return compatibility; + } private File getBundledFile(String name) { getDataFolder().mkdirs(); @@ -1348,39 +1064,41 @@ public YamlConfiguration loadConfig(String file) { return YamlConfiguration.loadConfiguration(getBundledFile(file)); } - public YamlConfiguration loadExternalConfig(File file) { - return YamlConfiguration.loadConfiguration( file ); - } + public YamlConfiguration loadExternalConfig( File file ) { + + return YamlConfiguration.loadConfiguration( file ); + } - public YamlConfiguration loadExternalConfig( Reader reader ) { - return YamlConfiguration.loadConfiguration( reader ); - } + public YamlConfiguration loadExternalConfig( Reader reader ) { + + return YamlConfiguration.loadConfiguration( reader ); + } - public void saveConfig(String fileName, YamlConfiguration config ) { - if ( config != null ) { - File file = getBundledFile(fileName); - try { + public void saveConfig( String fileName, YamlConfiguration config ) { + + if ( config != null ) { + File file = getBundledFile( fileName ); + try { config.save( file ); - } - catch (IOException e) { - String message = String.format( "Error saving config file: %s [%s]", - file.getAbsoluteFile(), e.getMessage() ); - - Output.get().logError( message ); + } catch ( IOException e ) { + String message = String.format( "Error saving config file: %s [%s]", + file.getAbsoluteFile(), e.getMessage() ); + + Output.get().logError( message ); } - } - } + } + } File getDataDirectory() { return dataDirectory; } - public boolean isPrisonConfig( String configId ) { + public boolean isPrisonConfig( String configId ) { - String config = SpigotPrison.getInstance().getConfig().getString( configId ); - boolean results = config != null && config.equalsIgnoreCase( "true" ); - return results; - } + String config = SpigotPrison.getInstance().getConfig().getString( configId ); + boolean results = config != null && config.equalsIgnoreCase( "true" ); + return results; + } /** * Setup hooks in to the valid prison block types. This will be only the 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 eb992ebd6..d5e3ff464 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 @@ -18,7 +18,6 @@ package tech.mcprison.prison.spigot; -import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitScheduler; import tech.mcprison.prison.Prison; @@ -40,68 +39,69 @@ public SpigotScheduler(SpigotPrison plugin) { } @Override - public int runTaskLater(Runnable run, long delay) { - return scheduler.runTaskLater(plugin, run, delay).getTaskId(); + public void cancelAll() { + scheduler.cancelTasks(plugin); } @Override - public int runTaskLaterAsync(Runnable run, long delay) { - return scheduler.runTaskLaterAsynchronously(plugin, run, delay).getTaskId(); + public void cancelTask(int taskId) { + scheduler.cancelTask(taskId); } - @Override - public int runTaskTimer(Runnable run, long delay, long interval) { - return scheduler.runTaskTimer(plugin, run, delay, interval).getTaskId(); - } + @Override + public void dispatchCommand( Player player, String command ) { + + if ( player != null && player instanceof SpigotPlayer ) { + SpigotPlayer sPlayer = (SpigotPlayer) player; + + sPlayer.dispatchCommand( command ); - @Override - public int runTaskTimerAsync(Runnable run, long delay, long interval) { - return scheduler.runTaskTimerAsynchronously(plugin, run, delay, interval).getTaskId(); - } - - @Override - public void dispatchCommand(Player player, String command) { - - if ( player != null && player instanceof SpigotPlayer ) { - SpigotPlayer sPlayer = (SpigotPlayer) player; - - sPlayer.dispatchCommand( command ); - // Bukkit.dispatchCommand( sPlayer.getWrapper(), command ); - } - } + } + } + + @Override + public boolean isPrimaryThread() { + + return this.plugin.getServer().isPrimaryThread(); + } @Override - public void performCommand(Player player, String command) { - - if ( player != null ) { - - Player p = Prison.get().getPlatform().getPlayer( player.getUUID() ).orElse( null ); - - if ( p != null && p instanceof SpigotPlayer ) { - - SpigotPlayer sPlayer = (SpigotPlayer) p; - - sPlayer.dispatchCommand( command ); - + public void performCommand( Player player, String command ) { + + if ( player != null ) { + + Player p = Prison.get().getPlatform().getPlayer( player.getUUID() ).orElse( null ); + + if ( p != null && p instanceof SpigotPlayer ) { + + SpigotPlayer sPlayer = (SpigotPlayer) p; + + sPlayer.dispatchCommand( command ); + // sPlayer.getWrapper().performCommand( command ); - } - } + } + } + } + + @Override + public int runTaskLater(Runnable run, long delay) { + return scheduler.runTaskLater(plugin, run, delay).getTaskId(); } @Override - public void cancelTask(int taskId) { - scheduler.cancelTask(taskId); + public int runTaskLaterAsync(Runnable run, long delay) { + return scheduler.runTaskLaterAsynchronously(plugin, run, delay).getTaskId(); } @Override - public void cancelAll() { - scheduler.cancelTasks(plugin); + public int runTaskTimer(Runnable run, long delay, long interval) { + return scheduler.runTaskTimer(plugin, run, delay, interval).getTaskId(); } - @Override - public boolean isPrimaryThread() { - return this.plugin.getServer().isPrimaryThread(); + @Override + public int runTaskTimerAsync(Runnable run, long delay, long interval) { + return scheduler.runTaskTimerAsynchronously(plugin, run, delay, interval).getTaskId(); } } 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 e9bb0fcd6..15129baf5 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 @@ -52,6 +52,7 @@ import tech.mcprison.prison.spigot.compat.BlockTestStats; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotWorld; +import tech.mcprison.prison.spigot.integrations.IntegrationBackpackAPI; import tech.mcprison.prison.spigot.integrations.IntegrationMinepacksPlugin; import tech.mcprison.prison.util.Location; import tech.mcprison.prison.util.Text; @@ -80,64 +81,14 @@ public static XMaterial getXMaterial( String materialName ) { return XMaterial.matchXMaterial( materialName ).orElse( null ); } -// /** -// *

    Gets the XMaterial based upon the BlockType name, and if it fails to hit -// * anything, then it falls back on to the id, of which XMaterial strips the -// * prefix of "minecraft:". -// *

    -// * -// * @param prisonBlockType -// * @return -// */ -// public static XMaterial getXMaterial( BlockType prisonBlockType ) { -// -// XMaterial xMat = SpigotCompatibility.getInstance() -// .getXMaterial( prisonBlockType ); -// -// return xMat; -// } - - public static XMaterial getXMaterial( PrisonBlock prisonBlock ) { - - XMaterial xMat = SpigotCompatibility.getInstance().getXMaterial(prisonBlock); - -// XMaterial xMat = getXMaterial( prisonBlock.getBlockName()); - - return xMat; - } - -// public static Material getMaterial( BlockType prisonBlockType ) { -// XMaterial xMat = getXMaterial( prisonBlockType ); -// -// return xMat == null ? null : xMat.parseMaterial(); -// } + public static XMaterial getXMaterial( PrisonBlock prisonBlock ) { + XMaterial xMat = SpigotCompatibility.getInstance().getXMaterial( prisonBlock ); + + return xMat; + } -// public static BlockType blockToBlockType( Block spigotBlock ) { -// BlockType results = SpigotCompatibility.getInstance() -// .getBlockType( spigotBlock ); -// -//// -//// XMaterial xMatMatch = XMaterial.matchXMaterial( material ); -//// -//// for ( BlockType blockType : BlockType.values() ) { -//// XMaterial xMat = getXMaterial( blockType ); -//// if ( xMat != null ) { -//// results = blockType; -//// break; -//// } -//// } -// -// return results; -// } - -// public static BlockType prisonBlockToBlockType( PrisonBlock prisonBlock ) { -// -// BlockType results = BlockType.getBlock( prisonBlock.getBlockName() ); -// -// return results; -// } /** *

    Returns a stack of PrisonBlock or a stack of air. @@ -178,11 +129,14 @@ public static ItemStack getItemStack( XMaterial xMaterial, int amount ) { public static SpigotItemStack getSpigotItemStackXMat( XMaterial xMaterial, int amount ) { SpigotItemStack itemStack = null; - try { - itemStack = new SpigotItemStack( getItemStack( xMaterial, amount ) ); - } - catch (PrisonItemStackNotSupportedRuntimeException e) { - // ignore + if ( xMaterial != null ) { + + try { + itemStack = new SpigotItemStack( getItemStack( xMaterial, amount ) ); + } + catch (PrisonItemStackNotSupportedRuntimeException e) { + // ignore + } } return itemStack; @@ -197,48 +151,7 @@ public static SpigotItemStack getSpigotItemStack( PrisonBlock material, int amou return iStack; } - public static void getSpigotBlock( ItemStack iStack ) { - XMaterial xmat = XMaterial.matchXMaterial( iStack ); - -// SpigotCompatibility.getInstance(). - } - - /*public static HashMap addItemToPlayerInventory( - Player player, SpigotItemStack itemStack ) { - HashMap results = new HashMap<>(); - - HashMap overflow = player.getInventory().addItem( itemStack.getBukkitStack() ); - Set keys = overflow.keySet(); - - if (SpigotPrison.getInstance().getConfig().getString("backpacks").equalsIgnoreCase("true") && - SpigotPrison.getInstance().getBackPacksConfig().getString("Options.BackPack_AutoPickup_Usable").equalsIgnoreCase("true")) { - - // Get backpack. - Inventory prisonBackpack = BackPacksUtil.get().getInventory(player); - - for (Integer key : keys){ - HashMap overflowBackPack = prisonBackpack.addItem(overflow.get(key)); - - if (!overflowBackPack.isEmpty()){ - Set keys2 = overflowBackPack.keySet(); - for (Integer key2 : keys2) { - results.put(key2, new SpigotItemStack(overflowBackPack.get(key2))); - } - } - } - // Save backpack with new items if not full. - BackPacksUtil.get().setInventory(player, prisonBackpack); - } else { - for (Integer key : keys) { - results.put(key, new SpigotItemStack(overflow.get(key))); - } - } - - return results; - }*/ - - /** * Used in AutoManagerFeatures. * @@ -255,7 +168,7 @@ public static HashMap addItemToPlayerInventory( player.updateInventory(); // Insert overflow in to Prison's backpack: - if ( BackpacksUtil.isEnabled() ) { + if ( BackpacksUtil.getInstance().isEnabled() ) { BackpacksUtil bpUtil = BackpacksUtil.get(); if (overflow.size() > 0 && @@ -294,6 +207,12 @@ public static HashMap addItemToPlayerInventory( } + // Insert overflow in to the backpack API: + if ( overflow.size() > 0 && IntegrationBackpackAPI.getInstance().isEnabled() ) { + overflow = IntegrationBackpackAPI.getInstance().addItemsBukkit( player, overflow ); + } + + // Cannot stick it anywhere else, so return the extras: for ( Integer key : overflow.keySet() ) { ItemStack iStack = overflow.get(key); @@ -311,30 +230,6 @@ public static HashMap addItemToPlayerInventory( return results; } -// public static int countItemsInPlayerInventory( -// Player player, SpigotItemStack itemStackSource, -// SpigotItemStack itemStackTarget, int quantity ) { -// int count = 0; -// -// player.getInventory(). -// -// -// -// return count ; -// } -// -// public static HashMap exchangeItemsFromPlayerInventory( -// Player player, SpigotItemStack itemStackSource, -// SpigotItemStack itemStackTarget, int quantity ) { -// HashMap overflow = new HashMap<>(); -// -// HashMap removed = new HashMap<>(); -// -// -// -// return overflow ; -// } - public static int itemStackCount(XMaterial xMat, Inventory inv ) { int count = 0; @@ -401,7 +296,7 @@ public static int itemStackRemoveAll(Player player, XMaterial xMat ) { removed += itemStackRemoveAll( xMat, player.getInventory() ); - // Insert overflow in to Prison's backpack: + // Then remove from Prison's backpack: if ( SpigotPrison.getInstance().getConfig().getString("backpacks").equalsIgnoreCase("true")) { String id = null; @@ -411,11 +306,17 @@ public static int itemStackRemoveAll(Player player, XMaterial xMat ) { } - // Insert overflow in to Minepacks backpack: + // Then remove from Minepacks backpack: if ( IntegrationMinepacksPlugin.getInstance().isEnabled() ) { removed += IntegrationMinepacksPlugin.getInstance().itemStackRemoveAll(player, xMat); } - + + + // Then remove from the backpack API: + if ( IntegrationBackpackAPI.getInstance().isEnabled() ) { + removed += IntegrationBackpackAPI.getInstance().itemStackRemoveAll(player, xMat); + } + return removed; } @@ -468,6 +369,33 @@ public static int itemStackRemoveAll( XMaterial xMat, Inventory inv ) { return count; } + + /** + *

    This function will take a given XMaterial and remove all occurrences of it + * from a player's inventory, and add the quantity removed, to the ItemStack drop + * amount. This basically moves an item from the player's inventory, to the drop + * ItemStack. + *

    + * + * @param player + * @param xMat + * @param drop + */ + public static void getAllDroppedItemTypesFromPlayerInventory( + Player player, XMaterial xMat, SpigotItemStack drop ) { + + if ( xMat != null ) { + + int inventoryCount = itemStackRemoveAll(player, xMat); + + if ( inventoryCount > 0 ) { + + int count = drop.getAmount(); + drop.setAmount( count + inventoryCount ); + } + } + } + /** *

    This function is used to convert a map to a String. It has been created to provide a * String conversion for ItemStack.serialize() functions. @@ -522,7 +450,8 @@ else if ( obj instanceof Map ) { * @param ratio */ public static void itemStackReplaceItems( List stacks, - XMaterial source, XMaterial target, int ratio ) { + XMaterial source, XMaterial target, int ratio, + StringBuilder debugInfo ) { // Removes all of the specified source types from all inventories: int sourceRemoved = itemStackRemoveAll( source, stacks ); @@ -541,6 +470,9 @@ public static void itemStackReplaceItems( List stacks, itemStackAddAll( stacks, target, targetCount ); } + debugInfo.append( "&d[&b" ).append( source.name() ).append( "&c:&b" ).append( sourceRemoved ) + .append( " &7->&b " ) + .append( target.name() ).append( "&c:&b" ).append( targetCount ).append( "&d]&3" ); } @@ -641,10 +573,21 @@ public static HashMap playerInventoryRemoveItem( Player play public static List getAllPlatformBlockTypes() { List blockTypes = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + for ( XMaterial xMat : XMaterial.values() ) { if ( xMat.isSupported() ) { - ItemStack itemStack = xMat.parseItem(); + ItemStack itemStack = null; + + boolean itemStackFailed = false; + + try { + itemStack = xMat.parseItem(); + } + catch (Exception e) { + itemStackFailed = true; + } if ( xMat.name().toLowerCase().contains( "_wood" ) ) { @@ -673,30 +616,64 @@ public static List getAllPlatformBlockTypes() { } } -// Material mat = xMat.parseMaterial(); -// if ( mat != null ) { -// if ( mat.isBlock() ) { -// -// PrisonBlock block = new PrisonBlock( xMat.name().toLowerCase() ); -// -// block.setValid( true ); -// block.setBlock( mat.isBlock() ); -// -// blockTypes.add( block ); -// } -// } else { - Output.get().logWarn( "### SpigotUtil.testAllPrisonBlockTypes: " + - "Possible XMaterial FAIL: XMaterial " + xMat.name() + - " is supported for this version, but the XMaterial cannot " + - "be mapped to an actual Material."); + + // NOTE: Wall hangings, water, and potted plants can be placed as blocks, but cannot + // created as ItemStacks: + if ( canItemStackMaterial( xMat ) ) { + + sb.append( xMat.name() ).append( " " ); + } + + +// Output.get().logInfo( +// "Notice: invalid XMaterial type encountered when trying to use 'parseItem()'. %s " + +// "Contact prison support. XSeries may need to be updated to support " + +// "the current version of spigot. ", +// xMat.name() +// ); + } } } + if ( sb.length() > 0 ) { + + Output.get().logInfo( "### SpigotUtil.testAllPrisonBlockTypes: " + + "The following XMaterial items could not generate an ItemStack. " + + "This is not an error. This list could be beneficial if there are any " + + "issues with XMaterial and new versions of Spigot/Paper. " + + "Igoring '*water*', '*wall*', and '*potted*' [%s] ", + sb.toString() ); + } + return blockTypes; } + + public static boolean canItemStackMaterial( Material max ) { + return canItemStackMaterial( max.name() ); + } + + public static boolean canItemStackMaterial( XMaterial max ) { + return canItemStackMaterial( max.name() ); + } + + public static boolean canItemStackMaterial( String name ) { + boolean results = true; + + name = name.toLowerCase(); + + if ( name.contains( "wall") || name.contains( "potted" ) || name.contains( "water" ) || + name.contains("") ) { + + results = false; + } + + return results; + } + + public static List getAllCustomBlockTypes() { List blockTypes = new ArrayList<>(); @@ -743,28 +720,6 @@ public static PrisonBlock getPrisonBlock( String blockName, String displayName ) PrisonBlock results = new PrisonBlock( blockName, displayName ); results.setValid( false ); -// BlockType bTypeObsolete = null; -// -// XMaterial xMat = getXMaterial( blockName ); -// -// if ( xMat == null ) { -// // Try to get the material through the old prison blocks: -// bTypeObsolete = BlockType.getBlock( blockName ); -// -// xMat = getXMaterial( bTypeObsolete ); -// } -// -// if ( xMat != null ) { -// results = new PrisonBlock( xMat.name() ); -// -// if ( bTypeObsolete != null ) { -// results.setLegacyBlock( true ); -// } -// } -// else { -// results = new PrisonBlock( blockName ); -// results.setValid( false ); -// } return results; } @@ -798,32 +753,6 @@ public static void testAllPrisonBlockTypes() { int supportedBlockCountPrison = 0; int supportedBlockCountXMaterial = 0; -// for ( BlockType block : BlockType.values() ) { -// -// if ( block.isBlock() ) { -// XMaterial xMat = getXMaterial( block ); -// -// if ( xMat == null ) { -// if ( sbNoMap.length() > 0 ) { -// sbNoMap.append( " " ); -// } -// -// Material mat = getMaterial( block ); -// -// String bName = block.name() + (mat == null ? "" : "(" + mat.name() + ")"); -// sbNoMap.append( bName ); -// } -// else if ( !xMat.isSupported() ) { -// if ( sbNotSupported.length() > 0 ) { -// sbNotSupported.append( " " ); -// } -// sbNotSupported.append( block.name() ); -// } -// else { -// supportedBlockCountPrison++; -// } -// } -// } // Validate which XMaterial for ( XMaterial xMat : XMaterial.values() ) { @@ -847,8 +776,20 @@ public static void testAllPrisonBlockTypes() { for ( Material spigotMaterial : Material.values() ) { + XMaterial xMat = null; + + try { + xMat = XMaterial.matchXMaterial( spigotMaterial ); + } + catch (Exception e) { + // Ignore since this version of spigot/paper does not support this block type + // within XMaterial. + } + if ( spigotMaterial.isBlock() && - XMaterial.matchXMaterial( spigotMaterial ) == null + + xMat == null +// XMaterial.matchXMaterial( spigotMaterial ) == null // BlockType.getBlock( spigotMaterial.name() ) == null ) { @@ -910,168 +851,146 @@ private static void logTestBlocks( StringBuilder sb, String message ) { Output.get().logWarn( message + sb.substring( start )); } -// @SuppressWarnings( "deprecation" ) -// public static BlockType materialToBlockType(Material material) { -// return BlockType.getBlock(material.getId()); // To be safe, we use legacy ID -// } - -// @SuppressWarnings( "deprecation" ) -// public static MaterialData blockTypeToMaterial(BlockType type) { -// Material material = Material.getMaterial(type.getLegacyId()); -// if ( material == null ) { -// material = Material.STONE; -// } -// return new MaterialData(material, (byte) type.getData()); // To be safe, we use legacy ID -//// Material material = Material.getMaterial(type.getLegacyId()); -//// if ( material == null ) { -//// material = Material.STONE; -//// } -//// -//// return new MaterialData(material, (byte) type.getData()); // To be safe, we use legacy ID -//// -//// -//// -//// MaterialData results = null; -//// -//// if ( type.getMaterialVersion() == MaterialVersion.v1_13 ) { -//// Output.get().logInfo( String.format( "SpigotUtil.blockTypeToMaterial: v1_13 : %s ", -//// type.getId()) ); -//// -//// // Material type for 1.13 and higher have a legacyID == 0: -//// Material material = null; -//// material = getMaterial( type.getId() ); -//// -//// if ( material == null ) { -//// String materialName = type.getId().toUpperCase(); -//// material = getMaterial( materialName ); -//// -//// Output.get().logInfo( String.format( "SpigotUtil.blockTypeToMaterial: was null : %s -> %s [%s]", -//// type.name(), materialName, (material == null ? "null" : "NOT null")) ); -//// -////// if ( material == null ) { -////// material = Material. -////// Output.get().logInfo( String.format( "SpigotUtil.blockTypeToMaterial: was null : %s -> %s [%s]", -////// type.name(), materialName, (material == null ? "null" : "NOT null")) ); -////// -////// } -//// } -//// else { -//// Output.get().logInfo( String.format( "SpigotUtil.blockTypeToMaterial: %s [%s]", -//// type.name(), (material == null ? "null" : "NOT null")) ); -//// -//// } -//// -//// if ( material == null ) { -//// material = Material.STONE; -//// } -//// results = new MaterialData(material); -//// } -//// else { -////// Output.get().logInfo( String.format( "SpigotUtil.blockTypeToMaterial: v1_8 : %s %s data=%s", -////// type.getId(), Integer.toString( type.getLegacyId()), -////// Integer.toString( type.getData())) ); -////// // type.getMaterialVersion() == MaterialVersion.v1_8 -//// -//// // Material types for 1.12 and lower: -//// Material material = Material.getMaterial(type.getLegacyId()); -//// if ( material == null ) { -//// material = Material.STONE; -//// } -//// -//// results = new MaterialData(material, (byte) type.getData()); // To be safe, we use legacy ID -//// -//// } -//// return results; -// } - -// private static Material getMaterial( String materialName ) { -// Material results = null; -// -// try { -// results = Material.matchMaterial( materialName ); -// } -// catch ( Exception e ) { -// // Do nothing for now... -// // Will try other combination later and will report failure if needed; -// Output.get().logInfo( "&cSpigotUtil.getMaterial() Failure : &7" + e.getMessage() ); -// } -// -// return results; -// } - /* - * Location - */ - public static Location bukkitLocationToPrison(org.bukkit.Location bukkitLocation) { - org.bukkit.util.Vector v = bukkitLocation.getDirection(); - Vector direction = new Vector( v.getX(), v.getY(), v.getZ() ); - - return new Location(new SpigotWorld(bukkitLocation.getWorld()), bukkitLocation.getX(), - bukkitLocation.getY(), bukkitLocation.getZ(), bukkitLocation.getPitch(), - bukkitLocation.getYaw(), - direction ); - } + /* + * Location + */ + + public static Location bukkitLocationToPrison( org.bukkit.Location bukkitLocation ) { + + Location loc = new Location( new SpigotWorld( bukkitLocation.getWorld() ), bukkitLocation.getX(), + bukkitLocation.getY(), bukkitLocation.getZ(), bukkitLocation.getPitch(), + bukkitLocation.getYaw() ); + + double x = bukkitLocation.getDirection().getX(); + double y = bukkitLocation.getDirection().getY(); + double z = bukkitLocation.getDirection().getZ(); + + Vector direction = new Vector( x, y, z ); + + loc.setDirection( direction ); + + return loc; + +// org.bukkit.util.Vector v = bukkitLocation.getDirection(); +// Vector direction = new Vector( v.getX(), v.getY(), v.getZ() ); +// +// return new Location(new SpigotWorld(bukkitLocation.getWorld()), bukkitLocation.getX(), +// bukkitLocation.getY(), bukkitLocation.getZ(), bukkitLocation.getPitch(), +// bukkitLocation.getYaw(), +// direction ); + } public static org.bukkit.Location prisonLocationToBukkit(Location prisonLocation) { - return new org.bukkit.Location(Bukkit.getWorld(prisonLocation.getWorld().getName()), - prisonLocation.getX(), prisonLocation.getY(), prisonLocation.getZ(), - prisonLocation.getYaw(), prisonLocation.getPitch()); + org.bukkit.Location loc = new org.bukkit.Location( + Bukkit.getWorld(prisonLocation.getWorld().getName()), + prisonLocation.getX(), prisonLocation.getY(), prisonLocation.getZ(), + prisonLocation.getYaw(), prisonLocation.getPitch() ); + +// Vector v = prisonLocation.getDirection(); +// org.bukkit.util.Vector vec = new org.bukkit.util.Vector( v.getX(), v.getY(), v.getZ() ); +// loc.setDirection( vec ); + + return loc; } - /* - * ItemStack - */ + /* + * ItemStack + */ - public static SpigotItemStack bukkitItemStackToPrison( ItemStack bukkitStack) { -; SpigotItemStack results = null; - - if ( bukkitStack != null ) { - try { + public static SpigotItemStack bukkitItemStackToPrison( ItemStack bukkitStack ) { + + SpigotItemStack results = null; + + if ( bukkitStack != null ) { + try { results = new SpigotItemStack( bukkitStack ); - } - catch (PrisonItemStackNotSupportedRuntimeException e) { + } catch ( PrisonItemStackNotSupportedRuntimeException e ) { // ignore... } - } - - return results; - } + } - public static ItemStack prisonItemStackToBukkit( - tech.mcprison.prison.internal.ItemStack prisonStack) { - int amount = prisonStack.getAmount(); - - ItemStack bukkitStack = getItemStack( prisonStack.getMaterial(), amount ); - -// MaterialData materialData = blockTypeToMaterial(prisonStack.getMaterial()); -// -// ItemStack bukkitStack = new ItemStack(materialData.getItemType(), amount); -// bukkitStack.setData(materialData); - - ItemMeta meta; - if (bukkitStack.getItemMeta() == null || !bukkitStack.hasItemMeta()) { - meta = Bukkit.getItemFactory().getItemMeta(bukkitStack.getType()); - } else { - meta = bukkitStack.getItemMeta(); - } - - if (meta != null) { - if (prisonStack.getDisplayName() != null) { - meta.setDisplayName(Text.translateAmpColorCodes(prisonStack.getDisplayName())); - } - if (prisonStack.getLore() != null) { - List colored = new ArrayList<>(); - for (String uncolor : prisonStack.getLore()) { - colored.add(Text.translateAmpColorCodes(uncolor)); - } - meta.setLore(colored); - } - bukkitStack.setItemMeta(meta); - } + return results; + } - return bukkitStack; - } + /** + *

    + * This function will try to use the 'prisonStack' parameter, and then construct an org.bukkit.inventory.ItemStack + * object and return it. If the provided prisonStack already contains a bukkit ItemStack, then it will be returned from + * this function, otherwise it will have to construct one. + *

    + * + *

    + * If it has to construct one, it will add the lore and custom name. It may have to also handle enchantments too. Not + * sure right now. + *

    + * + *

    + * The idea is that hopefully the prisonStack will always have an included bukkit ItemStack so everything will + * faithfully copy over. + *

    + * + * @param prisonStack + * @return + */ + public static ItemStack prisonItemStackToBukkit( + tech.mcprison.prison.internal.ItemStack prisonStack ) { + + ItemStack bukkitStack = null; + + int amount = prisonStack.getAmount(); + + if ( prisonStack instanceof SpigotItemStack ) { + + SpigotItemStack sItemStack = (SpigotItemStack) prisonStack; + + if ( sItemStack.getBukkitStack() != null ) { + bukkitStack = sItemStack.getBukkitStack(); + } + } + + + if ( bukkitStack == null ) { + + bukkitStack = getItemStack( prisonStack.getMaterial(), amount ); + + ItemMeta meta; + if ( bukkitStack.getItemMeta() == null || !bukkitStack.hasItemMeta() ) { + meta = Bukkit.getItemFactory().getItemMeta( bukkitStack.getType() ); + } + else { + meta = bukkitStack.getItemMeta(); + } + + if ( meta != null ) { + if ( prisonStack.getDisplayName() != null ) { + meta.setDisplayName( Text.translateAmpColorCodes( prisonStack.getDisplayName() ) ); + } + if ( prisonStack.getLore() != null ) { + List colored = new ArrayList<>(); + for ( String uncolor : prisonStack.getLore() ) { + colored.add( Text.translateAmpColorCodes( uncolor ) ); + } + meta.setLore( colored ); + } + bukkitStack.setItemMeta( meta ); + } + + // Need to copy enchantments? + + // Need to copy lore: + // No, this does not make sense... if prisonStack has NBT data, then + // it would also have a getBukkitStack() entry, so this part of the + // code would never be reached. So if there is no bukkitStack in the + // prisonStack, then there would be no NBT data either. +// PrisonNBTUtil.copyCustomNBT(bukkitStack, bukkitStack) + } + + return bukkitStack; + } + + /** @@ -1095,17 +1014,10 @@ public static List getDrops(SpigotBlock block, SpigotItemStack ret.add( SpigotUtil.bukkitItemStackToPrison(drop) ); } - // block.getWrapper().getDrops( tool.getBukkitStack() ) - // .forEach(itemStack -> ret.add(SpigotUtil.bukkitItemStackToPrison(itemStack))); - return ret; } -// public static void clearDrops(SpigotBlock block) { -// -// block.getWrapper().getDrops().clear();; -// } /* * InventoryType @@ -1135,26 +1047,20 @@ public static InventoryView.Property prisonPropertyToBukkit(Viewable.Property pr } - /** - *

    Vault economy requires the parameter of bukkit's OfflinePlayer. - * That was never exposed for good reasons, and do not want to use - * bukkit/spigot specific code within that integration. So, this is - * where this code will live since it is a Spigot untility. - *

    - * - * @param uuid - * @return OfflinePlayer - */ - public static OfflinePlayer getBukkitOfflinePlayer( UUID uuid ) { - OfflinePlayer results = null; - - for ( OfflinePlayer offP : Bukkit.getOfflinePlayers() ) { - if ( uuid != null && offP.getUniqueId().equals(uuid) ) { - results = offP; - break; - } - } - - return results; - } + /** + *

    + * Vault economy requires the parameter of bukkit's OfflinePlayer. That was never exposed for good reasons, and do not + * want to use bukkit/spigot specific code within that integration. So, this is where this code will live since it is a + * Spigot untility. + *

    + * + * @param uuid + * @return OfflinePlayer + */ + public static OfflinePlayer getBukkitOfflinePlayer( UUID uuid ) { + + OfflinePlayer results = Bukkit.getOfflinePlayer( uuid ); + + return results; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/Updater.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/Updater.java index d9d60d5ee..1b26285f4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/Updater.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/Updater.java @@ -1,784 +1,8 @@ package tech.mcprison.prison.spigot; -///** -// * Check for updates on BukkitDev for a given plugin, and download the updates if needed. -// *

    -// * VERY, VERY IMPORTANT: Because there are no standards for adding auto-update toggles in your plugin's config, this system provides NO CHECK WITH YOUR CONFIG to make sure the user has allowed auto-updating. -// *
    -// * It is a BUKKIT POLICY that you include a boolean value in your config that prevents the auto-updater from running AT ALL. -// *
    -// * If you fail to include this option in your config, your plugin will be REJECTED when you attempt to submit it to dev.bukkit.org. -// *

    -// * An example of a good configuration option would be something similar to 'auto-update: true' - if this value is set to false you may NOT run the auto-updater. -// *
    -// * If you are unsure about these rules, please read the plugin submission guidelines: http://goo.gl/8iU5l -// * -// * @author Gravity -// * @version 2.4 -// */ +// Since this class was disabled a long time ago, the commented out code was +// removed since it was no longer being used. See github history for former code. public class Updater { -// /* Constants */ -// -// // Remote file's title -// private static final String TITLE_VALUE = "name"; -// // Remote file's download link -// private static final String LINK_VALUE = "downloadUrl"; -// // Remote file's release type -// private static final String TYPE_VALUE = "releaseType"; -// // Remote file's build version -// private static final String VERSION_VALUE = "gameVersion"; -// // Path to GET -// private static final String QUERY = "/servermods/files?projectIds="; -// // Slugs will be appended to this to get to the project's RSS feed -// private static final String HOST = "https://api.curseforge.com"; -// // User-agent when querying Curse -// private static final String USER_AGENT = "Updater (by Gravity)"; -// // Used for locating version numbers in file names -// private static final String DELIMETER = "^v|[\\s_-]v"; -// // If the version number contains one of these, don't update. -// private static final String[] NO_UPDATE_TAG = {"-DEV", "-PRE", "SNAPSHOT"}; -// // Used for downloading files -// private static final int BYTE_SIZE = 1024; -// // Config key for api key -// private static final String API_KEY_CONFIG_KEY = "api-key"; -// // Config key for disabling Updater -// private static final String DISABLE_CONFIG_KEY = "disable"; -// // Default api key value in config -// private static final String API_KEY_DEFAULT = "PUT_API_KEY_HERE"; -// // Default disable value in config -// private static final boolean DISABLE_DEFAULT = false; -// -// /* User-provided variables */ -// -// // Plugin running Updater -// private final Plugin plugin; -// // Type of update check to run -// private final UpdateType type; -// // Whether to announce file downloads -// private final boolean announce; -// // The plugin file (jar) -// private final File file; -// // The folder that downloads will be placed in -// private final File updateFolder; -// // The provided callback (if any) -// private final UpdateCallback callback; -// // Project's Curse ID -// private int id = -1; -// // BukkitDev ServerMods API key -// private String apiKey = null; -// -// /* Collected from Curse API */ -// -// private String versionName; -// private String versionLink; -// private String versionType; -// private String versionGameVersion; -// -// /* Update process variables */ -// -// // Connection to RSS -// private URL url; -// // Updater thread -// private Thread thread; -// // Used for determining the outcome of the update process -// private Updater.UpdateResult result = Updater.UpdateResult.SUCCESS; -// -// -// /** -// * Gives the developer the result of the update process. Can be obtained by called {@link #getResult()} -// */ -// public enum UpdateResult { -// /** -// * The updater found an update, and has readied it to be loaded the next time the server restarts/reloads. -// */ -// SUCCESS, /** -// * The updater did not find an update, and nothing was downloaded. -// */ -// NO_UPDATE, /** -// * The server administrator has disabled the updating system. -// */ -// DISABLED, /** -// * The updater found an update, but was unable to download it. -// */ -// FAIL_DOWNLOAD, /** -// * For some reason, the updater was unable to contact dev.bukkit.org to download the file. -// */ -// FAIL_DBO, /** -// * When running the version check, the file on DBO did not contain a recognizable version. -// */ -// FAIL_NOVERSION, /** -// * The id provided by the plugin running the updater was invalid and doesn't exist on DBO. -// */ -// FAIL_BADID, /** -// * The server administrator has improperly configured their API key in the configuration. -// */ -// FAIL_APIKEY, /** -// * The updater found an update, but because of the UpdateType being set to NO_DOWNLOAD, it wasn't downloaded. -// */ -// UPDATE_AVAILABLE -// } -// -// -// /** -// * Allows the developer to specify the type of update that will be run. -// */ -// public enum UpdateType { -// /** -// * Run a version check, and then if the file is out of date, download the newest version. -// */ -// DEFAULT, /** -// * Don't run a version check, just find the latest update and download it. -// */ -// NO_VERSION_CHECK, /** -// * Get information about the version and the download size, but don't actually download anything. -// */ -// NO_DOWNLOAD -// } -// -// -// /** -// * Represents the various release types of a file on BukkitDev. -// */ -// public enum ReleaseType { -// /** -// * An "alpha" file. -// */ -// ALPHA, /** -// * A "beta" file. -// */ -// BETA, /** -// * A "release" file. -// */ -// RELEASE -// } -// -// /** -// * Initialize the updater. -// * -// * @param plugin The plugin that is checking for an update. -// * @param id The dev.bukkit.org id of the project. -// * @param file The file that the plugin is running from, get this by doing this.getFile() from within your main class. -// * @param type Specify the type of update this will be. See {@link UpdateType} -// * @param announce True if the program should announce the progress of new updates in console. -// */ -// public Updater(Plugin plugin, int id, File file, UpdateType type, boolean announce) { -// this(plugin, id, file, type, null, announce); -// } -// -// /** -// * Initialize the updater with the provided callback. -// * -// * @param plugin The plugin that is checking for an update. -// * @param id The dev.bukkit.org id of the project. -// * @param file The file that the plugin is running from, get this by doing this.getFile() from within your main class. -// * @param type Specify the type of update this will be. See {@link UpdateType} -// * @param callback The callback instance to notify when the Updater has finished -// */ -// public Updater(Plugin plugin, int id, File file, UpdateType type, UpdateCallback callback) { -// this(plugin, id, file, type, callback, false); -// } -// -// /** -// * Initialize the updater with the provided callback. -// * -// * @param plugin The plugin that is checking for an update. -// * @param id The dev.bukkit.org id of the project. -// * @param file The file that the plugin is running from, get this by doing this.getFile() from within your main class. -// * @param type Specify the type of update this will be. See {@link UpdateType} -// * @param callback The callback instance to notify when the Updater has finished -// * @param announce True if the program should announce the progress of new updates in console. -// */ -// public Updater(Plugin plugin, int id, File file, UpdateType type, UpdateCallback callback, -// boolean announce) { -// this.plugin = plugin; -// this.type = type; -// this.announce = announce; -// this.file = file; -// this.id = id; -// this.updateFolder = this.plugin.getServer().getUpdateFolderFile(); -// this.callback = callback; -// -// final File pluginFile = this.plugin.getDataFolder().getParentFile(); -// final File updaterFile = new File(pluginFile, "Updater"); -// final File updaterConfigFile = new File(updaterFile, "config.yml"); -// -// YamlConfiguration config = new YamlConfiguration(); -// config.options().header( -// "This configuration file affects all plugins using the Updater system (version 2+ - http://forums.bukkit.org/threads/96681/ )" -// + '\n' -// + "If you wish to use your API key, read http://wiki.bukkit.org/ServerMods_API and place it below." -// + '\n' -// + "Some updating systems will not adhere to the disabled value, but these may be turned off in their plugin's configuration."); -// config.addDefault(API_KEY_CONFIG_KEY, API_KEY_DEFAULT); -// config.addDefault(DISABLE_CONFIG_KEY, DISABLE_DEFAULT); -// -// if (!updaterFile.exists()) { -// this.fileIOOrError(updaterFile, updaterFile.mkdir(), true); -// } -// -// boolean createFile = !updaterConfigFile.exists(); -// try { -// if (createFile) { -// this.fileIOOrError(updaterConfigFile, updaterConfigFile.createNewFile(), true); -// config.options().copyDefaults(true); -// config.save(updaterConfigFile); -// } else { -// config.load(updaterConfigFile); -// } -// } catch (final Exception e) { -// final String message; -// if (createFile) { -// message = "The updater could not create configuration at " + updaterFile -// .getAbsolutePath(); -// } else { -// message = -// "The updater could not load configuration at " + updaterFile.getAbsolutePath(); -// } -// this.plugin.getLogger().log(Level.SEVERE, message, e); -// } -// -// if (config.getBoolean(DISABLE_CONFIG_KEY)) { -// this.result = UpdateResult.DISABLED; -// return; -// } -// -// String key = config.getString(API_KEY_CONFIG_KEY); -// if (API_KEY_DEFAULT.equalsIgnoreCase(key) || "".equals(key)) { -// key = null; -// } -// -// this.apiKey = key; -// -// try { -// this.url = new URL(Updater.HOST + Updater.QUERY + this.id); -// } catch (final MalformedURLException e) { -// this.plugin.getLogger().log(Level.SEVERE, -// "The project ID provided for updating, " + this.id + " is invalid.", e); -// this.result = UpdateResult.FAIL_BADID; -// } -// -// if (this.result != UpdateResult.FAIL_BADID) { -// this.thread = new Thread(new UpdateRunnable()); -// this.thread.start(); -// } else { -// runUpdater(); -// } -// } -// -// /** -// * Get the result of the update process. -// * -// * @return result of the update process. -// * @see UpdateResult -// */ -// public Updater.UpdateResult getResult() { -// this.waitForThread(); -// return this.result; -// } -// -// /** -// * Get the latest version's release type. -// * -// * @return latest version's release type. -// * @see ReleaseType -// */ -// public ReleaseType getLatestType() { -// this.waitForThread(); -// if (this.versionType != null) { -// for (ReleaseType type : ReleaseType.values()) { -// if (this.versionType.equalsIgnoreCase(type.name())) { -// return type; -// } -// } -// } -// return null; -// } -// -// /** -// * Get the latest version's game version (such as "CB 1.2.5-R1.0"). -// * -// * @return latest version's game version. -// */ -// public String getLatestGameVersion() { -// this.waitForThread(); -// return this.versionGameVersion; -// } -// -// /** -// * Get the latest version's name (such as "Project v1.0"). -// * -// * @return latest version's name. -// */ -// public String getLatestName() { -// this.waitForThread(); -// return this.versionName; -// } -// -// /** -// * Get the latest version's direct file link. -// * -// * @return latest version's file link. -// */ -// public String getLatestFileLink() { -// this.waitForThread(); -// return this.versionLink; -// } -// -// /** -// * As the result of Updater output depends on the thread's completion, it is necessary to wait for the thread to finish -// * before allowing anyone to check the result. -// */ -// private void waitForThread() { -// if ((this.thread != null) && this.thread.isAlive()) { -// try { -// this.thread.join(); -// } catch (final InterruptedException e) { -// this.plugin.getLogger().log(Level.SEVERE, null, e); -// } -// } -// } -// -// /** -// * Save an update from dev.bukkit.org into the server's update folder. -// * -// * @param file the name of the file to save it as. -// */ -// private void saveFile(String file) { -// final File folder = this.updateFolder; -// -// deleteOldFiles(); -// if (!folder.exists()) { -// this.fileIOOrError(folder, folder.mkdir(), true); -// } -// downloadFile(); -// -// // Check to see if it's a zip file, if it is, unzip it. -// final File dFile = new File(folder.getAbsolutePath(), file); -// if (dFile.getName().endsWith(".zip")) { -// // Unzip -// this.unzip(dFile.getAbsolutePath()); -// } -// if (this.announce) { -// this.plugin.getLogger().info("Finished updating."); -// } -// } -// -// /** -// * Download a file and save it to the specified folder. -// */ -// private void downloadFile() { -// BufferedInputStream in = null; -// FileOutputStream fout = null; -// try { -// URL fileUrl = followRedirects(this.versionLink); -// final int fileLength = fileUrl.openConnection().getContentLength(); -// in = new BufferedInputStream(fileUrl.openStream()); -// fout = new FileOutputStream(new File(this.updateFolder, file.getName())); -// -// final byte[] data = new byte[Updater.BYTE_SIZE]; -// int count; -// if (this.announce) { -// this.plugin.getLogger().info("About to download a new update: " + this.versionName); -// } -// long downloaded = 0; -// while ((count = in.read(data, 0, Updater.BYTE_SIZE)) != -1) { -// downloaded += count; -// fout.write(data, 0, count); -// final int percent = (int) ((downloaded * 100) / fileLength); -// if (this.announce && ((percent % 10) == 0)) { -// this.plugin.getLogger() -// .info("Downloading update: " + percent + "% of " + fileLength + " bytes."); -// } -// } -// } catch (Exception ex) { -// this.plugin.getLogger().log(Level.WARNING, -// "The auto-updater tried to download a new update, but was unsuccessful.", ex); -// this.result = Updater.UpdateResult.FAIL_DOWNLOAD; -// } finally { -// try { -// if (in != null) { -// in.close(); -// } -// } catch (final IOException ex) { -// this.plugin.getLogger().log(Level.SEVERE, null, ex); -// } -// try { -// if (fout != null) { -// fout.close(); -// } -// } catch (final IOException ex) { -// this.plugin.getLogger().log(Level.SEVERE, null, ex); -// } -// } -// } -// -// private URL followRedirects(String location) throws IOException { -// URL resourceUrl, base, next; -// HttpURLConnection conn; -// String redLoc; -// while (true) { -// resourceUrl = new URL(location); -// conn = (HttpURLConnection) resourceUrl.openConnection(); -// -// conn.setConnectTimeout(15000); -// conn.setReadTimeout(15000); -// conn.setInstanceFollowRedirects(false); -// conn.setRequestProperty("User-Agent", "Mozilla/5.0..."); -// -// switch (conn.getResponseCode()) { -// case HttpURLConnection.HTTP_MOVED_PERM: -// case HttpURLConnection.HTTP_MOVED_TEMP: -// redLoc = conn.getHeaderField("Location"); -// base = new URL(location); -// next = new URL(base, redLoc); // Deal with relative URLs -// location = next.toExternalForm(); -// continue; -// } -// break; -// } -// return conn.getURL(); -// } -// -// /** -// * Remove possibly leftover files from the update folder. -// */ -// private void deleteOldFiles() { -// //Just a quick check to make sure we didn't leave any files from last time... -// File[] list = listFilesOrError(this.updateFolder); -// for (final File xFile : list) { -// if (xFile.getName().endsWith(".zip")) { -// this.fileIOOrError(xFile, xFile.mkdir(), true); -// } -// } -// } -// -// /** -// * Part of Zip-File-Extractor, modified by Gravity for use with Updater. -// * -// * @param file the location of the file to extract. -// */ -// private void unzip(String file) { -// final File fSourceZip = new File(file); -// try { -// final String zipPath = file.substring(0, file.length() - 4); -// ZipFile zipFile = new ZipFile(fSourceZip); -// Enumeration e = zipFile.entries(); -// while (e.hasMoreElements()) { -// ZipEntry entry = e.nextElement(); -// File destinationFilePath = new File(zipPath, entry.getName());. - // The following "if" has been provided by Jonathan Leitschuh and - // addresses a zip-slip-vulnerability exploit with zip files. This exploit can take over - // a server. -// if (!destinationFilePath.toPath().normalize().startsWith(zipPath)) { -// throw new RuntimeException("Bad zip entry"); -// } -// this.fileIOOrError(destinationFilePath.getParentFile(), -// destinationFilePath.getParentFile().mkdirs(), true); -// if (!entry.isDirectory()) { -// final BufferedInputStream bis = -// new BufferedInputStream(zipFile.getInputStream(entry)); -// int b; -// final byte[] buffer = new byte[Updater.BYTE_SIZE]; -// final FileOutputStream fos = new FileOutputStream(destinationFilePath); -// final BufferedOutputStream bos = -// new BufferedOutputStream(fos, Updater.BYTE_SIZE); -// while ((b = bis.read(buffer, 0, Updater.BYTE_SIZE)) != -1) { -// bos.write(buffer, 0, b); -// } -// bos.flush(); -// bos.close(); -// bis.close(); -// final String name = destinationFilePath.getName(); -// if (name.endsWith(".jar") && this.pluginExists(name)) { -// File output = new File(this.updateFolder, name); -// this.fileIOOrError(output, destinationFilePath.renameTo(output), true); -// } -// } -// } -// zipFile.close(); -// -// // Move any plugin data folders that were included to the right place, Bukkit won't do this for us. -// moveNewZipFiles(zipPath); -// -// } catch (final IOException e) { -// this.plugin.getLogger().log(Level.SEVERE, -// "The auto-updater tried to unzip a new update file, but was unsuccessful.", e); -// this.result = Updater.UpdateResult.FAIL_DOWNLOAD; -// } finally { -// this.fileIOOrError(fSourceZip, fSourceZip.delete(), false); -// } -// } -// -// /** -// * Find any new files extracted from an update into the plugin's data directory. -// * -// * @param zipPath path of extracted files. -// */ -// private void moveNewZipFiles(String zipPath) { -// File[] list = listFilesOrError(new File(zipPath)); -// for (final File dFile : list) { -// if (dFile.isDirectory() && this.pluginExists(dFile.getName())) { -// // Current dir -// final File oFile = -// new File(this.plugin.getDataFolder().getParent(), dFile.getName()); -// // List of existing files in the new dir -// final File[] dList = listFilesOrError(dFile); -// // List of existing files in the current dir -// final File[] oList = listFilesOrError(oFile); -// for (File cFile : dList) { -// // Loop through all the files in the new dir -// boolean found = false; -// for (final File xFile : oList) { -// // Loop through all the contents in the current dir to see if it exists -// if (xFile.getName().equals(cFile.getName())) { -// found = true; -// break; -// } -// } -// if (!found) { -// // Move the new file into the current dir -// File output = new File(oFile, cFile.getName()); -// this.fileIOOrError(output, cFile.renameTo(output), true); -// } else { -// // This file already exists, so we don't need it anymore. -// this.fileIOOrError(cFile, cFile.delete(), false); -// } -// } -// } -// this.fileIOOrError(dFile, dFile.delete(), false); -// } -// File zip = new File(zipPath); -// this.fileIOOrError(zip, zip.delete(), false); -// } -// -// /** -// * Check if the name of a jar is one of the plugins currently installed, used for extracting the correct files out of a zip. -// * -// * @param name a name to check for inside the plugins folder. -// * @return true if a file inside the plugins folder is named this. -// */ -// private boolean pluginExists(String name) { -// File[] plugins = listFilesOrError(new File("plugins")); -// for (final File file : plugins) { -// if (file.getName().equals(name)) { -// return true; -// } -// } -// return false; -// } -// -// /** -// * Check to see if the program should continue by evaluating whether the plugin is already updated, or shouldn't be updated. -// * -// * @return true if the version was located and is not the same as the remote's newest. -// */ -// private boolean versionCheck() { -// final String title = this.versionName; -// if (this.type != UpdateType.NO_VERSION_CHECK) { -// final String localVersion = this.plugin.getDescription().getVersion(); -// if (title.split(DELIMETER).length >= 2) { -// // Get the newest file's version number -// final String remoteVersion = -// title.split(DELIMETER)[title.split(DELIMETER).length - 1].split(" ")[0]; -// -// if (this.hasTag(localVersion) || !this.shouldUpdate(localVersion, remoteVersion)) { -// // We already have the latest version, or this build is tagged for no-update -// this.result = Updater.UpdateResult.NO_UPDATE; -// return false; -// } -// } else { -// // The file's name did not contain the string 'vVersion' -// final String authorInfo = this.plugin.getDescription().getAuthors().isEmpty() ? -// "" : -// " (" + this.plugin.getDescription().getAuthors().get(0) + ")"; -// this.plugin.getLogger().warning("The author of this plugin" + authorInfo -// + " has misconfigured their Auto Update system"); -// this.plugin.getLogger() -// .warning("File versions should follow the format 'PluginName vVERSION'"); -// this.plugin.getLogger().warning("Please notify the author of this error."); -// this.result = Updater.UpdateResult.FAIL_NOVERSION; -// return false; -// } -// } -// return true; -// } -// -// /** -// * If you wish to run mathematical versioning checks, edit this method. -// *

    -// * With default behavior, Updater will NOT verify that a remote version available on BukkitDev -// * which is not this version is indeed an "update". -// * If a version is present on BukkitDev that is not the version that is currently running, -// * Updater will assume that it is a newer version. -// * This is because there is no standard versioning scheme, and creating a calculation that can -// * determine whether a new update is actually an update is sometimes extremely complicated. -// *

    -// *

    -// * Updater will call this method from {@link #versionCheck()} before deciding whether -// * the remote version is actually an update. -// * If you have a specific versioning scheme with which a mathematical determination can -// * be reliably made to decide whether one version is higher than another, you may -// * revise this method, using the local and remote version parameters, to execute the -// * appropriate check. -// *

    -// *

    -// * Returning a value of false will tell the update process that this is NOT a new version. -// * Without revision, this method will always consider a remote version at all different from -// * that of the local version a new update. -// *

    -// * -// * @param localVersion the current version -// * @param remoteVersion the remote version -// * @return true if Updater should consider the remote version an update, false if not. -// */ -// public boolean shouldUpdate(String localVersion, String remoteVersion) { -// return !localVersion.equalsIgnoreCase(remoteVersion); -// } -// -// /** -// * Evaluate whether the version number is marked showing that it should not be updated by this program. -// * -// * @param version a version number to check for tags in. -// * @return true if updating should be disabled. -// */ -// private boolean hasTag(String version) { -// for (final String string : Updater.NO_UPDATE_TAG) { -// if (version.contains(string)) { -// return true; -// } -// } -// return false; -// } -// -// /** -// * Make a connection to the BukkitDev API and request the newest file's details. -// * -// * @return true if successful. -// */ -// private boolean read() { -// try { -// final URLConnection conn = this.url.openConnection(); -// conn.setConnectTimeout(5000); -// -// if (this.apiKey != null) { -// conn.addRequestProperty("X-API-Key", this.apiKey); -// } -// conn.addRequestProperty("User-Agent", Updater.USER_AGENT); -// -// conn.setDoOutput(true); -// -// final BufferedReader reader = -// new BufferedReader(new InputStreamReader(conn.getInputStream())); -// final String response = reader.readLine(); -// -// final JSONArray array = (JSONArray) JSONValue.parse(response); -// -// if (array.isEmpty()) { -// this.plugin.getLogger() -// .warning("The updater could not find any files for the project id " + this.id); -// this.result = UpdateResult.FAIL_BADID; -// return false; -// } -// -// JSONObject latestUpdate = (JSONObject) array.get(array.size() - 1); -// this.versionName = (String) latestUpdate.get(Updater.TITLE_VALUE); -// this.versionLink = (String) latestUpdate.get(Updater.LINK_VALUE); -// this.versionType = (String) latestUpdate.get(Updater.TYPE_VALUE); -// this.versionGameVersion = (String) latestUpdate.get(Updater.VERSION_VALUE); -// -// return true; -// } catch (final IOException e) { -// if (e.getMessage().contains("HTTP response code: 403")) { -// this.plugin.getLogger().severe( -// "dev.bukkit.org rejected the API key provided in plugins/Updater/config.yml"); -// this.plugin.getLogger() -// .severe("Please double-check your configuration to ensure it is correct."); -// this.result = UpdateResult.FAIL_APIKEY; -// } else { -// this.plugin.getLogger() -// .severe("The updater could not contact dev.bukkit.org for updating."); -// this.plugin.getLogger().severe( -// "If you have not recently modified your configuration and this is the first time you are seeing this message, the site may be experiencing temporary downtime."); -// this.result = UpdateResult.FAIL_DBO; -// } -// this.plugin.getLogger().log(Level.SEVERE, null, e); -// return false; -// } -// } -// -// /** -// * Perform a file operation and log any errors if it fails. -// * -// * @param file file operation is performed on. -// * @param result result of file operation. -// * @param create true if a file is being created, false if deleted. -// */ -// private void fileIOOrError(File file, boolean result, boolean create) { -// if (!result) { -// this.plugin.getLogger().severe( -// "The updater could not " + (create ? "create" : "delete") + " file at: " + file -// .getAbsolutePath()); -// } -// } -// -// private File[] listFilesOrError(File folder) { -// File[] contents = folder.listFiles(); -// if (contents == null) { -// this.plugin.getLogger().severe( -// "The updater could not access files at: " + this.updateFolder.getAbsolutePath()); -// return new File[0]; -// } else { -// return contents; -// } -// } -// -// /** -// * Called on main thread when the Updater has finished working, regardless -// * of result. -// */ -// public interface UpdateCallback { -// /** -// * Called when the updater has finished working. -// * -// * @param updater The updater instance -// */ -// void onFinish(Updater updater); -// } -// -// -// private class UpdateRunnable implements Runnable { -// @Override public void run() { -// runUpdater(); -// } -// } -// -// private void runUpdater() { -// if (this.url != null && (this.read() && this.versionCheck())) { -// // Obtain the results of the project's file feed -// if ((this.versionLink != null) && (this.type != UpdateType.NO_DOWNLOAD)) { -// String name = this.file.getName(); -// // If it's a zip file, it shouldn't be downloaded as the plugin's name -// if (this.versionLink.endsWith(".zip")) { -// name = this.versionLink.substring(this.versionLink.lastIndexOf("/") + 1); -// } -// this.saveFile(name); -// } else { -// this.result = UpdateResult.UPDATE_AVAILABLE; -// } -// } -// -// if (this.callback != null) { -// new BukkitRunnable() { -// @Override public void run() { -// runCallback(); -// } -// }.runTask(this.plugin); -// } -// } -// -// private void runCallback() { -// this.callback.onFinish(this); -// } } \ No newline at end of file diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/BackpackEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/BackpackEvent.java new file mode 100644 index 000000000..61e65422c --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/BackpackEvent.java @@ -0,0 +1,389 @@ +package tech.mcprison.prison.spigot.api; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +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.Inventory; +import org.bukkit.plugin.EventExecutor; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; + +import tech.mcprison.prison.spigot.SpigotPrison; + +public class BackpackEvent + extends Event + implements Cancellable { + + private Player player; + + private BackpackCallback callback; + + private boolean cancel; + + private final List inventory; + + private BackpackAction action; + + private BackpackResults results; + + /** + *

    These backpack actions just represents the Integration's backpack + * function that was called. You may have special processing you would + * like to do before or after handling these events. It's optional. + *

    + * + *
      + * + *
    + */ + public enum BackpackAction { + undefined, + addItems, + smeltItems, + removeAll, + sellItems + } + + /** + *

    These are the backpack transaction results which would only be + * valid after the events are fired and the results are being processed + * in the BackpackCallback function. + *

    + * + *
      + *
    • undefined : The status before the backpack inventories are processed.
    • + *
    • noChange : The inventory has not been changed.
    • + *
    • contentsChanged : The inventory contents has been changed.
    • + *
    + */ + public enum BackpackResults { + undefined, // The status before the backpack inventories are processed + noChange, + contentsChanged + } + + public interface BackpackCallback { + public void run(); + } + + /** + *

    Warning: BlastUseEvent does not identify the block the player actually hit, so the dummyBlock + * is just a random first block from the explodedBlocks list and may not be the block + * that initiated the explosion event. Such events are identified by + * BlockEventType.CEXplosion. Make sure you do not process the first block twice, + * which is also passed as the org.bukkit.block.Block and the SpigotBlock to prevent have to + * pass nulls. They are the exact same objects. + *

    + * + * Due to this behavior, since BlockBreakEvent's handlers is static, it + * will "share" the handlers (listeners). To prevent this unwanted behavior, + * since prison's BlockBreakEvent listeners will be called, this class + * defines and overrides the the handlers with it's own instance. + * + */ + private static final HandlerList handlers = new HandlerList(); + + public BackpackEvent() { + super(); + + this.player = null; + this.cancel = false; + + this.callback = null; + + this.inventory = new ArrayList<>(); + + this.action = BackpackAction.undefined; + + this.results = BackpackResults.undefined; + } + + public BackpackEvent( Player player ) { + this(); + + this.player = player; + } + + + /** + *

    This is an example of how to fire this event for a player's backpack + * to take action. This function is flawed because you would need to use + * and access contents of the BackpackEvent, which this function will not + * return. So do not use this static function, but use the 4 lines of code + * as an example in your code. + *

    + * + *

    Generally this would not be used in your plugin, but this is how prison + * would fire the event internally. Your plugin could use it too, if it + * would cause the player's inventory to be full. + *

    + * + *

    Each time an event is fired, a new instance of the event is created + * so bukkit can pass that instance to all registered listeners. + *

    + * + * @param org.bukkit.entity.Player player + * @return boolean if the event was cancelled + */ + public static boolean fireBackpackEvent( Player player, BackpackAction action ) { + + BackpackEvent bpEvent = new BackpackEvent( player ); + bpEvent.setAction( action ); + + Bukkit.getServer().getPluginManager().callEvent( bpEvent ); + + if ( !bpEvent.fireBackpackEvent() ) { + // You would handle your plugin's actions here if this was called + // in line within your code. + } + + return bpEvent.isCancelled(); + } + + public boolean fireBackpackEvent() { + + Bukkit.getServer().getPluginManager().callEvent( this ); + + return isCancelled(); + } + + + /** + * This is an example of how you would setup a listener in your + * plugin, and how you would use it. It should generally be a class + * with a function of any name. The important key element is that it + * contains a parameter of class BackpackEvent. Specifying an + * @EventHandler annotation is optional, but it's included here to + * show you how you can use it to sent the event's priority. + * + * Dynamically setting the event priority based upon configs is + * beyond the purpose of this example. + * + * Make sure within your function, you put your code that will react + * to when this event is fired. You can refer to other classes + * within your plugin and do whatever you need to do. + * + * Your listener class must implement Listener. + * + */ + public class SampleBackpackListener + implements Listener { + + public SampleBackpackListener() { + super(); + + } + + /** + * This is for demonstration only. Do not use. + */ + public class DemoBackpack { + public DemoBackpack() { + super(); + } + public Inventory getPlayerBackpack( Player player ) { + return player.getInventory(); + } + public void setChanged() {} + public void save() {} + } + + + @EventHandler(priority=EventPriority.NORMAL) + public void onBackpackEvent( BackpackEvent bpEvent ) { + + // If the event has been canceled, then do not process this event + // since another plugin already processed it, or has denied that it + // should be processed. + if ( !bpEvent.isCancelled() ) { + + // Do something with this event here. + // You will have access to all of the functions in the event. + Player player = bpEvent.getPlayer(); + + // Pretend this represents a backpack object, whatever it may be. + // Just using an Object since we don't have your code for your backpacks, + // plus this is just an example. I've added dummy functions to this + // example backpack object so consider whatever you need to use + // with your own backpack. + + // Pretend we call our backpack function, passing the player to get + // the backpack for that player. In your code, the backpack object + // probably has been already created. For this demo, I'm just creating + // this dummy object here: + DemoBackpack backpack = new DemoBackpack(); + + + // Check to ensure the player has a valid backpack(s): + if ( backpack != null ) { + + // This example is just getting the player's inventory, which is wrong, + // for your code, return the inventory object from your backpack. + Inventory inventory = backpack.getPlayerBackpack( player ); + + // If you have more than one inventory object associated with your backpack, + // then add them all to bpEvent.getInventory(). + if ( inventory != null ) { + + // Add your backpack's inventory list. If you have more than one, then + // add them all. + bpEvent.getInventory().add( inventory ); + + + // Then setup your callback, which will run whatever code you need to use + // to process the backpack's action that was performed: + BackpackCallback callback = new BackpackCallback() { + public void run() { + + + switch ( bpEvent.getResults() ) { + case contentsChanged: + + // Process whatever you need to do after prison handles the + // inventory transactions: + backpack.setChanged(); + backpack.save(); + + break; + + default: + break; + } + + + } + }; + + bpEvent.setCallback( callback ); + + + boolean cancel = false; + + if ( cancel ) { + + // Canceling the event will prevent prison from process the backpack action: + bpEvent.setCancelled( true ); + } + // etc... + } + } + } + } + + + /** + * Somewhere in your plugin, you need to register your event listener with + * the Bukkit PluginManager. This is an example of how to do that. + * + * This will register your listener with the EventPriority of NORMAL if you + * have not used the @EventHandler annotation. + * + * When prison fires the InventoryEvent, Bukkit will go through all registered + * event listeners and will call the registered function (the one with the parameter + * that includes InventoryFullEvent) so it can run all of your code that you + * have placed in that function. + * + * Please note that this function is placed in the inner class of + * SampleInventoryFullListener only for demonstration purposes. You do not + * have to put this function, or the registration of your listener in + * your listener class. Generally, you may find it better suited to register + * all of your listeners in your primary plugin class. + * + * As a bonus, I have included a secondary registration at a custom priority + * that is not set by an annotation, but could be set within a config file. + * + */ + public void sampleUsageRegisterListenerEvent() { + + Plugin prison = SpigotPrison.getInstance(); // your plug. Don't use prison. + PluginManager pm = Bukkit.getServer().getPluginManager(); + + SampleBackpackListener sbpListener = new SampleBackpackListener(); + + pm.registerEvents( sbpListener, prison ); + + // Hint: to dynamically control the listener's EventPriority you would use + // the other pm.registerEvents() functions that allows you to set them + // upon registration. + + // WARNING: Do not register both events at the same time, or they will be + // be called twice and could duplicate everything. The following is + // included ONLY to show you how it can be done and is strictly + // for demonstration purposes. It's not needed if you can use + // the pm.registerEvents() function+. + + // The following shows how you can dynamically register your listener with + // a dynamically set EventPriority as defined in a config file. Assume + // that ePriority is based upon such a config that is requesting a LOW priority. + EventPriority ePriority = EventPriority.LOW; + + pm.registerEvent( BackpackEvent.class, sbpListener, ePriority, + new EventExecutor() { + public void execute( Listener l, Event e ) { + + BackpackEvent bpEvent = (BackpackEvent) e; + + ((SampleBackpackListener)l) + .onBackpackEvent( bpEvent ); + } + }, + prison ); + } + } + + + + @Override + public boolean isCancelled() { + return cancel; + } + @Override + public void setCancelled(boolean cancel) { + this.cancel = cancel; + } + + public Player getPlayer() { + return player; + } + + public List getInventory() { + return inventory; + } + + public BackpackCallback getCallback() { + return callback; + } + public void setCallback(BackpackCallback callback) { + this.callback = callback; + } + + public static HandlerList getHandlerList() { + return handlers; + } + public HandlerList getHandlers() { + return handlers; + } + + public BackpackAction getAction() { + return action; + } + public void setAction(BackpackAction action) { + this.action = action; + } + + public BackpackResults getResults() { + return results; + } + public void setResults(BackpackResults results) { + this.results = results; + } + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java index 6147bebaa..827bc560b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/ExplosiveBlockBreakEvent.java @@ -67,8 +67,6 @@ public class ExplosiveBlockBreakEvent private boolean calculateDurability = true; -// private boolean processedSuccessfully = false; - public ExplosiveBlockBreakEvent( Block theBlock, Player player, List explodedBlocks, String triggeredBy ) { @@ -76,6 +74,8 @@ public ExplosiveBlockBreakEvent( Block theBlock, Player player, this.explodedBlocks = explodedBlocks; this.triggeredBy = triggeredBy; + + this.setCancelled( false ); } public ExplosiveBlockBreakEvent( Block theBlock, Player player, List explodedBlocks ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/InventoryFullEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/InventoryFullEvent.java new file mode 100644 index 000000000..b19b01af8 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/InventoryFullEvent.java @@ -0,0 +1,255 @@ +/** + * + */ +package tech.mcprison.prison.spigot.api; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +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.Inventory; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.plugin.EventExecutor; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; + +import tech.mcprison.prison.spigot.SpigotPrison; + +/** + * This event is used by plugins that want to get access to notifications when + * prison detects a full inventory. + * + * In general, this only currently supports a player's inventory, but if + * a backpack is also registered with backpack events, then this could be + * fired when a backpack is also full. + */ +public class InventoryFullEvent + extends Event + implements Cancellable { + + private final Player player; + private boolean cancel; + + private final Inventory inventory; + + /** + *

    Warning: BlastUseEvent does not identify the block the player actually hit, so the dummyBlock + * is just a random first block from the explodedBlocks list and may not be the block + * that initiated the explosion event. Such events are identified by + * BlockEventType.CEXplosion. Make sure you do not process the first block twice, + * which is also passed as the org.bukkit.block.Block and the SpigotBlock to prevent have to + * pass nulls. They are the exact same objects. + *

    + * + * Due to this behavior, since BlockBreakEvent's handlers is static, it + * will "share" the handlers (listeners). To prevent this unwanted behavior, + * since prison's BlockBreakEvent listeners will be called, this class + * defines and overrides the the handlers with it's own instance. + * + */ + private static final HandlerList handlers = new HandlerList(); + + public InventoryFullEvent() { + super(); + + this.player = null; + this.cancel = false; + this.inventory = null; + } + + public InventoryFullEvent( Player player ) { + super(); + + this.player = player; + this.cancel = false; + + this.inventory = player.getInventory(); + } + + public PlayerInventory getPlayerInventory() { + PlayerInventory inv = null; + + if ( getInventory() != null && getInventory() instanceof PlayerInventory ) { + inv = (PlayerInventory) getInventory(); + } + + return inv; + } + + + /** + * This is an example of how to fire this event for a player's inventory. + * + * Generally this would not be used in your plugin, but this is how prison + * would fire the event internally. Your plugin could use it too, if it + * would cause the player's inventory to be full. + * + * Each time an event is fired, a new instance of the event is created + * so bukkit can pass that instance to all registered listeners. + * + * @param org.bukkit.entity.Player player + * @return boolean if the event was cancelled + */ + public static boolean fireInventoryFullEvent( Player player ) { + boolean isCancelled = false; + + InventoryFullEvent ifEvent = new InventoryFullEvent( player ); + + Bukkit.getServer().getPluginManager().callEvent( ifEvent ); + + if ( !ifEvent.isCancelled() ) { + // You would handle your plugin's actions here if this was called + // in line within your code. + } + + return isCancelled; + } + + + + /** + * This is an example of how you would setup a listener in your + * plugin, and how you would use it. It should generally be a class + * with a function of any name. The important key element is that it + * contains a parameter of class InventoryFullEvent. Specifying an + * @EventHandler annotation is optional, but it's included here to + * show you how you can use it to sent the event's priority. + * + * Dynamically setting the event priority based upon configs is + * beyond the purpose of this example. + * + * Make sure within your function, you put your code that will react + * to when this event is fired. You can refer to other classes + * within your plugin and do whatever you need to do. + * + * Your listener class must implement Listener. + * + */ + public class SampleInventoryFullListener + implements Listener { + + public SampleInventoryFullListener() { + super(); + + } + + @EventHandler(priority=EventPriority.NORMAL) + public void onInventoryFullEvent( InventoryFullEvent ifEvent ) { + + // If the event has been canceled, then do not process this event + // since another plugin already processed it, or has denyed that it + // should be processed. + if ( !ifEvent.isCancelled() ) { + + // Do something with this event here. + // You will have access to all of the functions in the event. + if ( ifEvent.getPlayerInventory() != null ) { + + // A playerInventory was registered with this event: + @SuppressWarnings("unused") + PlayerInventory pi = ifEvent.getPlayerInventory(); + + boolean success = true; + + if ( success ) { + + // If what we're doing in this example is successful and we need to + // cancel the event: + ifEvent.setCancelled( true ); + } + // etc... + } + } + } + + + /** + * Somewhere in your plugin, you need to register your event listener with + * the Bukkit PluginManager. This is an example of how to do that. + * + * This will register your listener with the EventPriority of NORMAL if you + * have not used the @EventHandler annotation. + * + * When prison fires the InventoryEvent, Bukkit will go through all registered + * event listeners and will call the registered function (the one with the parameter + * that includes InventoryFullEvent) so it can run all of your code that you + * have placed in that function. + * + * Please note that this function is placed in the inner class of + * SampleInventoryFullListener only for demonstration purposes. You do not + * have to put this function, or the registration of your listener in + * your listener class. Generally, you may find it better suited to register + * all of your listeners in your primary plugin class. + * + * As a bonus, I have included a secondary registration at a custom priority + * that is not set by an annotation, but could be set within a config file. + * + */ + public void sampleUsageRegisterListenerEvent() { + + Plugin prison = SpigotPrison.getInstance(); // Your plugin. Don't use prison. + PluginManager pm = Bukkit.getServer().getPluginManager(); + + SampleInventoryFullListener sifListener = new SampleInventoryFullListener(); + + pm.registerEvents( sifListener, prison ); + + // Hint: to dynamically control the listener's EventPriority you would use + // the other pm.registerEvents() functions that allows you to set them + // upon registration. + + // WARNING: Do not register both events at the same time, or they will be + // be called twice and could duplicate everything. The following is + // included ONLY to show you how it can be done and is strictly + // for demonstration purposes. It's not needed if you can use + // the pm.registerEvents() function+. + + // The following shows how you can dynamically register your listener with + // a dynamically set EventPriority as defined in a config file. Assume + // that ePriority is based upon such a config that is requesting a LOW priority. + EventPriority ePriority = EventPriority.LOW; + + pm.registerEvent(InventoryFullEvent.class, sifListener, ePriority, + new EventExecutor() { + public void execute(Listener l, Event e) { + + InventoryFullEvent iffEvent = (InventoryFullEvent) e; + + ((SampleInventoryFullListener)l) + .onInventoryFullEvent( iffEvent ); + } + }, + prison); + } + } + + public Player getPlayer() { + return player; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public Inventory getInventory() { + return inventory; + } + + public boolean isCancelled() { + return cancel; + } + + public void setCancelled(boolean cancel) { + this.cancel = cancel; + } + +} 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 415085e15..31380e756 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 @@ -11,6 +11,7 @@ import org.bukkit.event.block.BlockBreakEvent; import tech.mcprison.prison.Prison; +import tech.mcprison.prison.bombs.MineBombData; import tech.mcprison.prison.internal.block.MineTargetPrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; import tech.mcprison.prison.mines.data.Mine; @@ -18,9 +19,9 @@ 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.OnBlockBreakMines.MinesEventResults; 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; @@ -76,8 +77,6 @@ public class PrisonMinesBlockBreakEvent private MineTargetPrisonBlock targetBlock; - //private SpigotBlock overRideSpigotBlock; - private List explodedBlocks; // The targetBlocks are the blocks that were used to reset the mine with. @@ -88,6 +87,9 @@ public class PrisonMinesBlockBreakEvent private String triggered; + private MineBombData mineBomb; + + // If this is set during the validation process, and the validation fails, then this it will // force the canceling of the original block event. private boolean cancelOriginalEvent = false; @@ -137,6 +139,8 @@ public class PrisonMinesBlockBreakEvent private List bukkitDrops; + private int preventedDrops; + private List unprocessedRawBlocks; @@ -184,6 +188,8 @@ public PrisonMinesBlockBreakEvent( this.blockEventType = blockEventType; this.triggered = triggered; + this.mineBomb = null; + this.explodedBlocks = new ArrayList<>(); this.targetExplodedBlocks = new ArrayList<>(); @@ -191,6 +197,8 @@ public PrisonMinesBlockBreakEvent( this.bukkitDrops = new ArrayList<>(); + this.preventedDrops = 0; + this.debugInfo = new StringBuilder(); setDebugColorCodeDebug(); this.debugInfo.append( debugInfo ); @@ -225,8 +233,12 @@ public PrisonMinesBlockBreakEvent( Block theBlock, Player player, this.triggered = triggered; + this.mineBomb = null; + this.bukkitDrops = new ArrayList<>(); + this.preventedDrops = 0; + this.debugInfo = debugInfo; this.applyToPlayersBlockCount = true; @@ -430,6 +442,13 @@ public void setBukkitDrops( List drops ) { this.bukkitDrops = drops; } + public int getPreventedDrops() { + return preventedDrops; + } + public void setPreventedDrops(int preventedDrops) { + this.preventedDrops = preventedDrops; + } + public BlockEventType getBlockEventType() { return blockEventType; } @@ -444,13 +463,6 @@ public void setTriggered( String triggered ) { this.triggered = triggered; } -// public SpigotBlock getOverRideSpigotBlock() { -// return overRideSpigotBlock; -// } -// public void setOverRideSpigotBlock( SpigotBlock overRideSpigotBlock ) { -// this.overRideSpigotBlock = overRideSpigotBlock; -// } - public boolean isCancelOriginalEvent() { return cancelOriginalEvent; } @@ -486,20 +498,6 @@ public void setBbPriority( BlockBreakPriority bbPriority ) { this.bbPriority = bbPriority; } -// public boolean isMonitor() { -// return monitor; -// } -// public void setMonitor( boolean monitor ) { -// this.monitor = monitor; -// } -// -// public boolean isBlockEventsOnly() { -// return blockEventsOnly; -// } -// public void setBlockEventsOnly( boolean blockEventsOnly ) { -// this.blockEventsOnly = blockEventsOnly; -// } - public List getUnprocessedRawBlocks() { return unprocessedRawBlocks; } @@ -528,6 +526,13 @@ public HandlerList getHandlers() { public static HandlerList getHandlerList() { return handlers; } + + public MineBombData getMineBomb() { + return mineBomb; + } + public void setMineBomb( MineBombData mineBomb ) { + this.mineBomb = mineBomb; + } public StringBuilder getDebugInfo() { return debugInfo; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockEventEvent.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockEventEvent.java index 15631197a..fbf01bb3e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockEventEvent.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/api/PrisonMinesBlockEventEvent.java @@ -73,8 +73,6 @@ public class PrisonMinesBlockEventEvent private Mine mine; private SpigotBlock spigotBlock; - //private SpigotBlock overRideSpigotBlock; - private List explodedBlocks; private BlockEventType blockEventType; @@ -187,13 +185,6 @@ public void setTriggered( String triggered ) { this.triggered = triggered; } -// public SpigotBlock getOverRideSpigotBlock() { -// return overRideSpigotBlock; -// } -// public void setOverRideSpigotBlock( SpigotBlock overRideSpigotBlock ) { -// this.overRideSpigotBlock = overRideSpigotBlock; -// } - public String getParameter() { return parameter; } @@ -201,8 +192,6 @@ public void setParameter( String parameter ) { this.parameter = parameter; } - -// @Override public HandlerList getHandlers() { return handlers; } 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 58d8d426a..0c6357955 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 @@ -26,7 +26,6 @@ import tech.mcprison.prison.ranks.PrisonRanks; import tech.mcprison.prison.ranks.data.Rank; import tech.mcprison.prison.ranks.data.RankPlayer; -import tech.mcprison.prison.ranks.managers.PlayerManager; import tech.mcprison.prison.ranks.managers.RankManager; import tech.mcprison.prison.selection.Selection; import tech.mcprison.prison.spigot.SpigotPrison; @@ -51,31 +50,14 @@ *

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

    - * @param - * */ -public class PrisonSpigotAPI { +public class PrisonSpigotAPI { private PrisonMines prisonMineManager; private boolean mineModuleDisabled = false; private SellAllUtil sellAll; - private void junk() { - -// SpigotPrison.getInstance().isSellAllEnabled(); -// -// SpigotPlayer sPlayer = new SpigotPlayer( Player player ); -// -// sPlayer.getSellAllMulitiplier() -// sPlayer.getSellAllMultiplierListings() -// sPlayer.checkAutoSellPermsAutoFeatures() -// sPlayer.checkAutoSellTogglePerms( sbDebug ) -// sPlayer.isAutoSellEnabled( sbDebug ) -// - - // PrisonSpigotAPI.sellPlayerItems(Player player ); - } // private void handleAffectedBlocks(Player p, IWrappedRegion region, List blocksAffected) { // double totalDeposit = 0.0; @@ -127,57 +109,77 @@ private void junk() { // } /** - *

    This returns all mines that are within prison. + *

    + * This returns all mines that are within prison. *

    * * @return results - List of Mines */ public List getMines() { + List results = new ArrayList<>(); - - if ( PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled() ) { - MineManager mm = PrisonMines.getInstance().getMineManager(); - results = mm.getMines(); - } - + if ( PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled() ) { + MineManager mm = PrisonMines.getInstance().getMineManager(); + + results = mm.getMines(); + } + return results; } /** - *

    Returns all mines within prison, but sorted by the specified sort order. - * Because some sort types omit mines, there are two different collections within the - * PrisonSortableResults. There is an include and exclude list. + *

    + * Returns all mines within prison, but sorted by the specified sort order. Because some sort types omit mines, there + * are two different collections within the PrisonSortableResults. There is an include and exclude list. *

    * - *

    All sort types that omit mines from the result type has a counter sort type - * that will include all mines and will not omit any. Those begin with an "x". + *

    + * All sort types that omit mines from the result type has a counter sort type that will include all mines and will not + * omit any. Those begin with an "x". *

    * * @param sortOrder - MineSortOrder * @return results - PrisonSortableResults */ public PrisonSortableResults getMines( MineSortOrder sortOrder ) { + PrisonSortableResults results = null; - - if ( PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled() ) { - MineManager mm = PrisonMines.getInstance().getMineManager(); - results = mm.getMines(sortOrder); - } - + if ( PrisonMines.getInstance() != null && PrisonMines.getInstance().isEnabled() ) { + MineManager mm = PrisonMines.getInstance().getMineManager(); + + results = mm.getMines( sortOrder ); + } + return results; } + /** + *

    This will get the prison's RankPlayer object, which will trigger adding the + * given player to Prison if they do not already exist. This is done through the + * SpigotPlayer. + *

    + * + * @param bukkitPlayer + * @return + */ public RankPlayer getRankPlayer( Player bukkitPlayer ) { RankPlayer results = null; if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { - PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); + SpigotPlayer sPlayer = new SpigotPlayer( bukkitPlayer ); - results = pm.getPlayer( bukkitPlayer.getUniqueId(), bukkitPlayer.getName() ); + if ( sPlayer != null ) { + + results = sPlayer.getRankPlayer(); + } + +// PlayerManager pm = PrisonRanks.getInstance().getPlayerManager(); +// +// results = pm.getPlayer( bukkitPlayer.getUniqueId(), bukkitPlayer.getName() ); } return results; @@ -361,10 +363,11 @@ public Mine getPrisonMine( Player player, Block block, boolean isCanceledEvent) // Need to wrap in a Prison block so it can be used with the mines: SpigotBlock spigotBlock = SpigotBlock.getSpigotBlock(block); - Long playerUUIDLSB = Long.valueOf( player.getUniqueId().getLeastSignificantBits() ); + String uuid = player.getUniqueId().toString(); +// Long playerUUIDLSB = Long.valueOf( player.getUniqueId().getLeastSignificantBits() ); // Get the cached mine, if it exists: - Mine mine = getPlayerCache().get( playerUUIDLSB ); + Mine mine = getPlayerCache().get( uuid ); if ( mine == null || !mine.isInMineExact( spigotBlock.getLocation() ) ) { // Look for the correct mine to use. @@ -373,7 +376,7 @@ public Mine getPrisonMine( Player player, Block block, boolean isCanceledEvent) // Store the mine in the player cache if not null: if ( mine != null ) { - getPlayerCache().put( playerUUIDLSB, mine ); + getPlayerCache().put( uuid, mine ); } } @@ -450,7 +453,7 @@ public boolean createMine( String mineName, String tag, return results; } - private TreeMap getPlayerCache() { + private TreeMap getPlayerCache() { return getPrisonMineManager().getPlayerCache(); } @@ -781,14 +784,23 @@ public void payPlayer( Player player, double amount, String currency, boolean completelySilent = notifyPlayerEarned || notifyPlayerDelay || notifyPlayerEarningDelay || playSoundOnSellAll; SpigotPlayer sPlayer = new SpigotPlayer( player ); - RankPlayer rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer(sPlayer.getUUID(), sPlayer.getName()); + + + RankPlayer rankPlayer = sPlayer.getRankPlayer(); +// 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 ( rankPlayer != null ) { + + rankPlayer.addBalance(currency, amount); + } + else { + sPlayer.addBalance(currency, amount); + } if ( getPrisonSellAll().isSellAllDelayEnabled ){ getPrisonSellAll().addToDelay(player); 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 d11f389ca..0e43ba34d 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 @@ -3,8 +3,8 @@ import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Random; import java.util.Set; @@ -26,8 +26,10 @@ import org.bukkit.plugin.RegisteredListener; import com.cryptomorin.xseries.XMaterial; +import com.vk2gpz.tokenenchant.api.ITokenEnchant; import com.vk2gpz.tokenenchant.api.TokenEnchantAPI; +import me.revils.revenchants.api.RevEnchantsApi; import tech.mcprison.prison.Prison; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; @@ -35,6 +37,7 @@ import tech.mcprison.prison.cache.PlayerCache; import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlock.PrisonBlockType; +import tech.mcprison.prison.internal.block.PrisonBlockStatusData; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.output.ChatDisplay; import tech.mcprison.prison.output.Output; @@ -50,12 +53,13 @@ import tech.mcprison.prison.spigot.compat.SpigotCompatibility; import tech.mcprison.prison.spigot.game.SpigotHandlerList; import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.spigot.nbt.PrisonNBTUtil; import tech.mcprison.prison.spigot.sellall.SellAllUtil; -import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; import tech.mcprison.prison.spigot.utils.tasks.PlayerAutoRankupTask; import tech.mcprison.prison.tasks.PrisonCommandTaskData; import tech.mcprison.prison.tasks.PrisonCommandTaskData.TaskMode; import tech.mcprison.prison.tasks.PrisonCommandTasks; +import tech.mcprison.prison.util.BluesSemanticVersionComparator; import tech.mcprison.prison.util.Text; /** @@ -96,56 +100,57 @@ private void setup() { } - /** - *

    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. - *

    - * - * @param pmEvent - * @param start - * @return - */ - protected boolean checkIfNoAccess( PrisonMinesBlockBreakEvent pmEvent, double start ) { - boolean results = false; - - // NOTE: Check for the ACCESS priority and if someone does not have access, then return - // with a cancel on the event. - if ( pmEvent.getBbPriority().isAccess() && pmEvent.getMine() != null && - !pmEvent.getMine().hasMiningAccess( pmEvent.getSpigotPlayer() )) { - - String message = String.format( "(&cACCESS fail: player %s does not have access to " - + "mine %s&3. Event canceled) ", - pmEvent.getSpigotPlayer().getName(), - pmEvent.getMine().getTag() ); - pmEvent.getDebugInfo().append( message ); - - printDebugInfo( pmEvent, start ); - - - if ( pmEvent.getSpigotPlayer() != null && - isBoolean( AutoFeatures.eventPriorityACCESSFailureTPToCurrentMine ) ) { - // run the `/mines tp` command for the player which will TP them to a - // mine they can access: - + /** + *

    + * 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. + *

    + * + * @param pmEvent + * @param start + * @return + */ + protected boolean checkIfNoAccess( PrisonMinesBlockBreakEvent pmEvent, double start ) { + + boolean results = false; + + // NOTE: Check for the ACCESS priority and if someone does not have access, then return + // with a cancel on the event. + if ( pmEvent.getBbPriority().isAccess() && pmEvent.getMine() != null && + !pmEvent.getMine().hasMiningAccess( pmEvent.getSpigotPlayer() ) ) { + + String message = String.format( "(&cACCESS fail: player %s does not have access to " + + "mine %s&3. Event canceled) ", + pmEvent.getSpigotPlayer().getName(), + pmEvent.getMine().getTag() ); + pmEvent.getDebugInfo().append( message ); + + printDebugInfo( pmEvent, start ); + + + if ( pmEvent.getSpigotPlayer() != null && + isBoolean( AutoFeatures.eventPriorityACCESSFailureTPToCurrentMine ) ) { + // run the `/mines tp` command for the player which will TP them to a + // mine they can access: + String debugInfo = String.format( - "ACCESS failed: teleport %s to valid mine.", - pmEvent.getSpigotPlayer().getName() ); - - PrisonCommandTaskData cmdTask = new PrisonCommandTaskData( debugInfo, - "mines tp", 0 ); + "ACCESS failed: teleport %s to valid mine.", + pmEvent.getSpigotPlayer().getName() ); + + PrisonCommandTaskData cmdTask = new PrisonCommandTaskData( debugInfo, + "mines tp", 0 ); cmdTask.setTaskMode( TaskMode.syncPlayer ); - PrisonCommandTasks.submitTasks( pmEvent.getSpigotPlayer(), cmdTask ); - - } - - results = true; - } - - return results; - } + PrisonCommandTasks.submitTasks( pmEvent.getSpigotPlayer(), cmdTask ); + + } + + results = true; + } + + return results; + } /** *

    Prints out the debugInfo if it has anything to print. @@ -158,7 +163,7 @@ protected void printDebugInfo( PrisonMinesBlockBreakEvent pmEvent, double start if ( pmEvent != null && pmEvent.getDebugInfo().length() > 0 ) { long stop = System.nanoTime(); - pmEvent.getDebugInfo().append( "{br}|| ### ** End Event Debug Info ** ### [" ) + pmEvent.getDebugInfo().append( "{br}|| &6### ** End Event Debug Info ** ###&3 [" ) .append( (stop - start) / 1000000d ) .append( " ms]" ); @@ -253,7 +258,7 @@ protected EventListenerCancelBy processPMBBEvent(PrisonMinesBlockBreakEvent pmEv if ( pmEvent.getMine() != null || pmEvent.getMine() == null && !isBoolean( AutoFeatures.pickupLimitToMines ) ) { - pmEvent.getDebugInfo().append( "(Fire pmEvent) " ); + pmEvent.getDebugInfo().append( "&2(Fire pmEvent &6*start*&2) &b" ); // 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. @@ -276,7 +281,7 @@ protected EventListenerCancelBy processPMBBEvent(PrisonMinesBlockBreakEvent pmEv pmEvent.setDebugColorCodeWarning(); pmEvent.getDebugInfo().append( - "(Fire pmEvent: PrisonMinesBlockBreakEvent was canceled by another plugin!) " ); + "&2(Fire pmEvent: &dPrisonMinesBlockBreakEvent was canceled by another plugin!&2)&b " ); pmEvent.setDebugColorCodeDebug(); } else { @@ -308,18 +313,18 @@ protected EventListenerCancelBy processPMBBEvent(PrisonMinesBlockBreakEvent pmEv else { pmEvent.setDebugColorCodeWarning(); - pmEvent.getDebugInfo().append( "(fire pmEvent:doAction failed without details) " ); + pmEvent.getDebugInfo().append( "&2(fire pmEvent: &7doAction failed without details&2) &b" ); pmEvent.setDebugColorCodeDebug(); } } - pmEvent.getDebugInfo().append( "(Fire pmEvent completed) " ); + pmEvent.getDebugInfo().append( "&2(Fire pmEvent &6*completed*&2) &b" ); } else { - pmEvent.getDebugInfo().append( "(Fire pmEvent bypassed) " ); + pmEvent.getDebugInfo().append( "&2(Fire pmEvent &6*bypassed*&2) &b" ); } return cancelBy; } @@ -384,27 +389,104 @@ protected boolean hasFortune(SpigotItemStack itemInHand){ protected int getFortune(SpigotItemStack itemInHand, StringBuilder debugInfo ){ int fortLevel = 0; boolean usedTEFortune = false; + boolean usedRevEnchantsFortune = false; if ( isBoolean( AutoFeatures.isUseTokenEnchantsFortuneLevel ) && itemInHand != null && itemInHand.getBukkitStack() != null ) { + debugInfo.append( " (useTokenEnchantsFortuneLevel:"); + try { + Class.forName( "com.vk2gpz.tokenenchant.api.TokenEnchantAPI", false, this.getClass().getClassLoader() ); + if ( TokenEnchantAPI.getInstance() != null ) { fortLevel = TokenEnchantAPI.getInstance().getEnchantments( itemInHand.getBukkitStack() ) .get( TokenEnchantAPI.getInstance().getEnchantment("Fortune")); usedTEFortune = true; + debugInfo.append( "used TokenEnchantAPI: level " ).append( fortLevel ); } } catch ( Exception e ) { - // ignore: could not use TE. + // ignore: could not use TE or TE version before v23.x is not loaded + + // Test for TE v23 & newer: + try { + Class.forName( "com.vk2gpz.tokenenchant.api.ITokenEnchant", false, this.getClass().getClassLoader() ); + + if ( ITokenEnchant.getInstance() != null ) { + + fortLevel = ITokenEnchant.getInstance().getEnchantments( itemInHand.getBukkitStack() ) + .get( ITokenEnchant.getInstance().getEnchantment("Fortune")); + + usedTEFortune = true; + debugInfo.append( "used ITokenEnchant: level " ).append( fortLevel ); + } + } + catch ( Exception e2 ) { + // Ignore - Cannot use TE + + debugInfo.append( " &4WARNING: Feature enabled but TokenEnchants is not found.&3" ); + } + + } + + debugInfo.append(")"); + } + + + if ( isBoolean( AutoFeatures.isUseRevEnchantsFortuneLevel ) && + itemInHand != null && + itemInHand.getBukkitStack() != null ) { + + debugInfo.append( " (useRevEnchantsFortuneLevel:"); + + try { + Class.forName( "me.revils.revenchants.api.RevEnchantApi", false, this.getClass().getClassLoader() ); + +// boolean has1 = PrisonNBTUtil.hasNBTInt( itemInHand.getBukkitStack(), "tag"); +// boolean has2 = PrisonNBTUtil.hasNBTInt( itemInHand.getBukkitStack(), "tag.Enchants"); +// boolean has3 = PrisonNBTUtil.hasNBTInt( itemInHand.getBukkitStack(), "tag.Enchants.Fortune"); + + if ( RevEnchantsApi.isTool( itemInHand.getBukkitStack() ) && + PrisonNBTUtil.hasNBTInt( itemInHand.getBukkitStack(), "tag.Enchants.Fortune") ) { + + int fortRevEnchants = PrisonNBTUtil.getNBTInt( itemInHand.getBukkitStack(), "tag.Enchants.Fortune"); + + if ( fortRevEnchants > -1 ) { + + fortLevel = fortRevEnchants; + usedRevEnchantsFortune = true; + + debugInfo.append( "used RevEnchant NBT: level " ).append( fortLevel ); + } + else { + + debugInfo.append( "RevEnchantAPI returned -1 (no fortune) " ).append( fortLevel ); + } + + +// usedRevEnchantsFortune = true; + } + } + catch ( Exception e ) { + // ignore: could not use RevEnchants + + debugInfo.append( " &4WARNING: Feature enabled but RevEnchants is not found.&3" ); + } + + debugInfo.append(")"); } + + + try { if ( !usedTEFortune && + !usedRevEnchantsFortune && itemInHand != null && itemInHand.getBukkitStack() != null && itemInHand.getBukkitStack().containsEnchantment( Enchantment.LOOT_BONUS_BLOCKS ) && @@ -444,57 +526,19 @@ protected int getFortune(SpigotItemStack itemInHand, StringBuilder debugInfo ){ - -// @Override -// public boolean doAction( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { -// -// return processAutoEvents( pmEvent, debugInfo ); -// } - - - /** - *

    This function overrides the doAction in OnBlockBreakEventListener and - * this is only enabled when auto manager is enabled. - *

    - * - */ - @Override - public boolean doAction( PrisonMinesBlockBreakEvent pmEvent ) { - return applyAutoEvents( pmEvent ); - } - - -// private boolean processAutoEvents( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { -// boolean cancel = false; -// -// if (isBoolean(AutoFeatures.isAutoManagerEnabled) && !pmEvent.getSpigotBlock().isEmpty() ) { -// -// -// debugInfo.append( "(doAction autoManager processAutoEvent single-block) "); -// -// -//// Output.get().logInfo( "#### AutoManager.applyAutoEvents: BlockBreakEvent: :: " + mine.getName() + " " + -//// " blocks remaining= " + -//// mine.getRemainingBlockCount() + " [" + block.toString() + "]" -//// ); -// -// -// int count = applyAutoEventsDetails( pmEvent, debugInfo ); -// -// if ( count > 0 ) { -// processBlockBreakage( pmEvent, count, true, debugInfo ); -// -// cancel = true; -// } -// -// checkZeroBlockReset( pmEvent.getMine() ); -// -// } -// -// return cancel; -// } - + /** + *

    + * This function overrides the doAction in OnBlockBreakEventListener and this is only enabled when auto manager is + * enabled. + *

    + * + */ + @Override + public boolean doAction( PrisonMinesBlockBreakEvent pmEvent ) { + return applyAutoEvents( pmEvent ); + } + private int applyAutoEventsDetails( PrisonMinesBlockBreakEvent pmEvent ) { @@ -512,6 +556,19 @@ private int applyAutoEventsDetails( PrisonMinesBlockBreakEvent pmEvent ) { boolean loreSmelt = isLoreEnabled && checkLore( itemInHand, getMessage( AutoFeatures.loreSmeltValue) ); boolean loreBlock = isLoreEnabled && checkLore( itemInHand, getMessage( AutoFeatures.loreBlockValue ) ); + boolean isCustomEnchantEnabled = isBoolean( AutoFeatures.isCustomEnchantsEnabled ); + + boolean enchantsPickup = isCustomEnchantEnabled && checkEnchant( itemInHand, getMessage( AutoFeatures.customEnchantsAutoPickup ) ); + boolean enchantsSmelt = isCustomEnchantEnabled && checkEnchant( itemInHand, getMessage( AutoFeatures.customEnchantsAutoSmelt) ); + boolean enchantsBlock = isCustomEnchantEnabled && checkEnchant( itemInHand, getMessage( AutoFeatures.customEnchantsAutoBlock ) ); + + int enchantsPickupLevel = isCustomEnchantEnabled && enchantsPickup ? + getEnchantLevel( itemInHand, getMessage( AutoFeatures.customEnchantsAutoPickup ) ) : -1; + int enchantsSmeltLevel = isCustomEnchantEnabled && enchantsSmelt ? + getEnchantLevel( itemInHand, getMessage( AutoFeatures.customEnchantsAutoSmelt) ) : -1; + int enchantsBlockLevel = isCustomEnchantEnabled && enchantsBlock ? + getEnchantLevel( itemInHand, getMessage( AutoFeatures.customEnchantsAutoBlock ) ) : -1; + boolean isAutoFeaturesEnabled = isBoolean( AutoFeatures.isAutoFeaturesEnabled ); String permAutoPickup = getMessage( AutoFeatures.permissionAutoPickup ); @@ -544,56 +601,75 @@ private int applyAutoEventsDetails( PrisonMinesBlockBreakEvent pmEvent ) { boolean limit2minesSmelt = isBoolean( AutoFeatures.smeltLimitToMines ); boolean limit2minesBlock = isBoolean( AutoFeatures.blockLimitToMines ); - boolean isAutoPickup = lorePickup || configPickup || permPickup; + boolean isAutoPickup = lorePickup || enchantsPickup || configPickup || permPickup; isAutoPickup = (mine != null || mine == null && !limit2minesPickup) && isAutoPickup; - boolean isAutoSmelt = loreSmelt || configSmelt || permSmelt; + boolean isAutoSmelt = loreSmelt || enchantsSmelt || configSmelt || permSmelt; isAutoSmelt = (mine != null || mine == null && !limit2minesSmelt) && isAutoSmelt; - boolean isAutoBlock = loreBlock || configBlock || permBlock; + boolean isAutoBlock = loreBlock || enchantsPickup || configBlock || permBlock; isAutoBlock = (mine != null || mine == null && !limit2minesBlock) && isAutoBlock; + + boolean isNormalSmelt = loreSmelt || enchantsSmelt || configNormalDropSmelt || permSmelt; + isNormalSmelt = (mine != null || mine == null && !limit2minesSmelt) && isNormalSmelt; + + boolean isNormalBlock = loreBlock || enchantsPickup || configNormalDropBlock || permBlock; + isNormalBlock = (mine != null || mine == null && !limit2minesBlock) && isNormalBlock; + + + boolean includePlayerInventoryWhenSmelting = isBoolean( AutoFeatures.includePlayerInventoryWhenSmelting ); + boolean includePlayerInventoryWhenBlocking = isBoolean( AutoFeatures.includePlayerInventoryWhenBlocking ); + if ( Output.get().isDebug( DebugTarget.blockBreak ) ) { - pmEvent.getDebugInfo().append( "{br}|| (applyAutoEvents: " ) + pmEvent.getDebugInfo().append( "{br}|| (applyAutoEvents: " ) .append( pmEvent.getSpigotBlock().getBlockName() ); if ( !isAutoFeaturesEnabled ) { pmEvent.getDebugInfo().append(" isAutoFeaturesEnabled=false ("); pmEvent.getDebugInfo().append( Output.get().getColorCodeError() ); - pmEvent.getDebugInfo().append("disabled"); + pmEvent.getDebugInfo().append(" disabled"); pmEvent.getDebugInfo().append( Output.get().getColorCodeDebug() ); pmEvent.getDebugInfo().append(")"); } else { pmEvent.getDebugInfo() - .append( " Pickup [") - .append( isAutoPickup ? "enabled: " : "disabled:" ) + .append( " &7Pickup&3 [") + .append( isAutoPickup ? "enabled: " : + Output.get().getColorCodeError() + "disabled:" + Output.get().getColorCodeDebug() ) .append( lorePickup ? "lore " : "" ) + .append( enchantsPickup ? "enchant " + enchantsPickupLevel + " " : "" ) .append( permPickup ? "perm " : "" ) .append( configPickup ? "config " : "" ) .append( limit2minesPickup ? "mines" : "noLimit" ) .append( "] ") - .append( " Smelt [") - .append( isAutoSmelt ? "enabled: " : "disabled:" ) + .append( " &7Smelt&3 [") + .append( isAutoSmelt ? "enabled: " : + Output.get().getColorCodeError() + "disabled:" + Output.get().getColorCodeDebug() ) .append( loreSmelt ? "lore " : "" ) + .append( enchantsSmelt ? "enchant " + enchantsSmeltLevel + " " : "" ) .append( permSmelt ? "perm " : "" ) .append( configSmelt ? "config " : "" ) .append( limit2minesSmelt ? "mines" : "noLimit" ) + .append( includePlayerInventoryWhenSmelting ? " includePlayerInventory" : "" ) .append( "] ") - .append( " Block [") - .append( isAutoBlock ? "enabled: " : "disabled:" ) + .append( " &7Block&3 [") + .append( isAutoBlock ? "enabled: " : + Output.get().getColorCodeError() + "disabled:" + Output.get().getColorCodeDebug() ) .append( loreBlock ? "lore " : "" ) + .append( enchantsBlock ? "enchant " + enchantsBlockLevel + " " : "" ) .append( permBlock ? "perm " : "" ) .append( configBlock ? "config " : "" ) .append( limit2minesBlock ? "mines" : "noLimit" ) + .append( includePlayerInventoryWhenBlocking ? " includePlayerInventory" : "" ) .append( "] "); } @@ -606,7 +682,8 @@ private int applyAutoEventsDetails( PrisonMinesBlockBreakEvent pmEvent ) { // Ops will have to have the perms set to actually use them. // AutoPickup - if ( (mine != null || mine == null && !isBoolean( AutoFeatures.pickupLimitToMines )) ) { +// if ( (mine != null || mine == null && !isBoolean( AutoFeatures.pickupLimitToMines )) ) + { if ( isAutoPickup ) { @@ -622,25 +699,50 @@ private int applyAutoEventsDetails( PrisonMinesBlockBreakEvent pmEvent ) { if ( configNormalDrop ) { pmEvent.getDebugInfo() - .append( "{br}|| (NormalDrop handling enabled: " ) - .append( "normalDropSmelt[" ) - .append( configNormalDropSmelt ? "enabled" : "disabled" ) +// .append( "{br}|| ") + .append( "(&7NormalDrop handling enabled&3: " ) + .append( "&7normalDropSmelt&3[" ) + .append( isNormalSmelt ? "enabled" : + Output.get().getColorCodeError() + "disabled:" + Output.get().getColorCodeDebug() ) + + .append( loreSmelt ? "lore " : "" ) + .append( enchantsSmelt ? "enchant " + enchantsSmeltLevel + " " : "" ) + .append( permSmelt ? "perm " : "" ) + .append( configNormalDropSmelt ? "config " : "" ) + + .append( isNormalSmelt && includePlayerInventoryWhenSmelting ? " includePlayerInventory" : "" ) + + .append( "] " ) - .append( "normalDropBlock[" ) - .append( configNormalDropBlock ? "enabled" : "disabled" ) + .append( "&7normalDropBlock&3[" ) + .append( isNormalBlock ? "enabled" : + Output.get().getColorCodeError() + "disabled:" + Output.get().getColorCodeDebug() ) + + .append( loreBlock ? "lore " : "" ) + .append( enchantsBlock ? "enchant " + enchantsBlockLevel + " " : "" ) + .append( permBlock ? "perm " : "" ) + .append( configNormalDropBlock ? "config " : "" ) + + + .append( isNormalBlock && includePlayerInventoryWhenBlocking ? " includePlayerInventory" : "" ) .append( "] " ) - .append( "normalDropCheckForFullInventory[" ) - .append( configNormalDropCheckForFullInventory ? "enabled" : "disabled" ) + + .append( "&7normalDropCheckForFullInventory&3[" ) + .append( configNormalDropCheckForFullInventory ? "enabled" : + Output.get().getColorCodeError() + "disabled:" + Output.get().getColorCodeDebug() ) .append( "] " ) .append( ")" ); // process normal drops here: - totalDrops = calculateNormalDrop( pmEvent ); + totalDrops = calculateNormalDrop( pmEvent, isNormalSmelt, isNormalBlock ); } else { - pmEvent.getDebugInfo().append(" [Warning: normalDrop handling is disabled] " ); + pmEvent.getDebugInfo().append( + Output.get().getColorCodeError() + + " [Warning: normalDrop handling is disabled] " + + Output.get().getColorCodeDebug() ); } } @@ -695,6 +797,50 @@ private int applyAutoEventsDetails( PrisonMinesBlockBreakEvent pmEvent ) { } + private boolean checkEnchant(SpigotItemStack itemInHand, String enchantmentName) { + boolean results = false; + + Map enchants = itemInHand.getEnchantments(); + + if ( enchants != null && enchants.size() > 0 ) { + + Set enchs = enchants.keySet(); + for (Enchantment enchant : enchs) { + if ( enchant.getKey().toString().equalsIgnoreCase(enchantmentName) ) { + results = true; + break; + } + } + } + + return results; + } + + + private int getEnchantLevel(SpigotItemStack itemInHand, String enchantmentName) { + int enchantLevel = -1; + + Map enchants = itemInHand.getEnchantments(); + + if ( enchants != null && enchants.size() > 0 ) { + + Set enchs = enchants.keySet(); + for (Enchantment enchant : enchs) { + if ( enchant.getKey().toString().equalsIgnoreCase(enchantmentName) ) { + Integer eLevel = enchants.get(enchant); + if ( eLevel != null ) { + + enchantLevel = eLevel; + } + break; + } + } + } + + return enchantLevel; + } + + /** *

    This function gets called for EACH block that is impacted by the * explosion event. The event may have have a list of blocks, but not all @@ -826,7 +972,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, sb.insert( 0, "bukkitDropMult=" ); } - debugInfo.append( " [autoPickupDrops:beforeFortune:: " ).append( sb ).append( "] "); + debugInfo.append( " [&7autoPickupDrops&3:beforeFortune:: " ).append( sb ).append( "] "); @@ -858,7 +1004,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, .append( ":" ) .append( itemStack.getAmount() ); } - debugInfo.append( " [totalDrops:afterFortune:: " ).append( sb ).append( "] "); + debugInfo.append( " [&7totalDrops&3:afterFortune:: " ).append( sb ).append( "] "); } @@ -869,15 +1015,21 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, // Smelt if ( isAutoSmelt ) { - debugInfo.append( "(autoSmelting: drops)" ); - normalDropSmelt( drops ); + debugInfo.append( "(&7autoSmelting&3: " ); + + normalDropSmelt( pmEvent.getPlayer(), drops, debugInfo ); + + debugInfo.append( " )" ); } // Block if ( isAutoBlock ) { - debugInfo.append( "(autoBlocking: drops)" ); - normalDropBlock( drops ); + debugInfo.append( "(&7autoBlocking&3: " ); + + normalDropBlock( pmEvent.getPlayer(), drops, debugInfo ); + + debugInfo.append( " ) " ); } String mineName = pmEvent.getMine() == null ? null : pmEvent.getMine().getName(); @@ -982,7 +1134,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, amount, mineName ); if ( amount != 0 ) { - debugInfo.append( "(sold: " + itemStack.getName() + " qty: " + itemStack.getAmount() + + debugInfo.append( "(&7sold&3: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + dFmt.format( amount ) + ") "); // Set to zero quantity since they have all been sold. @@ -992,7 +1144,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, // Unable to sell since amount was zero. Not configured to be sold. pmEvent.setDebugColorCodeWarning(); - debugInfo.append( "(unsellable: " + itemStack.getName() + " qty: " + itemStack.getAmount() + ") "); + debugInfo.append( "(&7unsellable&3: " + itemStack.getName() + " qty: " + itemStack.getAmount() + ") "); pmEvent.setDebugColorCodeDebug(); autosellUnsellableCount += itemStack.getAmount(); } @@ -1024,7 +1176,8 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, double amount = SellAllUtil.get().getItemStackValue( pmEvent.getSpigotPlayer(), itemStack ); autosellTotal += amount; - debugInfo.append( "{br}|| (WARNING: autosell leftovers: " + itemStack.getName() + +// debugInfo.append( "{br}|| " ); + debugInfo.append( " (&7WARNING: autosell leftovers&3: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + dFmt.format( amount ) + " - " + ( amount == 0 ? " Items NOT in sellall shop!" : " CouldNotSell?") + @@ -1038,7 +1191,7 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, double amount = SellAllUtil.get().getItemStackValue( pmEvent.getSpigotPlayer(), itemStack ); autosellTotal += amount; - debugInfo.append( " (Debug-unsold-value-check: " + itemStack.getName() + + debugInfo.append( " (&7Debug-unsold-value-check&3: " + itemStack.getName() + " qty: " + itemStack.getAmount() + " value: " + dFmt.format( amount ) + ") "); } @@ -1074,7 +1227,8 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, if ( count > 0 || autosellTotal > 0 ) { - debugInfo.append( "{br}|| [autoPickupDrops total: qty: " + count + " value: " + dFmt.format( autosellTotal ) + +// debugInfo.append( "{br}|| " ); + debugInfo.append( " [&7autoPickupDrops total&3: qty: " + count + " value: " + dFmt.format( autosellTotal ) + " unsellableCount: " + autosellUnsellableCount ); if ( nanoTime > 0 ) { @@ -1104,7 +1258,8 @@ protected int autoPickup( PrisonMinesBlockBreakEvent pmEvent, - public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { + public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent, + boolean isNormalSmelt, boolean isNormalBlock ) { // Count should be the total number of items that are to be "dropped". // So effectively it will be the sum of all bukkitDrops counts. @@ -1157,7 +1312,7 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { sb.insert( 0, "bukkitDropMult=" ); } - pmEvent.getDebugInfo().append( "{br}|| [normalDrops:: " ).append( sb ).append( "] "); + pmEvent.getDebugInfo().append( "{br}|| [normalDrops:: " ).append( sb ).append( "] "); // Need better drop calculation that is not using the getDrops function. @@ -1184,15 +1339,21 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { drops = mergeDrops( drops ); - if ( isBoolean( AutoFeatures.normalDropSmelt ) ) { - pmEvent.getDebugInfo().append( "(normSmelting: drops)" ); - normalDropSmelt( drops ); + if ( isNormalSmelt ) { + pmEvent.getDebugInfo().append( "(normSmelting: " ); + + normalDropSmelt( pmEvent.getPlayer(), drops, pmEvent.getDebugInfo() ); + + pmEvent.getDebugInfo().append( " ) " ); } - if ( isBoolean( AutoFeatures.normalDropBlock ) ) { - pmEvent.getDebugInfo().append( "(normBlocking: drops)" ); - normalDropBlock( drops ); + if ( isNormalBlock ) { + pmEvent.getDebugInfo().append( "(normBlocking: " ); + + normalDropBlock( pmEvent.getPlayer(), drops, pmEvent.getDebugInfo() ); + + pmEvent.getDebugInfo().append( " ) " ); } @@ -1208,7 +1369,7 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { // } -// pmEvent.getDebugInfo().append( "{br}|| " ); +// pmEvent.getDebugInfo().append( "{br}|| " ); double autosellTotal = 0; @@ -1261,7 +1422,7 @@ public int calculateNormalDrop( PrisonMinesBlockBreakEvent pmEvent ) { if ( count > 0 || autosellTotal > 0 ) { - pmEvent.getDebugInfo().append( "{br}|| [normalDrops total: qty: " + count + " value: " + autosellTotal + "] "); + pmEvent.getDebugInfo().append( "{br}|| [normalDrops total: qty: " + count + " value: " + autosellTotal + "] "); } @@ -1640,11 +1801,6 @@ protected void dropExtra( HashMap extra, } -// private boolean isBoolean( Configuration sellAllConfig, String config ) { -// String configValue = sellAllConfig.getString( config ); -// return configValue != null && configValue.equalsIgnoreCase( "true" ); -// } - private void dropAtBlock( SpigotItemStack itemStack, SpigotBlock block ) { SpigotUtil.dropItems( block, itemStack ); @@ -1657,10 +1813,6 @@ private void notifyPlayerThatInventoryIsFull( Player player ) { notifyPlayerWithSound( player, message ); } -// @SuppressWarnings( "unused" ) -// private void notifyPlayerThatInventoryIsFullDroppingItems( Player player ) { -// notifyPlayerWithSound( player, AutoFeatures.inventoryIsFullDroppingItems ); -// } private void notifyPlayerThatInventoryIsFullLosingItems( Player player ) { @@ -1690,12 +1842,12 @@ private void notifyPlayerWithSound( Player player, String message ) { if ( sound == null ) { - if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.9.0" ) < 0 ) { + if ( new BluesSemanticVersionComparator().compareMCVersionTo( "1.9.0" ) < 0 ) { // 1.8.x sound = getSound("NOTE_PLING"); } - else if ( new BluesSpigetSemVerComparator().compareMCVersionTo( "1.13.0" ) < 0 ) { + else if ( new BluesSemanticVersionComparator().compareMCVersionTo( "1.13.0" ) < 0 ) { // 1.9.x through 1.12.x sound = getSound("BLOCK_NOTE_PLING"); @@ -1764,19 +1916,6 @@ private Sound getSound( String soundName ) { return results; } -// private void actionBarVersion(Player player, String message) { -// -// PlayerMessagingTask.submitTask( player, MessageType.actionBar, message ); -// -//// SpigotCompatibility.getInstance().sendActionBar( player, message ); -// -//// if (new BluesSpigetSemVerComparator().compareMCVersionTo("1.9.0") < 0) { -//// displayActionBarMessage(player, message); -//// } -//// else { -//// player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(SpigotPrison.format(message))); -//// } -// } /** * This is not usable since it not only prevents the player from mining when it is @@ -1800,10 +1939,6 @@ private void displayMessageHologram(Block block, String message, Player p){ Bukkit.getScheduler().scheduleSyncDelayedTask(SpigotPrison.getInstance(), as::remove, (7L * 20L)); } -// private void displayActionBarMessage(Player player, String message) { -// SpigotPlayer prisonPlayer = new SpigotPlayer(player); -// Prison.get().getPlatform().showActionBar(prisonPlayer, message, 80); -// } /** @@ -2227,11 +2362,13 @@ else if ( isBoolean( AutoFeatures.pickupBlockNameListEnabled ) && pickupBlockNam * * @param drops */ - protected void normalDropSmelt( List drops ) { + protected void normalDropSmelt( Player player, List drops, StringBuilder debugInfo ) { boolean isAll = isBoolean( AutoFeatures.smeltAllBlocks ); - Set xMats = new HashSet<>(); + boolean includePlayerInventory = isBoolean( AutoFeatures.includePlayerInventoryWhenSmelting ); + + TreeMap xMats = new TreeMap<>(); for ( SpigotItemStack sItemStack : drops ) { if ( sItemStack.getMaterial().getBlockType() == PrisonBlockType.CustomItems || @@ -2251,22 +2388,87 @@ else if ( sItemStack.getMaterial() != null ) { xMat = SpigotCompatibility.getInstance().getXMaterial( sItemStack.getMaterial() ); } - if ( xMat != null && !xMats.contains( xMat ) ) { - xMats.add( xMat ); + if ( xMat != null && !xMats.containsKey( xMat ) ) { + xMats.put( xMat, sItemStack ); } } - - for ( XMaterial source : xMats ) { - + Set keys = xMats.keySet(); + for ( XMaterial source : keys ) { + SpigotItemStack drop = xMats.get( source ); + + // smeltCobblestone: + // cCobblestone : stone + // smeltGoldOre: + // gold_ore : gold_ingot + // nether_gold_ore : gold_ingot + // deepslate_gold_ore : gold_ingot + // raw_gold : gold_ingot + // smeltIronOre: + // iron_ore : iron_ingot + // deepslate_iron_ore : iron_ingot + // raw_iron : iron__ingot + // smeltCoalOre: + // coal_ore: coal + // deeplate_core__ore : coal + // smeltDiamondlOre: + // diamond_ore : diamond + // deepslate_diamon_ore : diamond + // smeltEmeraldOre: + // emerald_ore : emerald + // deepslate_emerald_ore : emerald + // smeltLapisOre: + // lapis_ore : lapis_lazuli + // deepslate_lapis_ore : lapis_lazuli + // smeltRedstoneOre: + // redstone_ore : redstone + // deepslate_redstone_ore : redstone + // smeltNetherQuartzOre: + // nether_quartz__ore : quartz + // smeltAncientDebris: + // ancient_debris : netherite_scrap + // smeltCopperOre: + // copper_ore : copper_ingot + // deepslate_copper_ore : copper_ingot + // raw_copper : copper_ingot + + // No smelting: + // stone : smooth stone + // stone_bricks : cracked_stone_bricks + // cobbled_deepslate : deepslate + // deepslate_bricks : cracked_deepslate_bricks + // deepslate_tiles : cracked_deepslate_tiles + // sandstone : smooth_red_sandstone + // red_sandstone : smooth_red_sandstone + // nether_bricks : cracked_nether_bricks + // basalt : smooth_basalt + // polished_blackstone_bricks : cracked_polished_blackstone_bricks + // block_of_quartz : smooth_quartz + // clay : terracotta + // dyed terracotta : glazed_terracotta + // sand : glass + // wet_sponge : sponge + // log : charcoal + // wood : charcoal + // stripped_log : charcoal + // stripped_wood : charcoal + // chorus_fruit : popped_chorus_fruit + // sea_pickle : lime_dye + // cactus : green_dye + // clay_ball : brick + // netherrack : nether_brick switch ( source ) { case COBBLESTONE: if ( isAll || isBoolean( AutoFeatures.smeltCobblestone ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.STONE, 1 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.STONE, 1, debugInfo ); } break; @@ -2277,7 +2479,11 @@ else if ( sItemStack.getMaterial() != null ) { if ( isAll || isBoolean( AutoFeatures.smeltGoldOre ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.GOLD_INGOT, 1 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.GOLD_INGOT, 1, debugInfo ); } break; @@ -2286,7 +2492,11 @@ else if ( sItemStack.getMaterial() != null ) { case RAW_IRON: if ( isAll || isBoolean( AutoFeatures.smeltIronOre ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.IRON_INGOT, 1 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.IRON_INGOT, 1, debugInfo ); } break; @@ -2294,7 +2504,11 @@ else if ( sItemStack.getMaterial() != null ) { case DEEPSLATE_COAL_ORE: if ( isAll || isBoolean( AutoFeatures.smeltCoalOre ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.COAL, 1 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.COAL, 1, debugInfo ); } break; @@ -2302,7 +2516,11 @@ else if ( sItemStack.getMaterial() != null ) { case DEEPSLATE_DIAMOND_ORE: if ( isAll || isBoolean( AutoFeatures.smeltDiamondlOre ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.DIAMOND, 1 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.DIAMOND, 1, debugInfo ); } break; @@ -2310,7 +2528,11 @@ else if ( sItemStack.getMaterial() != null ) { case DEEPSLATE_EMERALD_ORE: if ( isAll || isBoolean( AutoFeatures.smeltEmeraldOre ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.EMERALD, 1 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.EMERALD, 1, debugInfo ); } break; @@ -2318,7 +2540,11 @@ else if ( sItemStack.getMaterial() != null ) { case DEEPSLATE_LAPIS_ORE: if ( isAll || isBoolean( AutoFeatures.smeltLapisOre ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.LAPIS_LAZULI, 1 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.LAPIS_LAZULI, 1, debugInfo ); } break; @@ -2326,21 +2552,33 @@ else if ( sItemStack.getMaterial() != null ) { case DEEPSLATE_REDSTONE_ORE: if ( isAll || isBoolean( AutoFeatures.smeltRedstoneOre ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.REDSTONE, 1 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.REDSTONE, 1, debugInfo ); } break; case NETHER_QUARTZ_ORE: if ( isAll || isBoolean( AutoFeatures.smeltNetherQuartzOre ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.QUARTZ, 1 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.QUARTZ, 1, debugInfo ); } break; case ANCIENT_DEBRIS: if ( isAll || isBoolean( AutoFeatures.smeltAncientDebris ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.NETHERITE_SCRAP, 1 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.NETHERITE_SCRAP, 1, debugInfo ); } break; @@ -2350,7 +2588,11 @@ else if ( sItemStack.getMaterial() != null ) { case RAW_COPPER: if ( isAll || isBoolean( AutoFeatures.smeltCopperOre ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.COPPER_INGOT, 1); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.COPPER_INGOT, 1, debugInfo); } break; @@ -2369,11 +2611,13 @@ else if ( sItemStack.getMaterial() != null ) { * * @param drops */ - protected void normalDropBlock( List drops ) { + protected void normalDropBlock( Player player, List drops, StringBuilder debugInfo ) { - boolean isAll = isBoolean( AutoFeatures.smeltAllBlocks ); + boolean isAll = isBoolean( AutoFeatures.blockAllBlocks ); + + boolean includePlayerInventory = isBoolean( AutoFeatures.includePlayerInventoryWhenSmelting ); - Set xMats = new HashSet<>(); + TreeMap xMats = new TreeMap<>(); for ( SpigotItemStack sItemStack : drops ) { if ( sItemStack.getMaterial().getBlockType() == PrisonBlockType.CustomItems || @@ -2386,98 +2630,281 @@ protected void normalDropBlock( List drops ) { XMaterial source = XMaterial.matchXMaterial( sItemStack.getBukkitStack() ); - if ( !xMats.contains( source ) ) { - xMats.add( source ); + if ( !xMats.containsKey( source ) ) { + xMats.put( source, sItemStack ); } } } - - for ( XMaterial source : xMats ) { + Set keys = xMats.keySet(); + for ( XMaterial source : keys ) { + SpigotItemStack drop = xMats.get( source ); switch ( source ) { + case GOLD_NUGGET: + if ( isAll || isBoolean( AutoFeatures.blockGoldIngot ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.GOLD_INGOT, 9, debugInfo ); + } + break; + + case RAW_GOLD: + if ( isAll || isBoolean( AutoFeatures.blockRawGoldBlock ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.RAW_GOLD_BLOCK, 9, debugInfo ); + } + break; + case GOLD_INGOT: if ( isAll || isBoolean( AutoFeatures.blockGoldBlock ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.GOLD_BLOCK, 9 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.GOLD_BLOCK, 9, debugInfo ); + } + break; + + case IRON_NUGGET: + if ( isAll || isBoolean( AutoFeatures.blockIronIngot ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.IRON_INGOT, 9, debugInfo ); + } + break; + + case RAW_IRON: + if ( isAll || isBoolean( AutoFeatures.blockRawIronBlock ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.RAW_IRON_BLOCK, 9, debugInfo ); } break; case IRON_INGOT: if ( isAll || isBoolean( AutoFeatures.blockIronBlock ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.IRON_BLOCK, 9 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.IRON_BLOCK, 9, debugInfo ); } break; case COAL: if ( isAll || isBoolean( AutoFeatures.blockCoalBlock ) ) { - - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.COAL_BLOCK, 9 ); + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.COAL_BLOCK, 9, debugInfo ); } break; case DIAMOND: if ( isAll || isBoolean( AutoFeatures.blockDiamondBlock ) ) { - - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.DIAMOND_BLOCK, 9 ); + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.DIAMOND_BLOCK, 9, debugInfo ); } break; case REDSTONE: if ( isAll || isBoolean( AutoFeatures.blockRedstoneBlock ) ) { - - SpigotUtil.itemStackReplaceItems( drops, source,XMaterial.REDSTONE_BLOCK, 9 ); + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source,XMaterial.REDSTONE_BLOCK, 9, debugInfo ); } break; case EMERALD: if ( isAll || isBoolean( AutoFeatures.blockEmeraldBlock ) ) { - - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.EMERALD_BLOCK, 9 ); + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.EMERALD_BLOCK, 9, debugInfo ); } break; case QUARTZ: if ( isAll || isBoolean( AutoFeatures.blockQuartzBlock ) ) { - - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.QUARTZ_BLOCK, 4 ); + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.QUARTZ_BLOCK, 4, debugInfo ); } break; case PRISMARINE_SHARD: if ( isAll || isBoolean( AutoFeatures.blockPrismarineBlock ) ) { - - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.PRISMARINE, 4 ); + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.PRISMARINE, 4, debugInfo ); } break; case SNOWBALL: if ( isAll || isBoolean( AutoFeatures.blockSnowBlock ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.SNOW_BLOCK, 4, debugInfo ); + } + break; + + case PACKED_ICE: + if ( isAll || isBoolean( AutoFeatures.blockPackedIceBlock ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.BLUE_ICE, 9, debugInfo ); + } + break; + + case BONE_MEAL: + if ( isAll || isBoolean( AutoFeatures.blockBoneBlock ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.BONE_BLOCK, 9, debugInfo ); + } + break; + + case DRIED_KELP: + if ( isAll || isBoolean( AutoFeatures.blockDriedKelpBlock ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.DRIED_KELP_BLOCK, 9, debugInfo ); + } + break; + + case WHEAT: + if ( isAll || isBoolean( AutoFeatures.blockHayBlock ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.HAY_BLOCK, 9, debugInfo ); + } + break; + + case MELON_SLICE: + if ( isAll || isBoolean( AutoFeatures.blockMelon ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.MELON, 9, debugInfo ); + } + break; + + case NETHER_WART: + if ( isAll || isBoolean( AutoFeatures.blockNetherWartBlock ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.SNOW_BLOCK, 4 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.NETHER_WART_BLOCK, 9, debugInfo ); } break; case GLOWSTONE_DUST: if ( isAll || isBoolean( AutoFeatures.blockGlowstone ) ) { - - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.GLOWSTONE, 4 ); + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.GLOWSTONE, 4, debugInfo ); } break; case LAPIS_LAZULI: if ( isAll || isBoolean( AutoFeatures.blockLapisBlock ) ) { - - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.LAPIS_BLOCK, 9 ); + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.LAPIS_BLOCK, 9, debugInfo ); + } + break; + + case RAW_COPPER: + if ( isAll || isBoolean( AutoFeatures.blockRawCopperBlock ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.RAW_COPPER_BLOCK, 9, debugInfo ); } break; case COPPER_INGOT: if ( isAll || isBoolean( AutoFeatures.blockCopperBlock ) ) { - SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.COPPER_BLOCK, 9 ); + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.COPPER_BLOCK, 9, debugInfo ); + } + break; + + + + case AMETHYST_SHARD: + if ( isAll || isBoolean( AutoFeatures.blockAmethystBlock ) ) { + + if ( includePlayerInventory ) { + SpigotUtil.getAllDroppedItemTypesFromPlayerInventory( + player, source, drop ); + } + SpigotUtil.itemStackReplaceItems( drops, source, XMaterial.AMETHYST_BLOCK, 4, debugInfo ); } break; @@ -3156,25 +3583,52 @@ private void calculateSilkTouch( PrisonMinesBlockBreakEvent pmEvent ) { List stacks = new ArrayList<>(); + Mine mine = pmEvent.getMine(); + + int preventedDrops = 0; + SpigotBlock sBlock = pmEvent.getSpigotBlock(); + PrisonBlockStatusData statsBlock = mine.getBlockStats(sBlock); String lore = null; - stacks.add( new SpigotItemStack( 1, sBlock, lore) ); + + if ( statsBlock == null || !statsBlock.isPreventDrops() ) { + + stacks.add( new SpigotItemStack( 1, sBlock, lore) ); + } + else { + preventedDrops++; + } for ( SpigotBlock spBlock : pmEvent.getExplodedBlocks() ) { - stacks.add( new SpigotItemStack( 1, spBlock, lore) ); + PrisonBlockStatusData exStatsBlock = mine.getBlockStats(sBlock); + if ( exStatsBlock == null || !exStatsBlock.isPreventDrops() ) { + + stacks.add( new SpigotItemStack( 1, spBlock, lore) ); + } + else { + preventedDrops++; + } } // Merge all of the single quantity item stacks together, then // set as the new drops: pmEvent.setBukkitDrops( mergeDrops( stacks ) ); + if ( preventedDrops > 0 ) { + + pmEvent.setPreventedDrops( pmEvent.getPreventedDrops() + preventedDrops ); + } + int count = 0; for ( SpigotItemStack sItemStack : pmEvent.getBukkitDrops() ) { count += sItemStack.getAmount(); } - String msg = String.format( "(SilkDrops: %d) " , count ); + String msg = String.format( "(SilkDrops: %d%s) " , + count, + (preventedDrops == 0 ? "" : " preventedSilkDrops: " + preventedDrops) + ); pmEvent.getDebugInfo().append( msg ); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/PrisonDebugBlockInspectorCommand.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/PrisonDebugBlockInspectorCommand.java new file mode 100644 index 000000000..7a99a5f42 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/PrisonDebugBlockInspectorCommand.java @@ -0,0 +1,46 @@ +package tech.mcprison.prison.spigot.autofeatures; + + +import tech.mcprison.prison.Prison; +import tech.mcprison.prison.commands.Command; +import tech.mcprison.prison.internal.CommandSender; +import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.spigot.autofeatures.events.PrisonDebugBlockInspector; +import tech.mcprison.prison.spigot.commands.PrisonSpigotBaseCommands; +import tech.mcprison.prison.spigot.game.SpigotPlayer; +import tech.mcprison.prison.util.Location; + +public class PrisonDebugBlockInspectorCommand + extends PrisonSpigotBaseCommands { + + + @Command( + identifier = "mines debugBlockBreak", + description = "This will debug the BlockBreakEvent chain of plugins handling the " + + "event. Look at a block, while holding the tool of choice, and then " + + "issue this command.", + altPermissions = "prison.admin", onlyPlayers = true ) + private void mineDebugBlockBreak( CommandSender sender ) { + + + PrisonDebugBlockInspector blockInspector = PrisonDebugBlockInspector.getInstance(); + + + Player player = Prison.get().getPlatform().getPlayer( sender.getPlatformPlayer().getUUID() ).orElse( null ); + + + if ( player != null && player instanceof SpigotPlayer ) { + + SpigotPlayer sPlayer = (SpigotPlayer) player; + + Location location = sPlayer.getLineOfSightExactLocation(); + + boolean isSneaking = true; + + blockInspector.debugBlockBreak( sPlayer, isSneaking, location ); + } + + + } + +} 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 79de1dcb8..d566a96ee 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 @@ -21,6 +21,7 @@ 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.InventoryFullEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; @@ -99,39 +100,38 @@ public void unregisterListeners() { } - public void initialize() { - - // Check to see if the class BlockBreakEvent even exists: - try { - - Output.get().logInfo( "AutoManager: Trying to register BlockBreakEvent" ); - - String eP = getMessage( AutoFeatures.blockBreakEventPriority ); - BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); - - setBbPriority( bbPriority ); - - - if ( getBbPriority() != BlockBreakPriority.DISABLED ) { - if ( bbPriority.isComponentCompound() ) { - - for (BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities()) { - - createListener( subBBPriority ); + public void initialize() { + + // Check to see if the class BlockBreakEvent even exists: + try { + + Output.get().logInfo( "AutoManager: Trying to register BlockBreakEvent" ); + + String eP = getMessage( AutoFeatures.blockBreakEventPriority ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + + setBbPriority( bbPriority ); + + + if ( getBbPriority() != BlockBreakPriority.DISABLED ) { + if ( bbPriority.isComponentCompound() ) { + + for ( BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities() ) { + + createListener( subBBPriority ); } - } - else { - - createListener(bbPriority); - } - - } - - } - catch ( Exception e ) { - Output.get().logInfo( "AutoManager: BlockBreakEvent failed to load. [%s]", e.getMessage() ); - } - } + } + else { + + createListener( bbPriority ); + } + + } + + } catch ( Exception e ) { + Output.get().logInfo( "AutoManager: BlockBreakEvent failed to load. [%s]", e.getMessage() ); + } + } private void createListener( BlockBreakPriority bbPriority ) { @@ -248,190 +248,180 @@ public void dumpEventListeners( StringBuilder sb ) { - /** - *

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

    - * - * @param e - * @param montior Identifies that a monitor event called this function. A monitor should only record - * block break counts. - */ + /** + *

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

    + * + * @param e + * @param montior Identifies that a monitor event called this function. A monitor should only record block break counts. + */ private void handleBlockBreakEvent( BlockBreakEvent e, BlockBreakPriority bbPriority ) { - - if ( e instanceof PrisonMinesBlockBreakEvent ) { - return; - } - + + if ( e instanceof PrisonMinesBlockBreakEvent ) { return; } + PrisonMinesBlockBreakEvent pmEvent = null; - long start = System.nanoTime(); + long start = System.nanoTime(); - // If the event is canceled, it still needs to be processed because of the + // 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 + // 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 + // 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.getBlock(), bbPriority, false ); - - if ( eventResults.isIgnoreEvent() ) { - return; - } + MinesEventResults eventResults = ignoreMinesBlockBreakEvent( e, + e.getPlayer(), e.getBlock(), bbPriority, false ); + + if ( eventResults.isIgnoreEvent() ) { return; } + - // Register all external events such as mcMMO and EZBlocks: // OnBlockBreakExternalEvents.getInstance().registerAllExternalEvents(); - + StringBuilder debugInfo = new StringBuilder(); - - debugInfo.append( String.format( "### ** handleBlockBreakEvent ** ### " + - "(event: BlockBreakEvent, config: %s, priority: %s, canceled: %s) ", + + debugInfo.append( String.format( "&6### ** handleBlockBreakEvent ** ###&3 " + + "(event: &6BlockBreakEvent&3, config: %s, priority: %s, canceled: %s) ", bbPriority.name(), bbPriority.getBukkitEventPriority().name(), - (e.isCancelled() ? "TRUE " : "FALSE") - ) ); - + ( e.isCancelled() ? "TRUE " : "FALSE" ) ) ); + debugInfo.append( eventResults.getDebugInfo() ); - - - - // Process all priorities if the event has not been canceled, and + + + // 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() ) { + if ( !bbPriority.isMonitor() && !e.isCancelled() || + bbPriority.isMonitor() ) { - // Need to wrap in a Prison block so it can be used with the mines: + // Need to wrap in a Prison block so it can be used with the mines: // SpigotBlock sBlock = SpigotBlock.getSpigotBlock(e.getBlock()); // SpigotPlayer sPlayer = new SpigotPlayer(e.getPlayer()); - - BlockEventType eventType = BlockEventType.blockBreak; - String triggered = null; - - pmEvent = new PrisonMinesBlockBreakEvent( - eventResults, + + BlockEventType eventType = BlockEventType.blockBreak; + String triggered = null; + + pmEvent = new PrisonMinesBlockBreakEvent( + eventResults, // e.getBlock(), // e.getPlayer(), // eventResults.getMine(), //// sBlock, sPlayer, // bbPriority, - eventType, - triggered, - debugInfo ); - + 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; + } + + + // 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 ); - // 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; - } - - - // 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 ) ) { - - // 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 occured already within validateEvent(): - 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 ); - } - } - - - // This is where the processing actually happens: - else { - + } + + + // Validate the event. + 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 occured already within validateEvent(): + 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 ); + } + } + + + // 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, e ); - } - - - EventListenerCancelBy cancelBy = EventListenerCancelBy.none; - - cancelBy = processPMBBEvent( pmEvent ); - - - if ( cancelBy == EventListenerCancelBy.event ) { - - e.setCancelled( true ); - debugInfo.append( "(cancelByEvent) " ); - } - else if ( cancelBy == EventListenerCancelBy.drops ) { - try - { + + // check all external events such as mcMMO and EZBlocks: + if ( e instanceof BlockBreakEvent ) { + processPMBBExternalEvents( pmEvent, e ); + } + + + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent( pmEvent ); + + + if ( cancelBy == EventListenerCancelBy.event ) { + + e.setCancelled( true ); + debugInfo.append( "(cancelByEvent) " ); + } + else if ( cancelBy == EventListenerCancelBy.drops ) { + try { e.setDropItems( false ); debugInfo.append( "(cancelByDrop) " ); - } - catch ( NoSuchMethodError e1 ) - { - String message = String.format( + } 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() ); + e1.getMessage() ); Output.get().logWarn( message ); - + AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig() .setFeature( AutoFeatures.cancelAllBlockEventBlockDrops, false ); } - } - } - + } + } + // // 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. // if ( pmEvent.getMine() != null ) { // sBlock.setPrisonBlockTypes( pmEvent.getMine().getPrisonBlockTypes() ); // } - + // // List explodedBlocks = new ArrayList<>(); // pmEvent.setExplodedBlocks( explodedBlocks ); @@ -492,79 +482,83 @@ else if ( cancelBy == EventListenerCancelBy.drops ) { // } // // } - - + + // debugInfo.append( "(normal processing completed) " ); // } // else { // // debugInfo.append( "(logic bypass) " ); // } - - - boolean isPlayerAutosellEnabled = pmEvent.getSpigotPlayer().isAutoSellEnabled( pmEvent.getDebugInfo() ); - - + + + 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, pmEvent.getDebugInfo() ); - - - - - if ( isBoolean( AutoFeatures.isForceSellAllOnInventoryWhenBukkitBlockBreakEventFires ) && - isPlayerAutosellEnabled ) { - + + + if ( pmEvent.getSpigotPlayer().isInventoryFull() ) { + + InventoryFullEvent.fireInventoryFullEvent( pmEvent.getPlayer() ); + } + + + if ( isBoolean( AutoFeatures.isForceSellAllOnInventoryWhenBukkitBlockBreakEventFires ) && + isPlayerAutosellEnabled ) { + // ( isPlayerAutosellEnabled || isPlayerAutoSellByPerm )) { - - pmEvent.getDebugInfo().append( Output.get().getColorCodeWarning()); - pmEvent.performSellAllOnPlayerInventoryLogged( "FORCED BlockBreakEvent sellall"); - pmEvent.getDebugInfo().append( Output.get().getColorCodeDebug()); - } - - if ( isBoolean( AutoFeatures.isEnabledDelayedSellAllOnInventoryWhenBukkitBlockBreakEventFires ) && - isPlayerAutosellEnabled ) { - + + pmEvent.getDebugInfo().append( Output.get().getColorCodeWarning() ); + pmEvent.performSellAllOnPlayerInventoryLogged( "FORCED BlockBreakEvent sellall" ); + pmEvent.getDebugInfo().append( Output.get().getColorCodeDebug() ); + } + + if ( isBoolean( AutoFeatures.isEnabledDelayedSellAllOnInventoryWhenBukkitBlockBreakEventFires ) && + isPlayerAutosellEnabled ) { + // ( 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 ); - } - + + 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 ); + } + } 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 2a0c9ff00..d9c2236dc 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 @@ -18,6 +18,7 @@ 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.InventoryFullEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; @@ -254,146 +255,141 @@ public void dumpEventListeners( StringBuilder sb ) { } /** - *

    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. + *

    + * 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. + *

    + * 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 handleBlastUseEvent( BlastUseEvent e, BlockBreakPriority bbPriority ) { - + PrisonMinesBlockBreakEvent pmEvent = null; long start = System.nanoTime(); - - // If the event is canceled, it still needs to be processed because of the + + // 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 + // 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 + // 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.getBlockList().get( 0 ), - bbPriority, true ); - - if ( eventResults.isIgnoreEvent() ) { - return; - } - + MinesEventResults eventResults = ignoreMinesBlockBreakEvent( e, + e.getPlayer(), e.getBlockList().get( 0 ), + bbPriority, true ); + + if ( eventResults.isIgnoreEvent() ) { return; } + StringBuilder debugInfo = new StringBuilder(); - - debugInfo.append( String.format( "### ** handleBlastUseEvent ** ### " + - "(event: BlastUseEvent, config: %s, priority: %s, canceled: %s) ", + + debugInfo.append( String.format( "&6### ** handleBlastUseEvent ** ###&3 " + + "(event: &6BlastUseEvent&3, config: %s, priority: %s, canceled: %s) ", bbPriority.name(), bbPriority.getBukkitEventPriority().name(), - (e.isCancelled() ? "TRUE " : "FALSE") - ) ); - + ( 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 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.getBlockList().size() > 0 ) { + if ( !bbPriority.isMonitor() && !e.isCancelled() || + bbPriority.isMonitor() && + e.getBlockList().size() > 0 ) { + - // Block bukkitBlock = e.getBlockList().get( 0 ); - - BlockEventType eventType = BlockEventType.CEXplosion; - String triggered = null; - - pmEvent = new PrisonMinesBlockBreakEvent( - eventResults, + BlockEventType eventType = BlockEventType.CEXplosion; + String triggered = null; + + + pmEvent = new PrisonMinesBlockBreakEvent( + eventResults, // bukkitBlock, // e.getPlayer(), // eventResults.getMine(), // bbPriority, - eventType, - triggered, - debugInfo ); - + 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 = 1; i < e.getBlockList().size(); i++ ) { - pmEvent.getUnprocessedRawBlocks().add( e.getBlockList().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) " ); - } - + // 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 ) ) { - // 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. - } - + e.setCancelled( true ); + return; + } + + for ( int i = 1; i < e.getBlockList().size(); i++ ) { + pmEvent.getUnprocessedRawBlocks().add( e.getBlockList().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. + } + + + // now process all blocks (non-monitor): + else { + + // This is where the processing actually happens: - // now process all blocks (non-monitor): - else { - - // This is where the processing actually happens: - // if ( e instanceof BlockBreakEvent ) { // processPMBBExternalEvents( pmEvent, debugInfo, e ); // } - - - - EventListenerCancelBy cancelBy = EventListenerCancelBy.none; - - cancelBy = processPMBBEvent( pmEvent ); - - // NOTE: you cannot cancel a crazy enchant's drops, so this will - // always cancel the event. - if ( cancelBy != EventListenerCancelBy.none ) { - - e.setCancelled( true ); - debugInfo.append( "(event canceled) " ); - } + + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent( pmEvent ); + + + // NOTE: you cannot cancel a crazy enchant's drops, so this will + // always cancel the event. + if ( cancelBy != EventListenerCancelBy.none ) { + + e.setCancelled( true ); + debugInfo.append( "(event canceled) " ); + } // else if ( cancelBy == EventListenerCancelBy.drops ) { // try // { @@ -415,12 +411,17 @@ else if ( pmEvent.getBbPriority().isMonitor() ) { // } // // } - } - + } + + + if ( pmEvent.getSpigotPlayer().isInventoryFull() ) { + + InventoryFullEvent.fireInventoryFullEvent( pmEvent.getPlayer() ); + } } - - printDebugInfo( pmEvent, start ); + + printDebugInfo( pmEvent, start ); } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerEntityExplodeEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerEntityExplodeEvents.java new file mode 100644 index 000000000..36d51ad07 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerEntityExplodeEvents.java @@ -0,0 +1,460 @@ +package tech.mcprison.prison.spigot.autofeatures.events; + +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +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.event.entity.EntityExplodeEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.EventExecutor; +import org.bukkit.plugin.PluginManager; + +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.InventoryFullEvent; +import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; +import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; +import tech.mcprison.prison.spigot.block.BlockBreakPriority; + +public class AutoManagerEntityExplodeEvents + extends AutoManagerFeatures + implements PrisonEventManager +{ + private BlockBreakPriority bbPriority; + + private Boolean entityExplodeEventEnabled; + + public AutoManagerEntityExplodeEvents() { + super(); + + this.entityExplodeEventEnabled = null; + } + + + public AutoManagerEntityExplodeEvents( BlockBreakPriority bbPriority ) { + super(); + + this.entityExplodeEventEnabled = null; + + 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 AutoManagerEntityExplodeEventListener + extends AutoManagerEntityExplodeEvents + implements Listener { + + public AutoManagerEntityExplodeEventListener( BlockBreakPriority bbPriority ) { + super( bbPriority ); + } + + @EventHandler(priority=EventPriority.NORMAL) + public void onBukkitEntityExplode( EntityExplodeEvent e, BlockBreakPriority bbPriority) { + + if ( isDisabled( e.getEntity().getLocation().getWorld().getName() ) || + bbPriority.isDisabled() ) { + return; + } + + handleEntityExplodeEvent( e, bbPriority ); + } + } + + + @Override + public void initialize() { + + String eP = getMessage( AutoFeatures.entityExplodeEventPriority ); + + BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + setBbPriority( bbPriority ); + +// boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + + if ( bbPriority == BlockBreakPriority.DISABLED ) { + return; + } + + try { + Output.get().logInfo( "AutoManager: checking if loaded: EntityExplodeEvents (ExcellentEnchants, and others)" ); + + // This class should always exist, since it's part of core bukkit: + Class.forName( "org.bukkit.event.entity.EntityExplodeEvent", false, + this.getClass().getClassLoader() ); + + Output.get().logInfo( "AutoManager: Trying to register EntityExplodeEvents (ExcellentEnchants, and others)" ); + + + if ( bbPriority != BlockBreakPriority.DISABLED ) { + if ( bbPriority.isComponentCompound() ) { + + for (BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities()) { + + createListener( subBBPriority ); + } + } + else { + + createListener(bbPriority); + } + + } + + + } + catch ( ClassNotFoundException e ) { + // EntityExplodeEvents (ExcellentEnchants, and others) is not loaded... so ignore. + Output.get().logInfo( "AutoManager: EntityExplodeEvents (ExcellentEnchants, and others) is not loaded" ); + } + catch ( Exception e ) { + Output.get().logInfo( "AutoManager: EntityExplodeEvents (ExcellentEnchants, and others) failed to load. [%s]", e.getMessage() ); + } + } + + + private void createListener(BlockBreakPriority bbPriority) { + + SpigotPrison prison = SpigotPrison.getInstance(); + PluginManager pm = Bukkit.getServer().getPluginManager(); + EventPriority ePriority = bbPriority.getBukkitEventPriority(); + + + AutoManagerEntityExplodeEventListener autoManagerListener = + new AutoManagerEntityExplodeEventListener( bbPriority ); + + pm.registerEvent(EntityExplodeEvent.class, autoManagerListener, ePriority, + new EventExecutor() { + public void execute(Listener l, Event e) { + + EntityExplodeEvent eeEvent = (EntityExplodeEvent) e; + + ((AutoManagerEntityExplodeEventListener)l) + .onBukkitEntityExplode( eeEvent, getBbPriority() ); + } + }, + 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.entityExplodeEventPriority ); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + + if ( !isEventEnabled ) { + return; + } + + // Check to see if the class BlastUseEvent even exists: + try { + + Class.forName( "org.bukkit.event.entity.EntityExplodeEvent", false, + this.getClass().getClassLoader() ); + + + HandlerList handlers = EntityExplodeEvent.getHandlerList(); + +// String eP = getMessage( AutoFeatures.blockBreakEventPriority ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + + dumpEventListenersCore( "EntityExplodeEvent", handlers, bbPriority, sb ); + + +// BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); +// +// +// String title = String.format( +// "BlastUseEvent (%s)", +// ( bbPriority == null ? "--none--" : bbPriority.name()) ); +// +// ChatDisplay eventDisplay = Prison.get().getPlatform().dumpEventListenersChatDisplay( +// title, +// new SpigotHandlerList( BlastUseEvent.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 ) { + // EntityExplodeEvent is not loaded... so ignore. + } + catch ( Exception e ) { + Output.get().logInfo( "AutoManager: EntityExplodeEvent failed to load. [%s]", e.getMessage() ); + } + } + + /** + *

    + * 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 handleEntityExplodeEvent( EntityExplodeEvent 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. + Entity bEntity = e.getEntity(); + Player bPlayer = bEntity instanceof Player ? (Player) bEntity : null; + + Block eBlock = e.blockList() != null && e.blockList().size() > 0 ? e.blockList().get( 0 ) : null; + + if ( bPlayer == null || eBlock == null ) { + + if ( bPlayer != null ) { + String msg = String.format( + "&dEntityExplodeEvent: player [&b%s&d] or eventBlock [&b%s&d] is null. " + + "&2Cannot process event without a player or at least one block. ", + ( bPlayer == null ? "&cnull" : bPlayer.getName() ), + ( eBlock == null ? "&cnull" : eBlock.getType().name() ) ); + Output.get().logInfo( msg ); + } + return; // Ignore the event... it's not a player. + } + + MinesEventResults eventResults = ignoreMinesBlockBreakEvent( e, + bPlayer, eBlock, + bbPriority, true ); + + if ( eventResults.isIgnoreEvent() ) { return; } + + StringBuilder debugInfo = new StringBuilder(); + + debugInfo.append( String.format( "&6### ** handleEntityExplodeEvent ** ###&3 " + + "(event: &3EntityExplodeEvent&3, 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.blockList().size() > 0 ) { + + +// Block bukkitBlock = e.getBlockList().get( 0 ); + + BlockEventType eventType = BlockEventType.EntityExplodeEvent; + 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 = 1; i < e.blockList().size(); i++ ) { + pmEvent.getUnprocessedRawBlocks().add( e.blockList().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 function. + 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. + } + + + // now process all blocks (non-monitor): + else { + + // This is where the processing actually happens: + +// if ( e instanceof BlockBreakEvent ) { +// processPMBBExternalEvents( pmEvent, debugInfo, e ); +// } + + + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent( pmEvent ); + + + // NOTE: you cannot cancel a crazy enchant's drops, so this will + // always cancel the event. + 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 ); +// } +// +// } + } + + if ( pmEvent.getSpigotPlayer().isInventoryFull() ) { + + InventoryFullEvent.fireInventoryFullEvent( pmEvent.getPlayer() ); + } + } + + printDebugInfo( pmEvent, start ); + } + + @Override + protected int checkBonusXp( Player player, Block block, ItemStack item ) { + int bonusXp = 0; + + // NOTE: This does not exist for EntityExplodeEvent. See AutoManagerCrazyEnchants for it's source code. + + return bonusXp; + } + + + public Boolean isEntityExplodeEventEnabled() { + return entityExplodeEventEnabled; + } + public void setEntityExplodeEventEnabled(Boolean entityExplodeEventEnabled) { + this.entityExplodeEventEnabled = entityExplodeEventEnabled; + } + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerEventsManager.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerEventsManager.java index d08af5abc..b75a0af42 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerEventsManager.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/autofeatures/events/AutoManagerEventsManager.java @@ -4,27 +4,11 @@ public abstract class AutoManagerEventsManager extends AutoManagerFeatures -// implements PrisonEventManager { -// private BlockBreakPriority bbPriority; public AutoManagerEventsManager() { super(); } -// public boolean isDisabled( String worldName ) { -// return Prison.get().getPlatform().isWorldExcluded( worldName ); -// } - - - -// public BlockBreakPriority getBbPriority() { -// return bbPriority; -// } -// public void setBbPriority( BlockBreakPriority bbPriority ) { -// this.bbPriority = bbPriority; -// } - - } 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 f3b5359fe..4f20a368f 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 @@ -1,6 +1,10 @@ package tech.mcprison.prison.spigot.autofeatures.events; +import java.lang.reflect.Method; +import java.util.List; + import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.Event; @@ -13,21 +17,45 @@ 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.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.InventoryFullEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; +/** + *

    This supports Pulsi's plugin, PrisonEnchants. There are three different versions + * and prison supports them all. + *

    + * + *
      + *
    • v1.x - Older versions of PEExplosionEvent. + * Uses functions: getBlockBroken() and getExplodedBlocks().
    • + *
    • v2.0.0 through v2.2.0 - Uses functions: getBlocks(). Does not + * have the original broken block.
    • + *
    • v2.2.1 + - Uses functions: getBlocks() and + * + *
    + */ public class AutoManagerPrisonEnchants extends AutoManagerFeatures implements PrisonEventManager { + private PEExplosionEventVersion peApiVersion = null; + private BlockBreakPriority bbPriority; + public enum PEExplosionEventVersion { + undefined, + pev1_0_0, + pev2_0_0, + pev2_2_1; + } + public AutoManagerPrisonEnchants() { super(); } @@ -36,6 +64,8 @@ public AutoManagerPrisonEnchants( BlockBreakPriority bbPriority ) { super(); this.bbPriority = bbPriority; + + } @@ -60,31 +90,42 @@ public void registerEvents() { * */ public class AutoManagerPEExplosiveEventListener - extends AutoManagerPrisonEnchants - implements Listener { - - public AutoManagerPEExplosiveEventListener( BlockBreakPriority bbPriority ) { - super( bbPriority ); - } - - @EventHandler(priority=EventPriority.NORMAL) - public void onPrisonEnchantsExplosiveEvent( PEExplosionEvent e, BlockBreakPriority bbPriority ) { - - if ( isDisabled( e.getBlockBroken().getLocation().getWorld().getName() ) || - bbPriority.isDisabled() ) { + extends AutoManagerPrisonEnchants + implements Listener { + + public AutoManagerPEExplosiveEventListener(BlockBreakPriority bbPriority, + PEExplosionEventVersion peApiVersion) { + super(bbPriority); + + // Setup the plugin's version: + if (peApiVersion != PEExplosionEventVersion.undefined) { + // It's already been calculated, so save it: + setPeApiVersion(peApiVersion); + } else { + // It was not properly calculated before, so figure it out and save it: + getPEPluginVersion(); + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPrisonEnchantsExplosiveEvent(PEExplosionEvent e, BlockBreakPriority bbPriority) { + + Block block = getBlock(e); + + if (isDisabled(block.getLocation().getWorld().getName()) || bbPriority.isDisabled()) { return; } - // me.pulsi_.prisonenchants.events.PEExplosionEvent - - handlePEExplosionEvent( e, bbPriority ); - + + handlePEExplosionEvent(e, bbPriority); + // genericBlockExplodeEventAutoManager( e ); } } +// @SuppressWarnings("unused") @Override public void initialize() { @@ -92,6 +133,7 @@ public void initialize() { BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); setBbPriority( bbPriority ); + //setPeApiVersion( PEExplosionEventVersion.undefined ); // boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); @@ -108,6 +150,56 @@ public void initialize() { Output.get().logInfo( "AutoManager: Trying to register Pulsi_'s PrisonEnchants" ); +// { +// // PrisonEnchants-API-v1.0.0: +// //me.pulsi_.prisonenchants.events.PEExplosionEvent +// +// PEExplosionEvent peEE = new PEExplosionEvent(); +// Block block = peEE.getBlockBroken(); +// String eventName = peEE.getEventName(); +// List explodedBlocks = peEE.getExplodedBlocks(); +// HandlerList handlers = peEE.getHandlers(); +// HandlerList handlerList = peEE.getHandlerList(); +// Player player = peEE.getPlayer(); +// boolean async = peEE.isAsynchronous(); +// boolean canceled = peEE.isCancelled(); +// peEE.setCancelled(false); +// +// } +// { +// // PrisonEnchants-API-v2.2.0: +// //me.pulsi_.prisonenchants.events.PEExplosionEvent +// +// PEExplosionEvent peEE = new PEExplosionEvent(); +// List blocks = peEE.getBlocks(); +// PEEnchant enchantSource = peEE.getEnchantSource(); // not needed +// String eventName = peEE.getEventName(); +// HandlerList handlers = peEE.getHandlers(); +// HandlerList handlerList = peEE.getHandlerList(); +// Player player = peEE.getPlayer(); +// boolean async = peEE.isAsynchronous(); +// boolean canceled = peEE.isCancelled(); +// peEE.setBlocks( blocks ); +// peEE.setCancelled(false); +// } +// { +// // PrisonEnchants-API-v2.2.1: +// //me.pulsi_.prisonenchants.events.PEExplosionEvent +// NOTE: v2.2.1 adds the function getOrigin(); +// +// Location locationOfOriginalBlock = peEE.getOrigin(); +// } + + + +// HandlerList handlerList = PEExplosionEvent.getHandlerList(); + + + getPEPluginVersion(); + + + + if ( getBbPriority() != BlockBreakPriority.DISABLED ) { if ( bbPriority.isComponentCompound() ) { @@ -134,6 +226,126 @@ public void initialize() { } } + private void getPEPluginVersion() { + Class klass = PEExplosionEvent.class; + + setPeApiVersion( PEExplosionEventVersion.undefined ); + + if ( hasMethod( "getBlockBroken", klass ) && + hasMethod( "getExplodedBlocks", klass ) ) { + + setPeApiVersion( PEExplosionEventVersion.pev1_0_0 ); + } + else if ( hasMethod( "getBlocks", klass ) && + !hasMethod( "getOrigin", klass ) ) { + + setPeApiVersion( PEExplosionEventVersion.pev2_0_0 ); + } + else if ( hasMethod( "getBlocks", klass ) && + hasMethod( "getOrigin", klass ) ) { + + setPeApiVersion( PEExplosionEventVersion.pev2_2_1 ); + } + + + String msg = ""; + if ( getPeApiVersion() == PEExplosionEventVersion.undefined ) { + msg = "&cWarning: AutoFeatures has been configured to use Pulsi's " + + "PrisonEnchant's PEExplosionEvent but the plugin is not " + + "loaded or active."; + } + else if ( getPeApiVersion() == PEExplosionEventVersion.pev2_2_1 ) { + msg = "&6PEExplosionEvent API based on v2.2.1 or newer has been found and &2successfully &6registered."; + } + else { + msg = "&6PEExplosionEvent API has been found and &2successfully &6registered, but it is " + + "out of date. &cPlease upgrade PrisonEnchants to the lastest release " + + "for best results. &6https://polymart.org/resource/prisonenchants.1434"; + } + + Output.get().logWarn( msg ); + + } + + /** + *

    Checks a Class to see if the given function exists. + * Based upon our own specific needs with this, we are just checking + * setters so no parameters need to be specified. + *

    + * + * @param methodName + * @param klass + * @return + */ + private boolean hasMethod( String methodName, Class klass ) { + boolean results = false; + + try { + Method method = klass.getMethod( methodName, (Class[]) null); + + results = ( method != null ); + } + catch (NoSuchMethodException | SecurityException e) { + // Ignore exceptions... + } + + return results; + } + + private Block getBlock( PEExplosionEvent event ) { + Block results = null; + + if ( getPeApiVersion() == null ) { + getPEPluginVersion(); + } + + if ( getPeApiVersion() == PEExplosionEventVersion.pev1_0_0 ) { + + results = event.getBlockBroken(); + } + else if ( getPeApiVersion() == PEExplosionEventVersion.pev2_0_0 ) { + + results = event.getBlocks().size() > 0 ? + event.getBlocks().get(0) : null; + } + else if ( getPeApiVersion() == PEExplosionEventVersion.pev2_2_1 ) { + + Location bLocation = event.getOrigin(); + results = bLocation.getWorld().getBlockAt(bLocation); + } + else if ( getPeApiVersion() == PEExplosionEventVersion.undefined ) { + Output.get().logWarn( "AutoManager: Pulsi_'s PrisonEnchants api version is &6undefined&3!" ); + } + + return results; + } + +// private List getBlocks( PEExplosionEvent event ) { +// List results = new ArrayList<>(); +// +// if ( getPeApiVersion() == null ) { +// getPEPluginVersion(); +// } +// +// if ( getPeApiVersion() == PEExplosionEventVersion.pev1_0_0 ) { +// +// results.addAll( event.getExplodedBlocks() ); +// } +// else if ( getPeApiVersion() == PEExplosionEventVersion.pev2_0_0 ) { +// +// results.addAll( event.getBlocks().subList(1, event.getBlocks().size())); +// } +// else if ( getPeApiVersion() == PEExplosionEventVersion.pev2_2_1 ) { +// +// results.addAll( event.getBlocks() ); +// } +// else if ( getPeApiVersion() == PEExplosionEventVersion.undefined ) { +// Output.get().logWarn( "AutoManager: Pulsi_'s PrisonEnchants api version is &6undefined&3!" ); +// } +// +// return results; +// } + private void createListener(BlockBreakPriority bbPriority) { SpigotPrison prison = SpigotPrison.getInstance(); @@ -141,7 +353,7 @@ private void createListener(BlockBreakPriority bbPriority) { EventPriority ePriority = bbPriority.getBukkitEventPriority(); AutoManagerPEExplosiveEventListener autoManagerListener = - new AutoManagerPEExplosiveEventListener( bbPriority ); + new AutoManagerPEExplosiveEventListener( bbPriority, getPeApiVersion() ); pm.registerEvent(PEExplosionEvent.class, autoManagerListener, ePriority, new EventExecutor() { @@ -159,11 +371,11 @@ public void execute(Listener l, Event e) { - @Override - public void unregisterListeners() { - + @Override + public void unregisterListeners() { + setPeApiVersion(null); // super.unregisterListeners(); - } + } @Override public void dumpEventListeners() { @@ -185,30 +397,30 @@ public void dumpEventListeners() { @Override - public void dumpEventListeners( StringBuilder sb ) { - - String eP = getMessage( AutoFeatures.PrisonEnchantsExplosiveEventPriority ); - boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + public void dumpEventListeners(StringBuilder sb) { + + String eP = getMessage(AutoFeatures.PrisonEnchantsExplosiveEventPriority); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase(eP); + + if (!isEventEnabled) { + return; + } - if ( !isEventEnabled ) { - return; - } - // Check to see if the class ExplosiveEvent even exists: try { - - Class.forName( "me.pulsi_.prisonenchants.events.PEExplosionEvent", false, - this.getClass().getClassLoader() ); - - + + Class.forName("me.pulsi_.prisonenchants.events.PEExplosionEvent", false, this.getClass().getClassLoader()); + HandlerList handlers = PEExplosionEvent.getHandlerList(); - + + // debug only: + Output.get().logInfo("PEExplosionEvent: " + handlers.getClass().getName()); + // String eP = getMessage( AutoFeatures.blockBreakEventPriority ); - BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString(eP); + + dumpEventListenersCore("Pulsi_'s PEExplosionEvent", handlers, bbPriority, sb); - dumpEventListenersCore( "Pulsi_'s PEExplosionEvent", handlers, bbPriority, sb ); - - // BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); // // String title = String.format( @@ -240,147 +452,189 @@ public void dumpEventListeners( StringBuilder sb ) { // // sb.append( msg ).append( "\n" ); // } - } - catch ( ClassNotFoundException e ) { + } catch (ClassNotFoundException e) { // PrisonEnchants is not loaded... so ignore. - } - catch ( Exception e ) { - Output.get().logInfo( "AutoManager: PrisonEnchants failed to load. [%s]", e.getMessage() ); + } catch (Exception e) { + Output.get().logInfo("AutoManager: PrisonEnchants failed to load. [%s]", e.getMessage()); } } /** - *

    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. + *

    + * 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. + *

    + * 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 handlePEExplosionEvent( PEExplosionEvent e, BlockBreakPriority bbPriority) { - + public void handlePEExplosionEvent(PEExplosionEvent e, BlockBreakPriority bbPriority) { + PrisonMinesBlockBreakEvent pmEvent = null; long start = System.nanoTime(); - - // If the event is canceled, it still needs to be processed because of the + + // 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 + // 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 + // 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.getBlockBroken(), - bbPriority, true ); - - if ( eventResults.isIgnoreEvent() ) { - return; - } - + + if (e.getBlocks().size() == 0) { + // Nothing to process: + return; + } + + // Remove all invalid blocks: + // The original collection in the event will be updated... + @SuppressWarnings("unused") + int blocksBefore = e.getBlocks().size(); + + // verified blocks: + List vBlocks = removeAllInvalidBlocks(e.getPlayer(), e.getBlocks(), bbPriority, true); + @SuppressWarnings("unused") + int blocksAfter = vBlocks.size(); + +// Output.get().logInfo( "&6 #### PEExplosionEvent: &7removeAllInvalidBlocks:&3 before: %d after: %d", +// blocksBefore, blocksAfter ); + + if (vBlocks.size() == 0) { + // No blocks are within prison mines... ignore this event. + return; + } + + // NOTE: support for v1.0, v2.2, and v2.2.1 has different block structures: + Block bBlock = getBlock(e); + + MinesEventResults eventResults = ignoreMinesBlockBreakEvent(e, e.getPlayer(), bBlock, bbPriority, true); + + // The primary block is not in the mine, or they don't have access to it, so + // ignore event: + if (eventResults.isIgnoreEvent()) { + + // But if vBlocks.size() > 0, the try the first block in that list to see if it + // will work: + if (vBlocks.size() > 0) { + bBlock = vBlocks.remove(0); + + eventResults = ignoreMinesBlockBreakEvent(e, e.getPlayer(), bBlock, bbPriority, true); + + if (eventResults.isIgnoreEvent()) { + return; + } + } else { + + return; + } + } + StringBuilder debugInfo = new StringBuilder(); - - - debugInfo.append( String.format( "### ** handlePEEExplosionEvent (Pulsi) ** ### " + - "(event: PEExplosionEvent, config: %s, priority: %s, canceled: %s) ", - bbPriority.name(), - bbPriority.getBukkitEventPriority().name(), - (e.isCancelled() ? "TRUE " : "FALSE") - ) ); - - debugInfo.append( eventResults.getDebugInfo() ); - - - // Process all priorities if the event has not been canceled, and + + debugInfo.append(String.format( + "&6### ** handlePEEExplosionEvent (Pulsi) ** ###&3 " + + "(event: &6PEExplosionEvent&3, config: %s, priority: %s, %scanceled: %s) ", + bbPriority.name(), bbPriority.getBukkitEventPriority().name(), + (e.getEventName() == null ? "" : "EventName: " + e.getEventName()), + (e.isCancelled() ? "TRUE " : "FALSE"))); + + 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() || - bbPriority.isMonitor() ) { - - - BlockEventType eventType = BlockEventType.PEExplosive; - String triggered = null; // e.getTriggeredBy(); - - pmEvent = new PrisonMinesBlockBreakEvent( - eventResults, + if (!bbPriority.isMonitor() && !e.isCancelled() || bbPriority.isMonitor()) { + + BlockEventType eventType = BlockEventType.PEExplosive; + String triggered = null; // e.getTriggeredBy(); + + pmEvent = new PrisonMinesBlockBreakEvent(eventResults, // e.getBlockBroken(), // 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; - } - - 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 - // so do nothing more. This is to just prevent normal processing from occurring. - - if ( pmEvent.isCancelOriginalEvent() ) { - - e.setCancelled( true ); - } - - debugInfo.append( "(doAction failed validation) " ); - } + eventType, triggered, debugInfo); - - - // 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. - } - + // 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; + } + +// List blocks = getBlocks( e ); + + // vBlocks have been verified to be within a mine. There may be restrictions + // that prevent them + // from being used, but they passed the first check. + pmEvent.setUnprocessedRawBlocks(vBlocks); + + // 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 function. + 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.getBlocks().clear(); + 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 { - // This is where the processing actually happens: - else { - // debugInfo.append( "(normal processing initiating) " ); - - // check all external events such as mcMMO and EZBlocks: + + // 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) " ); - } + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent(pmEvent); + + if (cancelBy != EventListenerCancelBy.none) { + + e.setCancelled(true); + debugInfo.append("(event canceled) "); + } + + e.getBlocks().clear(); + // else if ( cancelBy == EventListenerCancelBy.drops ) { // try // { @@ -402,13 +656,16 @@ else if ( pmEvent.getBbPriority().isMonitor() ) { // } // // } - } + } + if (pmEvent.getSpigotPlayer().isInventoryFull()) { + InventoryFullEvent.fireInventoryFullEvent(pmEvent.getPlayer()); + } } - - printDebugInfo( pmEvent, start ); + + printDebugInfo(pmEvent, start); } @Override @@ -417,5 +674,13 @@ protected int checkBonusXp( Player player, Block block, ItemStack item ) { return bonusXp; } - + + public PEExplosionEventVersion getPeApiVersion() { + return this.peApiVersion; + } + public void setPeApiVersion(PEExplosionEventVersion peApiVersion) { + this.peApiVersion = peApiVersion; + } + + } 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 c429dc195..014e20770 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 @@ -15,10 +15,13 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; +import tech.mcprison.prison.bombs.MineBombData; +import tech.mcprison.prison.bombs.MineBombData.BombStatus; 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.ExplosiveBlockBreakEvent; +import tech.mcprison.prison.spigot.api.InventoryFullEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; @@ -171,27 +174,25 @@ public void dumpEventListeners() { @Override - public void dumpEventListeners( StringBuilder sb ) { + public void dumpEventListeners(StringBuilder sb) { - String eP = getMessage( AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority ); - boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + String eP = getMessage(AutoFeatures.ProcessPrisons_ExplosiveBlockBreakEventsPriority); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase(eP); + + if (!isEventEnabled) { + return; + } - if ( !isEventEnabled ) { - return; - } - // Check to see if the class ExplosiveEvent even exists: try { - - + HandlerList handlers = ExplosiveBlockBreakEvent.getHandlerList(); - + // String eP = getMessage( AutoFeatures.blockBreakEventPriority ); - BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString(eP); + + dumpEventListenersCore("ExplosiveBlockBreakEvent", handlers, bbPriority, sb); - dumpEventListenersCore( "ExplosiveBlockBreakEvent", handlers, bbPriority, sb ); - - // BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); // // String title = String.format( @@ -224,193 +225,193 @@ public void dumpEventListeners( StringBuilder sb ) { // // sb.append( msg ).append( "\n" ); // } - } - catch ( Exception e ) { - Output.get().logInfo( "AutoManager: PrisonEnchants failed to load. [%s]", e.getMessage() ); + } catch (Exception e) { + Output.get().logInfo("AutoManager: PrisonEnchants failed to load. [%s]", e.getMessage()); } } - protected void handleExplosiveBlockBreakEvent( ExplosiveBlockBreakEvent e, - BlockBreakPriority bbPriority ) { - + protected void handleExplosiveBlockBreakEvent(ExplosiveBlockBreakEvent e, BlockBreakPriority bbPriority) { + PrisonMinesBlockBreakEvent pmEvent = null; long start = System.nanoTime(); - - // If the event is canceled, it still needs to be processed because of the + + MineBombData mineBomb = e.getMineBomb(); + + // 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 + // 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 + // 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.getBlock(), - bbPriority, true ); - - if ( eventResults.isIgnoreEvent() ) { + MinesEventResults eventResults = ignoreMinesBlockBreakEvent(e, e.getPlayer(), e.getBlock(), bbPriority, true); + + if (eventResults.isIgnoreEvent()) { + if (mineBomb != null) + mineBomb.setBombStatus(BombStatus.event_ignored); return; } - - + StringBuilder debugInfo = new StringBuilder(); - - debugInfo.append( String.format( "### ** handleExplosiveBlockBreakEvent (Prisons's bombs) ** ### " + - "(event: ExplosiveBlockBreakEvent, config: %s, priority: %s, canceled: %s) ", - bbPriority.name(), - bbPriority.getBukkitEventPriority().name(), - (e.isCancelled() ? "TRUE " : "FALSE") - ) ); - - debugInfo.append( eventResults.getDebugInfo() ); - - - // Process all priorities if the event has not been canceled, and + + debugInfo.append(String.format( + "&6### ** handleExplosiveBlockBreakEvent (Prisons's bombs) ** ###&3 " + + "(event: &6ExplosiveBlockBreakEvent&3, config: %s, priority: %s, canceled: %s) ", + bbPriority.name(), bbPriority.getBukkitEventPriority().name(), (e.isCancelled() ? "TRUE " : "FALSE"))); + + 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() || - bbPriority.isMonitor() ) { - - + if (!bbPriority.isMonitor() && !e.isCancelled() || bbPriority.isMonitor()) { + BlockEventType eventType = BlockEventType.PrisonExplosion; String triggered = e.getTriggeredBy(); - - pmEvent = new PrisonMinesBlockBreakEvent( - eventResults, + + pmEvent = new PrisonMinesBlockBreakEvent(eventResults, // e.getBlock(), // 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; - } - - // If this event is fired, but yet there are no exploded blocks, then do not set + 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); + if (mineBomb != null) + mineBomb.setBombStatus(BombStatus.no_access); + return; + } + + // If this event is fired, but yet there are no exploded blocks, then do not set // forceIfAirBlock to true so this event is skipped. - if ( e.getExplodedBlocks() != null && e.getExplodedBlocks().size() > 0 ) { - - pmEvent.setUnprocessedRawBlocks( e.getExplodedBlocks() ); - pmEvent.setForceIfAirBlock( e.isForceIfAirBlock() ); + if (e.getExplodedBlocks() != null && e.getExplodedBlocks().size() > 0) { + + pmEvent.setUnprocessedRawBlocks(e.getExplodedBlocks()); + pmEvent.setForceIfAirBlock(e.isForceIfAirBlock()); } - - - // Warning: toolInHand really needs to be defined in the event if the source is a - // Mine Bomb, otherwise auto features will detect the player is holding - // a mine bomb which is not a pickaxe so the drops will be ZERO. If they - // used their last mine bomb, then auto features will detect only AIR - // in their hand. - if ( e.getToolInHand() != null && e.getToolInHand() instanceof SpigotItemStack ) { - pmEvent.setItemInHand( (SpigotItemStack) e.getToolInHand() ); + + // Warning: toolInHand really needs to be defined in the event if the source is + // a + // Mine Bomb, otherwise auto features will detect the player is holding + // a mine bomb which is not a pickaxe so the drops will be ZERO. If they + // used their last mine bomb, then auto features will detect only AIR + // in their hand. + if (e.getToolInHand() != null && e.getToolInHand() instanceof SpigotItemStack) { + pmEvent.setItemInHand((SpigotItemStack) e.getToolInHand()); } - - - - // Note: If the mineBomb is set, then the bomb itself uses a pseudo - // tool in hand, so need to disable durability calculations since - // if the pseudo tool breaks, it will clear the player's in-hand - // inventory stack, which will be more mine bombs if they had more - // than one. - if ( e.getMineBomb() != null ) { - pmEvent.setCalculateDurability( false ); - + + // Note: If the mineBomb is set, then the bomb itself uses a pseudo + // tool in hand, so need to disable durability calculations since + // if the pseudo tool breaks, it will clear the player's in-hand + // inventory stack, which will be more mine bombs if they had more + // than one. + if (mineBomb != null) { + + pmEvent.setForceIfAirBlock(true); + + pmEvent.setMineBomb(mineBomb); + + pmEvent.setCalculateDurability(false); + // Set if forced autoSell: - pmEvent.setForceAutoSell( e.getMineBomb().isAutosell() ); + pmEvent.setForceAutoSell(mineBomb.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 ); - - - - pmEvent.setApplyToPlayersBlockCount( - e.getMineBomb().isApplyToPlayersBlockCount() ); - - - if ( !validateEvent( pmEvent ) ) { - - // The event has not passed validation. All logging and Errors have been recorded + + // 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 function. + removeEventTriggerBlocksFromExplosions(pmEvent); + + if (e.getMineBomb() != null) { + pmEvent.setApplyToPlayersBlockCount(e.getMineBomb().isApplyToPlayersBlockCount()); + } + + 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 ); + + if (pmEvent.isCancelOriginalEvent()) { + + e.setCancelled(true); } - - debugInfo.append( "(doAction failed validation) " ); + + if (mineBomb != null) + mineBomb.setBombStatus(BombStatus.failed_validation); + + 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 { - + // 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. + if (mineBomb != null) + mineBomb.setBombStatus(BombStatus.monitor_successful); + } + + // 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, e ); - } - - - EventListenerCancelBy cancelBy = EventListenerCancelBy.none; - - cancelBy = processPMBBEvent( pmEvent ); - - if ( cancelBy == EventListenerCancelBy.event ) { - - 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 ); - + // check all external events such as mcMMO and EZBlocks: + if (e instanceof BlockBreakEvent) { + processPMBBExternalEvents(pmEvent, e); + } + + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent(pmEvent); + + if (cancelBy == EventListenerCancelBy.event) { + + 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 ); + .setFeature(AutoFeatures.cancelAllBlockEventBlockDrops, false); } - } - } - - + } + if (mineBomb != null) + mineBomb.setBombStatus(BombStatus.successful); + } + + if (pmEvent.getSpigotPlayer().isInventoryFull()) { + + InventoryFullEvent.fireInventoryFullEvent(pmEvent.getPlayer()); + } } - - printDebugInfo( pmEvent, start ); + + printDebugInfo(pmEvent, start); } @Override 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 595c9291a..09192677d 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 @@ -18,6 +18,7 @@ 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.InventoryFullEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; @@ -252,148 +253,138 @@ public void dumpEventListeners( StringBuilder sb ) { /** - *

    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. + *

    + * 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. + *

    + * 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 handleRevEnchantsExplosiveEvent( ExplosiveEvent e, BlockBreakPriority bbPriority ) { - + public void handleRevEnchantsExplosiveEvent(ExplosiveEvent e, BlockBreakPriority bbPriority) { + PrisonMinesBlockBreakEvent pmEvent = null; long start = System.nanoTime(); - - // If the event is canceled, it still needs to be processed because of the + + // 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 + // 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 + // 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.getBlocks().get( 0 ), - bbPriority, true ); - - if ( eventResults.isIgnoreEvent() ) { + + Block bBlock = e.getBlocks().size() >= 0 ? e.getBlocks().get(0) : null; + + MinesEventResults eventResults = ignoreMinesBlockBreakEvent(e, e.getPlayer(), bBlock, bbPriority, true); + + if (eventResults.isIgnoreEvent()) { return; } - - + StringBuilder debugInfo = new StringBuilder(); - - debugInfo.append( String.format( "### ** handleRevEnchantsExplosiveEvent ** ### " + - "(event: ExplosiveEvent, 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 + + debugInfo.append(String.format( + "&6### ** handleRevEnchantsExplosiveEvent ** ###&3 " + + "(event: &6ExplosiveEvent&3, 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.getBlocks().size() > 0 ) { + if (!bbPriority.isMonitor() && !e.isCancelled() || bbPriority.isMonitor() && e.getBlocks().size() > 0) { - - // Block bukkitBlock = e.getBlocks().get( 0 ); - - BlockEventType eventType = BlockEventType.RevEnExplosion; - String triggered = null; - - pmEvent = new PrisonMinesBlockBreakEvent( - eventResults, + BlockEventType eventType = BlockEventType.RevEnExplosion; + String triggered = null; + + pmEvent = new PrisonMinesBlockBreakEvent(eventResults, // bukkitBlock, // e.getPlayer(), // eventResults.getMine(), // bbPriority, - eventType, triggered, - debugInfo ); - + 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 = 1; i < e.getBlocks().size(); i++ ) { - pmEvent.getUnprocessedRawBlocks().add( e.getBlocks().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) " ); - } + // 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; + } - // 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. - } - + for (int i = 1; i < e.getBlocks().size(); i++) { + pmEvent.getUnprocessedRawBlocks().add(e.getBlocks().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 { - - // This is where the processing actually happens: - else { - // debugInfo.append( "(normal processing initiating) " ); - - // check all external events such as mcMMO and EZBlocks: + + // 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) " ); - } + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent(pmEvent); + + if (cancelBy != EventListenerCancelBy.none) { + + e.setCancelled(true); + debugInfo.append("(event canceled) "); + } // else if ( cancelBy == EventListenerCancelBy.drops ) { // try // { @@ -415,12 +406,15 @@ else if ( pmEvent.getBbPriority().isMonitor() ) { // } // // } - } + } + if (pmEvent.getSpigotPlayer().isInventoryFull()) { + InventoryFullEvent.fireInventoryFullEvent(pmEvent.getPlayer()); + } } - - printDebugInfo( pmEvent, start ); + + printDebugInfo(pmEvent, start); } @Override 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 6af193697..46514cf1e 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 @@ -22,6 +22,7 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; +import tech.mcprison.prison.spigot.api.InventoryFullEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; @@ -260,166 +261,151 @@ public void dumpEventListeners( StringBuilder sb ) { /** - *

    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. + *

    + * 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. + *

    + * 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 handleRevEnchantsJackHammerEvent( JackHammerEvent e, BlockBreakPriority bbPriority ) { - + public void handleRevEnchantsJackHammerEvent(JackHammerEvent e, BlockBreakPriority bbPriority) { + PrisonMinesBlockBreakEvent pmEvent = null; long start = System.nanoTime(); - - // If the event is canceled, it still needs to be processed because of the + + // 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 + // 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 + // 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.getBlocks().get( 0 ), - bbPriority, true ); - - if ( eventResults.isIgnoreEvent() ) { + + Block bBlock = e.getBlocks().size() >= 0 ? e.getBlocks().get(0) : null; + + MinesEventResults eventResults = ignoreMinesBlockBreakEvent(e, e.getPlayer(), bBlock, bbPriority, true); + + if (eventResults.isIgnoreEvent()) { return; } - - + StringBuilder debugInfo = new StringBuilder(); - - debugInfo.append( String.format( "### ** handleRevEnchantsJackHammerEvent ** ### " + - "(event: JackHammerEvent, 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 + + debugInfo.append(String.format( + "&6### ** handleRevEnchantsJackHammerEvent ** ###&3 " + + "(event: &6JackHammerEvent&3, 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.getBlocks().size() > 0 ) { - - - + if (!bbPriority.isMonitor() && !e.isCancelled() || bbPriority.isMonitor() && e.getBlocks().size() > 0) { + // Block bukkitBlock = e.getBlocks().get( 0 ); - + BlockEventType eventType = BlockEventType.RevEnJackHammer; String triggered = null; - - - pmEvent = new PrisonMinesBlockBreakEvent( - eventResults, + + pmEvent = new PrisonMinesBlockBreakEvent(eventResults, // bukkitBlock, e.getPlayer(), // eventResults.getMine(), // bbPriority, - eventType, - triggered, - debugInfo ); - + 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; - } - - Location loc1 = SpigotUtil.bukkitLocationToPrison( e.getPoint1() ); - Location loc2 = SpigotUtil.bukkitLocationToPrison( e.getPoint2() ); - - List blocks = MineBombs.getInstance().calculateCube( loc1, loc2 ); - - String msg = String.format( - "(JackHammerEvent: e.blocks=%d locationBlocks=%d %s %s) ", - e.getBlocks().size(), - blocks.size(), - loc1.toWorldCoordinates(), - loc2.toWorldCoordinates() - ); - debugInfo.append( msg ); - - for (Location loc : blocks) { + // 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; + } + + Location loc1 = SpigotUtil.bukkitLocationToPrison(e.getPoint1()); + Location loc2 = SpigotUtil.bukkitLocationToPrison(e.getPoint2()); + + List blocks = MineBombs.getInstance().calculateCube(loc1, loc2); + + String msg = String.format("(JackHammerEvent: e.blocks=%d locationBlocks=%d %s %s) ", + e.getBlocks().size(), blocks.size(), loc1.toWorldCoordinates(), loc2.toWorldCoordinates()); + debugInfo.append(msg); + + for (Location loc : blocks) { SpigotBlock block = (SpigotBlock) loc.getBlockAt(); - - pmEvent.getUnprocessedRawBlocks().add( block.getWrapper() ); + + pmEvent.getUnprocessedRawBlocks().add(block.getWrapper()); } - + // for ( int i = 1; i < blocks.size(); i++ ) { // 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 ) ) { - - // The event has not passed validation. All logging and Errors have been recorded + + // 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 ); + + if (pmEvent.isCancelOriginalEvent()) { + + e.setCancelled(true); } - - debugInfo.append( "(doAction failed validation) " ); + + 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 { - + + // 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: + + // 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) " ); - } + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent(pmEvent); + + if (cancelBy != EventListenerCancelBy.none) { + + e.setCancelled(true); + debugInfo.append("(event canceled) "); + } // else if ( cancelBy == EventListenerCancelBy.drops ) { // try // { @@ -441,12 +427,15 @@ else if ( pmEvent.getBbPriority().isMonitor() ) { // } // // } - } - - + } + + if (pmEvent.getSpigotPlayer().isInventoryFull()) { + + InventoryFullEvent.fireInventoryFullEvent(pmEvent.getPlayer()); + } } - - printDebugInfo( pmEvent, start ); + + printDebugInfo(pmEvent, start); } @Override 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 5ea2ff076..0568c5a93 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 @@ -19,6 +19,7 @@ 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.InventoryFullEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; @@ -82,48 +83,42 @@ public void onTEBlockExplode( TEBlockExplodeEvent e, BlockBreakPriority bbPriori } - @Override - public void initialize() { + @Override + public void initialize() { + + String eP = getMessage(AutoFeatures.TokenEnchantBlockExplodeEventPriority); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString(eP); + + setBbPriority(bbPriority); - String eP = getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ); - 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 TEBlockExplodeEvent even exists: - try { - Output.get().logInfo( "AutoManager: checking if loaded: TokenEnchant" ); - - Class.forName( "com.vk2gpz.tokenenchant.event.TEBlockExplodeEvent", false, - this.getClass().getClassLoader() ); - - Output.get().logInfo( "AutoManager: Trying to register TokenEnchant" ); - - - if ( getBbPriority() != BlockBreakPriority.DISABLED ) { - if ( bbPriority.isComponentCompound() ) { - - for (BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities()) { - - createListener( subBBPriority ); + if (getBbPriority() == BlockBreakPriority.DISABLED) { + return; + } + + // Check to see if the class TEBlockExplodeEvent even exists: + try { + Output.get().logInfo("AutoManager: checking if loaded: TokenEnchant"); + + Class.forName("com.vk2gpz.tokenenchant.event.TEBlockExplodeEvent", false, this.getClass().getClassLoader()); + + Output.get().logInfo("AutoManager: Trying to register TokenEnchant"); + + if (getBbPriority() != BlockBreakPriority.DISABLED) { + if (bbPriority.isComponentCompound()) { + + for (BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities()) { + + createListener(subBBPriority); } - } - else { - - createListener(bbPriority); - } - - } - - - - + } else { + + createListener(bbPriority); + } + + } + // BlockBreakPriority eventPriority = BlockBreakPriority.fromString( eP ); // // if ( eventPriority != BlockBreakPriority.DISABLED ) { @@ -182,18 +177,16 @@ public void initialize() { // prison); // prison.getRegisteredBlockListeners().add( normalListenerMonitor ); // } - + // } - - } - catch ( ClassNotFoundException e ) { - // TokenEnchant is not loaded... so ignore. - Output.get().logInfo( "AutoManager: TokenEnchant is not loaded" ); - } - catch ( Exception e ) { - Output.get().logInfo( "AutoManager: TokenEnchant failed to load. [%s]", e.getMessage() ); - } - } + + } catch (ClassNotFoundException e) { + // TokenEnchant is not loaded... so ignore. + Output.get().logInfo("AutoManager: TokenEnchant is not loaded"); + } catch (Exception e) { + Output.get().logInfo("AutoManager: TokenEnchant failed to load. [%s]", e.getMessage()); + } + } private void createListener( BlockBreakPriority bbPriority ) { @@ -243,32 +236,28 @@ public void dumpEventListeners() { } - @Override - public void dumpEventListeners( StringBuilder sb ) { - - String eP = getMessage( AutoFeatures.TokenEnchantBlockExplodeEventPriority ); - boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + @Override + public void dumpEventListeners(StringBuilder sb) { + + String eP = getMessage(AutoFeatures.TokenEnchantBlockExplodeEventPriority); + boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase(eP); + + if (!isEventEnabled) { + return; + } - if ( !isEventEnabled ) { - return; - } - // Check to see if the class TEBlockExplodeEvent even exists: try { - - Class.forName( "com.vk2gpz.tokenenchant.event.TEBlockExplodeEvent", false, - this.getClass().getClassLoader() ); - - + + Class.forName("com.vk2gpz.tokenenchant.event.TEBlockExplodeEvent", false, this.getClass().getClassLoader()); + HandlerList handlers = TEBlockExplodeEvent.getHandlerList(); - + // String eP = getMessage( AutoFeatures.blockBreakEventPriority ); - BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString(eP); + + dumpEventListenersCore("BlockBreakEvent", handlers, bbPriority, sb); - dumpEventListenersCore( "BlockBreakEvent", handlers, bbPriority, sb ); - - - // BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); // // String title = String.format( @@ -300,156 +289,143 @@ public void dumpEventListeners( StringBuilder sb ) { // // sb.append( msg ).append( "\n" ); // } - } - catch ( ClassNotFoundException e ) { + } catch (ClassNotFoundException e) { // TokenEnchant is not loaded... so ignore. - } - catch ( Exception e ) { - Output.get().logInfo( "AutoManager: TokenEnchant failed to load. [%s]", e.getMessage() ); + } catch (Exception e) { + Output.get().logInfo("AutoManager: TokenEnchant failed to load. [%s]", e.getMessage()); } } /** - *

    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. + *

    + * 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. + *

    + * 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 handleTEBlockExplodeEvent( TEBlockExplodeEvent e, BlockBreakPriority bbPriority ) { - + public void handleTEBlockExplodeEvent(TEBlockExplodeEvent e, BlockBreakPriority bbPriority) { + PrisonMinesBlockBreakEvent pmEvent = null; long start = System.nanoTime(); - - // If the event is canceled, it still needs to be processed because of the + + // 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 + // 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 + // 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.getBlock(), bbPriority, true ); - - if ( eventResults.isIgnoreEvent() ) { - return; - } + MinesEventResults eventResults = ignoreMinesBlockBreakEvent(e, e.getPlayer(), e.getBlock(), bbPriority, true); + + if (eventResults.isIgnoreEvent()) { + return; + } - StringBuilder debugInfo = new StringBuilder(); - - debugInfo.append( String.format( "### ** genericBlockExplodeEvent ** ### " + - "(event: TEBlockExplodeEvent, config: %s, priority: %s, canceled: %s) ", - bbPriority.name(), - bbPriority.getBukkitEventPriority().name(), - (e.isCancelled() ? "TRUE " : "FALSE") - ) ); - - debugInfo.append( eventResults.getDebugInfo() ); - - - // Process all priorities if the event has not been canceled, and + + debugInfo.append(String.format( + "&6### ** genericBlockExplodeEvent ** ###&3 " + + "(event: &6TEBlockExplodeEvent&3, config: %s, priority: %s, canceled: %s) ", + bbPriority.name(), bbPriority.getBukkitEventPriority().name(), (e.isCancelled() ? "TRUE " : "FALSE"))); + + 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() || - bbPriority.isMonitor() ) { + if (!bbPriority.isMonitor() && !e.isCancelled() || bbPriority.isMonitor()) { + BlockEventType eventType = BlockEventType.TEXplosion; + String triggered = checkTEBlockExplodeEventTriggered(e); - BlockEventType eventType = BlockEventType.TEXplosion; - String triggered = checkTEBlockExplodeEventTriggered( e ); - - pmEvent = new PrisonMinesBlockBreakEvent( - eventResults, + pmEvent = new PrisonMinesBlockBreakEvent(eventResults, // e.getBlock(), // 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; - } - - - // NOTE: Token Enchant will pass the event's block to prison, but that block may - // have already been processed by prison. Therefore the PrisonMinesBlockBreakEvent - // must enable the feature setForceIfAirBlock( true ). That block will not be used a - // second time, but it will allow the explosion event to be processed. - pmEvent.setForceIfAirBlock( true ); - - 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 - // 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 { - + 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; + } + + // NOTE: Token Enchant will pass the event's block to prison, but that block may + // have already been processed by prison. Therefore the + // PrisonMinesBlockBreakEvent + // must enable the feature setForceIfAirBlock( true ). That block will not be + // used a + // second time, but it will allow the explosion event to be processed. + pmEvent.setForceIfAirBlock(true); + + 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 + // 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: + + // 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) " ); - } + + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent(pmEvent); + + if (cancelBy != EventListenerCancelBy.none) { + + e.setCancelled(true); + debugInfo.append("(event canceled) "); + } // else if ( cancelBy == EventListenerCancelBy.drops ) { // try // { @@ -471,12 +447,15 @@ else if ( pmEvent.getBbPriority().isMonitor() ) { // } // // } - } - - - } - - printDebugInfo( pmEvent, start ); + } + + if (pmEvent.getSpigotPlayer().isInventoryFull()) { + + InventoryFullEvent.fireInventoryFullEvent(pmEvent.getPlayer()); + } + } + + printDebugInfo(pmEvent, start); } private String checkTEBlockExplodeEventTriggered( TEBlockExplodeEvent e ) 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 index 758d082b0..38ffe1e50 100644 --- 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 @@ -18,6 +18,7 @@ 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.InventoryFullEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; @@ -295,8 +296,8 @@ public void handleXPrisonExplosionTriggerEvent( ExplosionTriggerEvent e, BlockBr StringBuilder debugInfo = new StringBuilder(); - debugInfo.append( String.format( "### ** handleXPrisonExplosionTriggerEvent ** ### " + - "(event: ExplosionTriggerEvent, config: %s, priority: %s, canceled: %s) ", + debugInfo.append( String.format( "&6### ** handleXPrisonExplosionTriggerEvent ** ###&3 " + + "(event: &6ExplosionTriggerEvent&3, config: %s, priority: %s, canceled: %s) ", bbPriority.name(), bbPriority.getBukkitEventPriority().name(), (e.isCancelled() ? "TRUE " : "FALSE") @@ -427,7 +428,10 @@ else if ( pmEvent.getBbPriority().isMonitor() ) { // } } - + if ( pmEvent.getSpigotPlayer().isInventoryFull() ) { + + InventoryFullEvent.fireInventoryFullEvent( pmEvent.getPlayer() ); + } } printDebugInfo( pmEvent, start ); 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 index 6043f5a2b..7102cef38 100644 --- 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 @@ -18,6 +18,7 @@ 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.InventoryFullEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; @@ -187,31 +188,29 @@ public void dumpEventListeners() { } -@Override -public void dumpEventListeners( StringBuilder sb ) { - - String eP = getMessage( AutoFeatures.XPrisonLayerTriggerEventPriority ); - boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + @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(); - 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 ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString(eP); + + dumpEventListenersCore("XPrison LayerTriggerEvent", handlers, bbPriority, sb); - dumpEventListenersCore( "XPrison LayerTriggerEvent", handlers, bbPriority, sb ); - - // // BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); // @@ -245,166 +244,150 @@ public void dumpEventListeners( StringBuilder sb ) { // // 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); + } } - 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 ) { + /** + *

    + * 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( + "&6### ** handleXPrisonLayerTriggerEvent ** ###&3 " + + "(event: &6LayerTriggerEvent&3, 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, + BlockEventType eventType = BlockEventType.XPrisonLayerTriggerEvent; + String triggered = null; + + pmEvent = new PrisonMinesBlockBreakEvent(eventResults, // bukkitBlock, // e.getPlayer(), // eventResults.getMine(), // bbPriority, - eventType, triggered, - debugInfo ); - + 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 ); - + // 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)) { - - 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 ); + e.setCancelled(true); + return; } - - pmEvent.setDebugColorCodeWarning(); - debugInfo.append( "(doAction failed validation) " ); - pmEvent.setDebugColorCodeDebug(); - } - + for (int i = 0; i < e.getBlocksAffected().size(); i++) { + pmEvent.getUnprocessedRawBlocks().add(e.getBlocksAffected().get(i)); + } - // 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. - } - + // 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 { - - // This is where the processing actually happens: - else { - // debugInfo.append( "(normal processing initiating) " ); - - // check all external events such as mcMMO and EZBlocks: + + // 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) " ); - } + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent(pmEvent); + + if (cancelBy != EventListenerCancelBy.none) { + + e.setCancelled(true); + debugInfo.append("(event canceled) "); + } // else if ( cancelBy == EventListenerCancelBy.drops ) { // try // { @@ -426,13 +409,16 @@ else if ( pmEvent.getBbPriority().isMonitor() ) { // } // // } - } + } + + if (pmEvent.getSpigotPlayer().isInventoryFull()) { + InventoryFullEvent.fireInventoryFullEvent(pmEvent.getPlayer()); + } + } + printDebugInfo(pmEvent, start); } - - printDebugInfo( pmEvent, start ); -} @Override protected int checkBonusXp( Player player, Block block, ItemStack item ) { 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 index 2185fc3d5..75023641c 100644 --- 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 @@ -18,200 +18,176 @@ 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.InventoryFullEvent; 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 -{ +public class AutoManagerXPrisonNukeTriggerEvent extends AutoManagerFeatures implements PrisonEventManager { - // private ExplosionTriggerEvent ete; // private LayerTriggerEvent lte; // private NukeTriggerEvent nte; - - //dev.drawethree.xprison.enchants.api.events.NukeTriggerEvent; - - - + + // dev.drawethree.xprison.enchants.api.events.NukeTriggerEvent; + private BlockBreakPriority bbPriority; - + public AutoManagerXPrisonNukeTriggerEvent() { super(); } - - public AutoManagerXPrisonNukeTriggerEvent( BlockBreakPriority bbPriority ) { + + public AutoManagerXPrisonNukeTriggerEvent(BlockBreakPriority bbPriority) { super(); - + this.bbPriority = bbPriority; } - - + public BlockBreakPriority getBbPriority() { return bbPriority; } - public void setBbPriority( BlockBreakPriority bbPriority ) { + + public void setBbPriority(BlockBreakPriority bbPriority) { this.bbPriority = bbPriority; } - + @Override public void registerEvents() { - - if ( AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled) ) { - + + if (AutoFeaturesWrapper.getInstance().isBoolean(AutoFeatures.isAutoManagerEnabled)) { + initialize(); } } + public class AutoManagerXPrisonNukeTriggerEventListener extends AutoManagerXPrisonNukeTriggerEvent + implements Listener { -public class AutoManagerXPrisonNukeTriggerEventListener - extends AutoManagerXPrisonNukeTriggerEvent - implements Listener { - - public AutoManagerXPrisonNukeTriggerEventListener( BlockBreakPriority bbPriority ) { - super( bbPriority ); - } - - @EventHandler(priority=EventPriority.NORMAL) - public void onXPrisonNukeTriggerEvent( - NukeTriggerEvent e, BlockBreakPriority bbPriority) { + public AutoManagerXPrisonNukeTriggerEventListener(BlockBreakPriority bbPriority) { + super(bbPriority); + } - if ( isDisabled( e.getPlayer().getLocation().getWorld().getName() ) || - bbPriority.isDisabled() ) { - return; + @EventHandler(priority = EventPriority.NORMAL) + public void onXPrisonNukeTriggerEvent(NukeTriggerEvent e, BlockBreakPriority bbPriority) { + + if (isDisabled(e.getPlayer().getLocation().getWorld().getName()) || bbPriority.isDisabled()) { + return; + } + + handleXPrisonNukeTriggerEvent(e, bbPriority); } - - handleXPrisonNukeTriggerEvent( e, bbPriority ); } -} + @Override + public void initialize() { -@Override -public void initialize() { + String eP = getMessage(AutoFeatures.XPrisonNukeTriggerEventPriority); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString(eP); + + setBbPriority(bbPriority); - 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 ); + + 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); } + } - 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()); } } - 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); } -} - -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() { -@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 = new StringBuilder(); + + dumpEventListeners(sb); -@Override -public void dumpEventListeners( StringBuilder sb ) { - - String eP = getMessage( AutoFeatures.XPrisonNukeTriggerEventPriority ); - boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + if (sb.length() > 0) { + + for (String line : sb.toString().split("\n")) { + + Output.get().logInfo(line); + } + } - 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(); - + + @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 ); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString(eP); + + dumpEventListenersCore("XPrison NukeTriggerEvent", handlers, bbPriority, sb); - dumpEventListenersCore( "XPrison NukeTriggerEvent", handlers, bbPriority, sb ); - - // // BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); // @@ -245,166 +221,147 @@ public void dumpEventListeners( StringBuilder sb ) { // // 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); + } } - 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 ) { - - - + + /** + *

    + * 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( + "&6### ** handleXPrisonNukeTriggerEvent ** ###&3 " + + "(event: &6NukeTriggerEvent&3, 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, + 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 ); + 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; } - - debugInfo.append( "(doAction failed validation) " ); - } - + for (int i = 0; i < e.getBlocksAffected().size(); i++) { + pmEvent.getUnprocessedRawBlocks().add(e.getBlocksAffected().get(i)); + } - // 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. - } - + // 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 { - - // This is where the processing actually happens: - else { - // debugInfo.append( "(normal processing initiating) " ); - - // check all external events such as mcMMO and EZBlocks: + + // 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) " ); - } + + EventListenerCancelBy cancelBy = EventListenerCancelBy.none; + + cancelBy = processPMBBEvent(pmEvent); + + if (cancelBy != EventListenerCancelBy.none) { + + e.setCancelled(true); + debugInfo.append("(event canceled) "); + } // else if ( cancelBy == EventListenerCancelBy.drops ) { // try // { @@ -426,18 +383,21 @@ else if ( pmEvent.getBbPriority().isMonitor() ) { // } // // } - } + } + + if (pmEvent.getSpigotPlayer().isInventoryFull()) { + InventoryFullEvent.fireInventoryFullEvent(pmEvent.getPlayer()); + } + } + printDebugInfo(pmEvent, start); } - - printDebugInfo( pmEvent, start ); -} @Override - protected int checkBonusXp( Player player, Block block, ItemStack item ) { + 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 23bfb8643..8f31265c3 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 @@ -18,6 +18,7 @@ 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.InventoryFullEvent; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; import tech.mcprison.prison.spigot.autofeatures.AutoManagerFeatures; import tech.mcprison.prison.spigot.block.BlockBreakPriority; @@ -65,68 +66,61 @@ public AutoManagerBlockShredEventListener( BlockBreakPriority bbPriority ) { super( bbPriority ); } - @EventHandler(priority=EventPriority.NORMAL) - public void onBlockShredBreak( BlockShredEvent e, BlockBreakPriority bbPriority ) { - - if ( isDisabled( e.getBlock().getLocation().getWorld().getName() ) ) { + @EventHandler(priority = EventPriority.NORMAL) + public void onBlockShredBreak(BlockShredEvent e, BlockBreakPriority bbPriority) { + + if (isDisabled(e.getBlock().getLocation().getWorld().getName())) { return; } - - handleZenchantmentsBlockBreakEvent( e, bbPriority ); - -// genericBlockEventAutoManager( e ); - } + + handleZenchantmentsBlockBreakEvent(e, bbPriority); + + } } - @Override - public void initialize() { - - String eP = getMessage( AutoFeatures.ZenchantmentsBlockShredEventPriority ); - BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); - - setBbPriority( bbPriority ); - -// boolean isEventEnabled = eP != null && !"DISABLED".equalsIgnoreCase( eP ); + @Override + public void initialize() { - if ( getBbPriority() == BlockBreakPriority.DISABLED ) { - return; - } - - // Check to see if the class BlastUseEvent even exists: - try { - Output.get().logInfo( "AutoManager: checking if loaded: Zenchantments" ); - - Class.forName( "zedly.zenchantments.BlockShredEvent", false, - this.getClass().getClassLoader() ); - - Output.get().logInfo( "AutoManager: Trying to register Zenchantments" ); - - if ( getBbPriority() != BlockBreakPriority.DISABLED ) { - if ( bbPriority.isComponentCompound() ) { - - for (BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities()) { - - createListener( subBBPriority ); + String eP = getMessage(AutoFeatures.ZenchantmentsBlockShredEventPriority); + BlockBreakPriority bbPriority = BlockBreakPriority.fromString(eP); + + setBbPriority(bbPriority); + + if (getBbPriority() == BlockBreakPriority.DISABLED) { + return; + } + + // Check to see if the class BlastUseEvent even exists: + try { + Output.get().logInfo("AutoManager: checking if loaded: Zenchantments"); + + Class.forName("zedly.zenchantments.BlockShredEvent", false, this.getClass().getClassLoader()); + + Output.get().logInfo("AutoManager: Trying to register Zenchantments"); + + if (getBbPriority() != BlockBreakPriority.DISABLED) { + if (bbPriority.isComponentCompound()) { + + for (BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities()) { + + createListener(subBBPriority); } - } - else { - - createListener(bbPriority); - } - - } - - } - catch ( ClassNotFoundException e ) { - // Zenchantments is not loaded... so ignore. - Output.get().logInfo( "AutoManager: Zenchantments is not loaded" ); - } - catch ( Exception e ) { - Output.get().logInfo( "AutoManager: Zenchantments failed to load. [%s]", e.getMessage() ); - } - } + } else { + + createListener(bbPriority); + } + + } + + } catch (ClassNotFoundException e) { + // Zenchantments is not loaded... so ignore. + Output.get().logInfo("AutoManager: Zenchantments is not loaded"); + } catch (Exception e) { + Output.get().logInfo("AutoManager: Zenchantments failed to load. [%s]", e.getMessage()); + } + } private void createListener( BlockBreakPriority bbPriority ) { @@ -197,9 +191,8 @@ public void dumpEventListeners( StringBuilder sb ) { this.getClass().getClassLoader() ); - HandlerList handlers = BlockShredEvent.getHandlerList(); + HandlerList handlers = BlockShredEvent.getHandlerList(); -// String eP = getMessage( AutoFeatures.blockBreakEventPriority ); BlockBreakPriority bbPriority = BlockBreakPriority.fromString( eP ); dumpEventListenersCore( "BlockBreakEvent", handlers, bbPriority, sb ); @@ -284,8 +277,8 @@ private void handleZenchantmentsBlockBreakEvent( BlockBreakEvent e, BlockBreakPr StringBuilder debugInfo = new StringBuilder(); - debugInfo.append( String.format( "### ** handleZenchantmentsBlockBreakEvent ** ### " + - "(event: BlockBreakEvent, config: %s, priority: %s, canceled: %s) ", + debugInfo.append( String.format( "&6### ** handleZenchantmentsBlockBreakEvent ** ###&3 " + + "(event: &6BlockBreakEvent&3, config: %s, priority: %s, canceled: %s) ", bbPriority.name(), bbPriority.getBukkitEventPriority().name(), (e.isCancelled() ? "TRUE " : "FALSE") @@ -400,7 +393,10 @@ else if ( cancelBy == EventListenerCancelBy.drops ) { } } - + if ( pmEvent.getSpigotPlayer().isInventoryFull() ) { + + InventoryFullEvent.fireInventoryFullEvent( pmEvent.getPlayer() ); + } } printDebugInfo( pmEvent, start ); 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 0ddd9ffd0..32a8450d4 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 @@ -17,7 +17,6 @@ import tech.mcprison.prison.internal.events.player.PrisonPlayerInteractEvent; import tech.mcprison.prison.mines.data.Mine; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.selection.SelectionManager; import tech.mcprison.prison.spigot.block.OnBlockBreakMines; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; @@ -26,14 +25,12 @@ import tech.mcprison.prison.util.Location; public class PrisonDebugBlockInspector -// extends OnBlockBreakMines { private static PrisonDebugBlockInspector instance; private OnBlockBreakMines obbMines; private long lastAccess = 0; -// private boolean active = false; public enum EventDropsStatus { normal, @@ -67,500 +64,282 @@ private void init() { Prison.get().getEventBus().register(this); - -// // Check to see if the class BlockBreakEvent even exists: -// try { -// -// Output.get().logInfo( "AutoManager: Trying to register PrisonDebugBlockInspector" ); -// -// -// -// -// -// if ( getBbPriority() != BlockBreakPriority.DISABLED ) { -// if ( bbPriority.isComponentCompound() ) { -// -// for (BlockBreakPriority subBBPriority : bbPriority.getComponentPriorities()) { -// -// createListener( subBBPriority ); -// } -// } -// else { -// -// createListener(bbPriority); -// } -// -// } -// -// } -// catch ( Exception e ) { -// Output.get().logInfo( "AutoManager: BlockBreakEvent failed to load. [%s]", e.getMessage() ); -// } } - @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; + @Subscribe + public void onPlayerInteract(PrisonPlayerInteractEvent e) { - if ( ourItem == null || !ourItem.equals(toolItem) || !Output.get().isDebug() ) { - return; - } - //e.setCanceled(true); + // 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 = ItemStack.SELECTION_WAND; + + if (ourItem == null || ourItem.getMaterial().compareTo(toolItem.getMaterial()) != 0 + || !Output.get().isDebug()) { + return; + } + + SpigotPlayer player = (SpigotPlayer) e.getPlayer(); + + boolean isSneaking = player.isSneaking(); + + Location location = e.getClicked(); + + debugBlockBreak(player, isSneaking, location); + + } + + public void debugBlockBreak(SpigotPlayer player, boolean isSneaking, Location location) { + + List output = new ArrayList<>(); + + SpigotBlock sBlock = (SpigotBlock) location.getBlockAt(); + + // Get the mine, and if in a mine, then get the target block: + Mine mine = obbMines.findMine(player.getWrapper(), sBlock, null, null); + + MineTargetPrisonBlock targetBlock = null; + + if (mine == null) { + + output.add(String.format("-&dDebugBlockInfo: &7Not in a mine. &5%s &7%s", sBlock.getBlockName(), + location.toWorldCoordinates())); + + } else { + + targetBlock = mine.getTargetPrisonBlock(sBlock); + + if (targetBlock != null && obbMines.isBlockAMatch(targetBlock, sBlock)) { + // Match ... PrisonBlockType and blockName was updated in isBlockAMatch(): + } - SpigotPlayer player = (SpigotPlayer) e.getPlayer(); - - boolean isSneaking = player.isSneaking(); - - Location location = e.getClicked(); - SpigotBlock sBlock = (SpigotBlock) location.getBlockAt(); - -// UUID playerUUID = e.getPlayer().getUUID(); -// Mine mine = obbMines.findMine( playerUUID, sBlock, null, null ); - - // Get the mine, and if in a mine, then get the target block: - Mine mine = obbMines.findMine( player.getWrapper(), sBlock, null, null ); - - MineTargetPrisonBlock targetBlock = null; - - if ( mine == null ) { - - output.add( - String.format( - "-&dDebugBlockInfo: &7Not in a mine. &5%s &7%s", - sBlock.getBlockName(), location.toWorldCoordinates()) ); - - } - else { - - targetBlock = mine.getTargetPrisonBlock( sBlock ); - - if ( targetBlock != null && obbMines.isBlockAMatch( targetBlock, sBlock ) ) { - // Match ... PrisonBlockType and blockName was updated in isBlockAMatch(): - } - // // Check if it's a custom block, if it is, then change PrisonBlockType and blockName: // checkForCustomBlock( sBlock, targetBlock ); - - String m1 = String.format( - "-&dDebugBlockInfo: &3Mine &7%s &3Rank: &7%s " + - "&5%s &7%s ", - mine.getName(), - (mine.getRank() == null ? "---" : mine.getRank().getName()), - sBlock.getBlockName(), - location.toWorldCoordinates()); - - output.add( m1 ); -// player.sendMessage( m1 ); -// Output.get().logInfo( m1 ); - + + String m1 = String.format("-&dDebugBlockInfo: &3Mine &7%s &3Rank: &7%s " + "&5%s &7%s ", mine.getName(), + (mine.getRank() == null ? "---" : mine.getRank().getName()), sBlock.getBlockName(), + location.toWorldCoordinates()); + + output.add(m1); + // Get the mine's targetBlock: // MineTargetPrisonBlock tBlock = mine.getTargetPrisonBlock( sBlock ); - if ( targetBlock == null ) { - - - 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 &3Counted: &7%b", - targetBlock.getPrisonBlock().getBlockName(), - (targetBlock.isMined() ? "&d" : "&2"), - targetBlock.isMined(), - targetBlock.isAirBroke(), - targetBlock.isCounted() - ); - - output.add( message ); -// player.sendMessage( message ); -// Output.get().logInfo( message ); - - String message2 = String.format( "- &3isEdge: &7%b " + - "&3Exploded: %s%b &3IgnoreAllEvents: &7%b", - - targetBlock.isEdge(), - (targetBlock.isExploded() ? "&d" : "&2"), - targetBlock.isExploded(), - targetBlock.isIgnoreAllBlockEvents() - ); - - output.add( message2 ); -// player.sendMessage( message2 ); -// Output.get().logInfo( message2 ); - - } - } - - - if ( !isSneaking ) { - output.add( - String.format( - " &d(&7Sneak to test BlockBreakEvent with block.&d)" - ) ); - } - - else { -// player.sendMessage( -// String.format( -// "&dDebugBlockInfo: &7Sneak enabled! Block testing coming soon..." -// ) ); - - // Debug the block break events: - - 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 ); + if (targetBlock == null) { + + 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 &3Counted: &7%b", + targetBlock.getPrisonBlock().getBlockName(), (targetBlock.isMined() ? "&d" : "&2"), + targetBlock.isMined(), targetBlock.isAirBroke(), targetBlock.isCounted()); + + output.add(message); + + String message2 = String.format("- &3isEdge: &7%b " + "&3Exploded: %s%b &3IgnoreAllEvents: &7%b", + + targetBlock.isEdge(), (targetBlock.isExploded() ? "&d" : "&2"), targetBlock.isExploded(), + targetBlock.isIgnoreAllBlockEvents()); + + output.add(message2); + + } } - - - -// if (e.getAction() == PrisonPlayerInteractEvent.Action.LEFT_CLICK_BLOCK) { -// // Set first position -// Selection sel = Prison.get().getSelectionManager().getSelection(e.getPlayer()); -// sel.setMin(e.getClicked()); -// Prison.get().getSelectionManager().setSelection(e.getPlayer(), sel); -// e.getPlayer() -// .sendMessage("&7First position set to &8" + e.getClicked().toBlockCoordinates()); -// -// checkForEvent(e.getPlayer(), sel); -// } else if (e.getAction() == PrisonPlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { -// // Set second position -// Selection sel = Prison.get().getSelectionManager().getSelection(e.getPlayer()); -// sel.setMax(e.getClicked()); -// Prison.get().getSelectionManager().setSelection(e.getPlayer(), sel); -// e.getPlayer() -// .sendMessage("&7Second position set to &8" + e.getClicked().toBlockCoordinates()); -// -// checkForEvent(e.getPlayer(), sel); -// } - - // disable active prior to exiting function: - //this.active = false; - } + if (!isSneaking) { + output.add(String.format(" &d(&7Sneak to test BlockBreakEvent with block.&d)")); + } + + else { + + 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); + } + + // disable active prior to exiting function: + // this.active = false; + + } - public void dumpBlockBreakEvent( SpigotPlayer player, SpigotBlock sBlock, MineTargetPrisonBlock targetBlock, - List output ) { -// List output = new ArrayList<>(); - - SpigotBlock checkBlock = sBlock; - -// -// // Get the mine, and if in a mine, then get the target block: -// Mine mine = obbMines.findMine( player.getWrapper(), sBlock, null, null ); -// -// MineTargetPrisonBlock targetBlock = null; -// if ( mine != null ) { -// -// targetBlock = mine.getTargetPrisonBlock( sBlock ); -// } -// -// -// // Check if it's a custom block: -// checkForCustomBlock( checkBlock, targetBlock ); -// - - // Save the item held in the player's hand, which should be the prison wand: - org.bukkit.inventory.ItemStack heldItem = SpigotCompatibility.getInstance().getItemInMainHand( player.getWrapper() ); - - BlockBreakEvent bbe = new BlockBreakEvent( sBlock.getWrapper(), player.getWrapper() ); - - String blockName = checkBlock.getBlockName().toLowerCase(); - - boolean useShovel = blockName.matches( - "^clay$|farmland|grass_block|dirt|gravel|mycelium|" + - "podzol|^sand$|^red_sand$|soul_sand|soul_soil|" + - "concrete_powder|^snow$|snow_block|powder_snow" ); - + public void dumpBlockBreakEvent(SpigotPlayer player, SpigotBlock sBlock, MineTargetPrisonBlock targetBlock, + List output) { + + SpigotBlock checkBlock = sBlock; + + // Save the item held in the player's hand, which should be the prison wand: + org.bukkit.inventory.ItemStack heldItem = SpigotCompatibility.getInstance() + .getItemInMainHand(player.getWrapper()); + + BlockBreakEvent bbe = new BlockBreakEvent(sBlock.getWrapper(), player.getWrapper()); + + String blockName = checkBlock.getBlockName().toLowerCase(); + + boolean useShovel = blockName.matches("^clay$|farmland|grass_block|dirt|gravel|mycelium|" + + "podzol|^sand$|^red_sand$|soul_sand|soul_soil|" + "concrete_powder|^snow$|snow_block|powder_snow"); + // XMaterial. - - boolean useAxe = blockName.matches( - "wood$|acacia|birch|jungle|spruce|leaves|crimson|" + - "sapling|bamboo|ladder|vine|bed$|fence|chest$|" + - "table|bookshelf|jack_o_lantern|^melon$|^pumpkn$|" + - "sign|^cocoa$|mushroom_block|note_block|campfire|" + - "banner|beehive|loom|barrel|jukebox|composter|" + - "daylight_detector" - ); - -// boolean isLeaves = blockName.contains( "leaves" ); -// boolean isWood = blockName.matches( "wood|log|planks|sapling" ); - - - SpigotItemStack tool = useShovel ? - new SpigotItemStack( XMaterial.DIAMOND_SHOVEL.parseItem() ) : - ( useAxe ? - new SpigotItemStack( XMaterial.DIAMOND_AXE.parseItem() ) : - new SpigotItemStack( XMaterial.DIAMOND_PICKAXE.parseItem() - ) ); - - - // Temporaily put the tool in the player's hand: - SpigotCompatibility.getInstance().setItemInMainHand( player.getWrapper(), tool.getBukkitStack() ); - - - //String blockName = sBlk.getBlockName(); - - - output.add( - String.format( "&dBlockBreakEvent Dump: &7%s &3%s", - checkBlock.getBlockName(), - checkBlock.getLocation().toBlockCoordinates() - ) ); - - output.add( - String.format( " &3Tool Used for drops: &2%s", - tool.getName() - ) ); - - - 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(); -// } - + boolean useAxe = blockName.matches("wood$|acacia|birch|jungle|spruce|leaves|crimson|" + + "sapling|bamboo|ladder|vine|bed$|fence|chest$|" + "table|bookshelf|jack_o_lantern|^melon$|^pumpkn$|" + + "sign|^cocoa$|mushroom_block|note_block|campfire|" + "banner|beehive|loom|barrel|jukebox|composter|" + + "daylight_detector"); + + ItemStack ourItem = new SpigotItemStack(heldItem); + ItemStack toolItem = ItemStack.SELECTION_WAND; + + boolean isMineWand = ourItem != null && ourItem.getMaterial().compareTo(toolItem.getMaterial()) == 0; + + // If what is being held is not a mine wand, then use what is being held: + SpigotItemStack tool = !isMineWand ? (SpigotItemStack) ourItem + : useShovel ? new SpigotItemStack(XMaterial.DIAMOND_SHOVEL.parseItem()) + : (useAxe ? new SpigotItemStack(XMaterial.DIAMOND_AXE.parseItem()) + : new SpigotItemStack(XMaterial.DIAMOND_PICKAXE.parseItem())); + + // Temporaily put the tool in the player's hand: + SpigotCompatibility.getInstance().setItemInMainHand(player.getWrapper(), tool.getBukkitStack()); + + output.add(String.format("&dBlockBreakEvent Dump: &7%s &3%s", checkBlock.getBlockName(), + checkBlock.getLocation().toBlockCoordinates())); + + output.add(String.format(" &3Tool Used for drops: &2%s", tool.getName())); + + 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 { + + start = System.nanoTime(); + listener.callEvent(bbe); + stop = System.nanoTime(); + + } catch (EventException e) { + output.add(String.format(" &cError calling event: &3%s &2[%s]", listener.getPlugin().getName(), + e.getMessage())); + } - catch ( EventException e ) { - output.add( - String.format( " &cError calling event: &3%s &2[%s]", - listener.getPlugin().getName(), - e.getMessage() - ) ); + double durationNano = (stop - start); + + if (durationNano > 0) { + durationNano = durationNano / 1_000_000; } - - 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, durationNano ); - - } - - - // 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 ); -// } - } + + printEventStatus(bbe, listener.getPlugin().getName(), listener.getPriority().name(), checkBlock, + targetBlock, tool, output, player, durationNano); + + } + + // Put the heldItem back in the player's hand, which should be the prison wand: + SpigotCompatibility.getInstance().setItemInMainHand(player.getWrapper(), heldItem); + + } -// private void checkForCustomBlock( SpigotBlock checkBlock, MineTargetPrisonBlock targetBlock ) { -// -// // USE OnBlockBreakMines.isBlockAMatch() instead of this one... -// -// if ( targetBlock != null && targetBlock.getPrisonBlock().getBlockType() == PrisonBlockType.CustomItems ) { -// -// List cbIntegrations = -// PrisonAPI.getIntegrationManager().getCustomBlockIntegrations(); -// -// for ( CustomBlockIntegration customBlock : cbIntegrations ) -// { -// PrisonBlock ciPBlock = customBlock.getCustomBlock( checkBlock ); -// -// if ( ciPBlock != null ) { -// -// checkBlock.setBlockType( ciPBlock.getBlockType() ); -// checkBlock.setBlockName( ciPBlock.getBlockName() ); -// -// break; -// } -// } -// } -// } - private void printEventStatus( BlockBreakEvent bbe, - String plugin, String priority, - SpigotBlock sBlock, - MineTargetPrisonBlock targetBlock, - SpigotItemStack tool, - List output, - SpigotPlayer player, - double durationNano ) { - - StringBuilder sb = new StringBuilder(); - StringBuilder sb2 = new StringBuilder(); - sb.append( " " ); - - boolean isCanceled = bbe.isCancelled(); - EventDropsStatus isDropCanceled = isDropCanceled( bbe ); - String dropStats = "&7" + isDropCanceled.name(); - if ( isDropCanceled == EventDropsStatus.canceled ) { - dropStats = "&4" + isDropCanceled.name(); - } - else if ( isDropCanceled == EventDropsStatus.notSupported ) { - dropStats = "&dNS"; // + isDropCanceled.name(); - } - - // Get a fresh copy of the block to ensure we pickup the latest status: - SpigotBlock sBlk = (SpigotBlock) sBlock.getLocation().getBlockAt(); + private void printEventStatus(BlockBreakEvent bbe, String plugin, String priority, SpigotBlock sBlock, + MineTargetPrisonBlock targetBlock, SpigotItemStack tool, List output, SpigotPlayer player, + double durationNano) { + + StringBuilder sb = new StringBuilder(); + StringBuilder sb2 = new StringBuilder(); + sb.append(" "); + + boolean isCanceled = bbe.isCancelled(); + EventDropsStatus isDropCanceled = isDropCanceled(bbe); + String dropStats = "&7" + isDropCanceled.name(); + if (isDropCanceled == EventDropsStatus.canceled) { + dropStats = "&4" + isDropCanceled.name(); + } else if (isDropCanceled == EventDropsStatus.notSupported) { + dropStats = "&dNS"; // + isDropCanceled.name(); + } + + // Get a fresh copy of the block to ensure we pickup the latest status: + SpigotBlock sBlk = (SpigotBlock) sBlock.getLocation().getBlockAt(); + + List bukkitDrops = new ArrayList<>(); + obbMines.collectBukkitDrops(bukkitDrops, targetBlock, tool, sBlk, player); + bukkitDrops = obbMines.mergeDrops(bukkitDrops); + + SpigotBlock eventBlock = SpigotBlock.getSpigotBlock(bbe.getBlock()); + String eventBlockName = eventBlock == null ? "&4none" : eventBlock.getBlockNameFormal(); + + // Build the drops listing: + if (bukkitDrops.size() > 0) { - List bukkitDrops = new ArrayList<>(); - obbMines.collectBukkitDrops( bukkitDrops, targetBlock, tool, sBlk, player ); - bukkitDrops = obbMines.mergeDrops( bukkitDrops ); - - - SpigotBlock eventBlock = SpigotBlock.getSpigotBlock( bbe.getBlock() ); - String eventBlockName = eventBlock == null ? - "&4none" : - eventBlock.getBlockNameFormal(); - - - // Build the drops listing: - if ( bukkitDrops.size() > 0 ) { - // List drops = sBlk.getDrops( tool ); - for ( ItemStack itemStack : bukkitDrops ) - { -// SpigotItemStack sis = (SpigotItemStack) itemStack; - - sb2.append( " &b" ).append( itemStack.getName() ); - if ( itemStack.getAmount() > 0 ) { - sb2.append( "&a(&b" ).append( itemStack.getAmount() ).append( "&a)" ); - } - } - } - else { - sb2.append( "&4none" ); - } - - - 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() ); + for (ItemStack itemStack : bukkitDrops) { - -// sb.setLength( 0 ); - + sb2.append(" &b").append(itemStack.getName()); + if (itemStack.getAmount() > 0) { + sb2.append("&a(&b").append(itemStack.getAmount()).append("&a)"); + } + } + } else { + sb2.append("&4none"); + } -// 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 ); -// } - - } + 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()); + + } - private EventDropsStatus isDropCanceled( BlockBreakEvent bbe ) { - EventDropsStatus results = EventDropsStatus.normal; - - try { - if ( !bbe.isDropItems() ) { + private EventDropsStatus isDropCanceled(BlockBreakEvent bbe) { + EventDropsStatus results = EventDropsStatus.normal; + + try { + if (!bbe.isDropItems()) { results = EventDropsStatus.canceled; - } - else { + } else { results = EventDropsStatus.normal; } - } - catch ( NoSuchMethodError e ) { - // ignore.... not supported in this version of spigot: - results = EventDropsStatus.notSupported; - } - catch ( Exception e ) { + } catch (NoSuchMethodError e) { + // ignore.... not supported in this version of spigot: + results = EventDropsStatus.notSupported; + } catch (Exception e) { // ignore.... not supported in this version of spigot: results = EventDropsStatus.notSupported; } - - return results; - } + + return results; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java index 1140f941a..0d4cb278e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/backpacks/BackpacksUtil.java @@ -23,20 +23,25 @@ import com.cryptomorin.xseries.XMaterial; import tech.mcprison.prison.Prison; -import tech.mcprison.prison.gui.PrisonCoreGuiMessages; +import tech.mcprison.prison.backpacks.PrisonCoreBackpackMessages; import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.SpigotUtil; 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.game.SpigotPlayer; +import tech.mcprison.prison.spigot.inventory.SpigotInventory; +import tech.mcprison.prison.spigot.sellall.SellAllData; +import tech.mcprison.prison.spigot.sellall.SellAllUtil; /** * @author GABRYCA * */ public class BackpacksUtil - extends PrisonCoreGuiMessages { + extends PrisonCoreBackpackMessages { + private boolean enabled = false; + private static BackpacksUtil instance; private Configuration backpacksConfig = SpigotPrison.getInstance().getBackpacksConfig(); private File backpacksFile = new File(SpigotPrison.getInstance().getDataFolder() + "/backpacks/backpacksData.yml"); @@ -46,15 +51,70 @@ public class BackpacksUtil private final Compatibility compat = SpigotCompatibility.getInstance(); private final int backpackDefaultSize = Integer.parseInt(backpacksConfig.getString("Options.BackPack_Default_Size")); - /** - * Check if Backpacks's enabled. - * */ - public static boolean isEnabled(){ - if (SpigotPrison.getInstance().getConfig().getString("backpacks") != null){ - return SpigotPrison.getInstance().getConfig().getString("backpacks").equalsIgnoreCase("true"); + + private BackpacksUtil() { + super(); + + + String backpackConfig = SpigotPrison.getInstance().getConfig().getString("backpacks"); + + this.enabled = backpackConfig != null && + backpackConfig.equalsIgnoreCase("true"); + + } + + + public static BackpacksUtil getInstance() { + if (instance == null ){ + instance = new BackpacksUtil(); } - return false; + + return instance; } + + +// /** +// * Check if Backpacks's enabled. +// * */ +// public static boolean isPrisonBackpacksEnabled(){ +// +// return getInstance().isEnabled(); +// } + + + public boolean isEnabled() { + return enabled; + } + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + + @Override + public boolean hasIntegrated() { + return isEnabled(); + } + + /** + * Remove reference to Prison backpacks and then get a new instance, which will basically + * be similar to reloading the integration. + */ + @Override + public void disableIntegration() { + + + } + + @Override + public String getDisplayName() + { + return super.getDisplayName(); + } + + @Override + public String getPluginSourceURL() { + return "These backpacks are a part of prison."; + } /** * Get Backpacks DATA config. @@ -94,7 +154,7 @@ public boolean reachedBackpacksLimit(Player p){ } /** - * Get SellAll instance. + * Get Backpack instance. * */ public static BackpacksUtil get() { return getInstance(); @@ -754,13 +814,15 @@ private boolean backpacksLimitSet(OfflinePlayer p, int limit) { // backpacksConfig = bpTemp.getFileBackpacksConfig(); // } - private static BackpacksUtil getInstance() { - if (instance == null && SpigotPrison.getInstance().getConfig().getString("backpacks") != null && SpigotPrison.getInstance().getConfig().getString("backpacks").equalsIgnoreCase("true")){ - instance = new BackpacksUtil(); - } - - return instance; - } + + // This NEEDS to be at the top of the class... it's that important. +// private static BackpacksUtil getInstance() { +// if (instance == null && SpigotPrison.getInstance().getConfig().getString("backpacks") != null && SpigotPrison.getInstance().getConfig().getString("backpacks").equalsIgnoreCase("true")){ +// instance = new BackpacksUtil(); +// } +// +// return instance; +// } private boolean checkOwnBackpack(Player p) { updateCachedBackpack(); @@ -1587,4 +1649,28 @@ private Player getOnlinePlayer(String name, String id) { } return null; } + + public List sellInventoryItems( Player player, double multiplier ) { + List soldItems = new ArrayList<>(); + + + if ( isEnabled() ) { + + // WARNING! This is WRONG! There is no way to tell what are valid IDs. + // So just using null for auto sell. Players may not want + // some backpacks to be used by autosell. And some players may + // want more than one backpack to autosell? + String id = null; + + Inventory inv = getBackpackOwn( player, id ); + + SpigotInventory sInventory = new SpigotInventory( inv ); + + soldItems.addAll( SellAllUtil.get().sellInventoryItems( sInventory, multiplier ) ); + + saveInventory(player, inv, id); + } + + return soldItems; + } } 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 30d12655c..06f6977ff 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 @@ -42,7 +42,7 @@ public abstract class OnBlockBreakEventCore // The two variables, uses and usesElapsedTimeNano, are designed to better understand // how frequently this class is used and it's impact on the server. It's is disabled - // but not deleted since it is useful for future useage. + // but not deleted since it is useful for future usage. // private int uses = 0; // private long usesElapsedTimeNano = 0L; @@ -70,29 +70,6 @@ public enum EventDetails { public boolean isDisabled( String worldName ) { return Prison.get().getPlatform().isWorldExcluded( worldName ); } - -// /** -// *

    The Prison Mines module must be enabled, or these BlockBreakEvents should -// * not be enabled since they are geared to work with the prison mines. -// *

    -// * -// *

    At this time, prison's block handling is not supported outside of the mines. -// *

    -// * -// * @return -// */ -// public boolean isEnabled() { -// boolean results = false; -// -// Optional mmOptional = Prison.get().getModuleManager().getModule( PrisonMines.MODULE_NAME ); -// if ( mmOptional.isPresent() && mmOptional.get().isEnabled() ) { -// PrisonMines prisonMines = (PrisonMines) mmOptional.get(); -// -// results = prisonMines != null; -// } -// -// return results; -// } public AutoFeaturesFileConfig getAutoFeaturesConfig() { return autoFeatureWrapper.getAutoFeaturesConfig(); @@ -118,28 +95,6 @@ protected List getListString( AutoFeatures feature ) { return autoFeatureWrapper.getListString( feature ); } - - -// public enum ItemLoreCounters { -// -// // NOTE: the String value must include a trailing space! -// -// itemLoreBlockBreakCount( ChatColor.LIGHT_PURPLE + "Prison Blocks Mined:" + -// ChatColor.GRAY + " "), -// -// itemLoreBlockExplodeCount( ChatColor.LIGHT_PURPLE + "Prison Blocks Exploded:" + -// ChatColor.GRAY + " "); -// -// -// private final String lore; -// ItemLoreCounters( String lore ) { -// this.lore = lore; -// } -// public String getLore() { -// return lore; -// } -// -// } public enum ItemLoreEnablers { Pickup, @@ -149,22 +104,43 @@ public enum ItemLoreEnablers { } - - - + /** + *

    The purpose of this function is to "quickly" evaluate if this event should be used, + * canceled, or ignored. Ignoring the event will mean that other plugins, and the originator + * of the event, can process EVERYTHING normally. If the event is canceled, then some plugins + * may then ignore the whole event, but some may also process it in some way or another. Prison + * uses canceled events to track block breakage when other plugins are handling the breaks. + *

    + * + * @param event The event we're monitoring and processing + * @param player The player that caused the event by mining or breaking blocks + * @param block The "target" block that was initially broke by the player. Note that sometimes + * this is not the actual block, since the event does not preserve that information. + * @param bbPriority The priority that prison was listening at for this event. + * @param ignoreBlockReuse If set to true, then if the block was already counted, then prison + * will still process the blocks. Otherwise if the block has been already counted, then + * prison will ignore the event, which can have a huge impact if it's an explosion and + * there are many other blocks that "should" be processed, but ignoring the whole event + * would be skipping a lot of block processing. + * @return + */ protected MinesEventResults ignoreMinesBlockBreakEvent( Cancellable event, Player player, Block block, BlockBreakPriority bbPriority, boolean ignoreBlockReuse ) { + + String eventName = event.getClass().getSimpleName(); MinesEventResults eventResults = ignoreMinesBlockBreakEvent( player, block, bbPriority, ignoreBlockReuse ); + eventResults.setEventName( eventName ); if ( eventResults.isCancelEvent() ) { event.setCancelled( eventResults.isCancelEvent() ); } -// return eventResults.isIgnoreEvent(); + eventResults.logDebugInfo(); + return eventResults; } @@ -188,7 +164,6 @@ protected MinesEventResults ignoreMinesBlockBreakEvent( ExplosiveEvent event, Pl if ( eventResults.isCancelEvent() ) { event.setCancelled( eventResults.isCancelEvent() ); } -// return eventResults.isIgnoreEvent(); return eventResults; } @@ -202,7 +177,6 @@ protected MinesEventResults ignoreMinesBlockBreakEvent( JackHammerEvent event, P if ( eventResults.isCancelEvent() ) { event.setCancelled( eventResults.isCancelEvent() ); } -// return eventResults.isIgnoreEvent(); return eventResults; } @@ -216,7 +190,6 @@ protected MinesEventResults ignoreMinesBlockBreakEvent( PEExplosionEvent event, if ( eventResults.isCancelEvent() ) { event.setCancelled( eventResults.isCancelEvent() ); } -// return eventResults.isIgnoreEvent(); return eventResults; } @@ -237,11 +210,14 @@ protected void doBlockEvents( PrisonMinesBlockBreakEvent pmEvent ) if ( pmEvent.getMine() != null ) { + int blockEventsRan = 0; + // Count the blocks that were mined: countBlocksMined( pmEvent, pmEvent.getTargetBlock() ); // process the prison blockEvents commands: - processPrisonBlockEventCommands( pmEvent, pmEvent.getTargetBlock() ); + blockEventsRan += + processPrisonBlockEventCommands( pmEvent, pmEvent.getTargetBlock() ); for ( MineTargetPrisonBlock teBlock : pmEvent.getTargetExplodedBlocks() ) { @@ -250,13 +226,27 @@ protected void doBlockEvents( PrisonMinesBlockBreakEvent pmEvent ) countBlocksMined( pmEvent, teBlock ); // process the prison blockEvents commands: - processPrisonBlockEventCommands( pmEvent, teBlock ); + blockEventsRan += + processPrisonBlockEventCommands( pmEvent, teBlock ); + } + + if ( blockEventsRan > 0 ) { + pmEvent.getDebugInfo().append( " (&bBlockEvents&3:" ) + .append( blockEventsRan ) + .append( ")" ); } - checkZeroBlockReset( pmEvent.getMine() ); + + if ( pmEvent.getMine().checkZeroBlockReset() ) { + + pmEvent.getDebugInfo().append( " (&dMine Reset was triggered&3)"); + } // Check Mine Sweeper: - checkMineSweeper( pmEvent.getMine() ); + if ( pmEvent.getMine().submitMineSweeperTask() ) { + + pmEvent.getDebugInfo().append( " (&dMineSweeper was submitted&3)"); + } } } @@ -267,6 +257,10 @@ protected void finalizeBreakTheBlocks( PrisonMinesBlockBreakEvent pmEvent ) if ( isBoolean( AutoFeatures.applyBlockBreaksThroughSyncTask ) ) { AutoManagerBreakBlockTask.submitTask( blocks, pmEvent.getMine() ); + + pmEvent.getDebugInfo().append( " (&bbreakBlocks&3:submitTask:" ) + .append( blocks.size() ) + .append( ")" ); } else { @@ -283,23 +277,31 @@ protected void finalizeBreakTheBlocks( PrisonMinesBlockBreakEvent pmEvent ) spigotBlock.setPrisonBlock( PrisonBlock.AIR ); } + pmEvent.getDebugInfo().append( " (&bbreakBlocks&3:" ) + .append( count ) + .append( ":finished)" ); } - + } + + private List finalizeBreakTheBlocksCollectEm( PrisonMinesBlockBreakEvent pmEvent ) { List blocks = new ArrayList<>(); - if ( pmEvent.getTargetBlock() != null && pmEvent.getTargetBlock().getMinedBlock() != null ) { + MineTargetPrisonBlock tBlock = pmEvent.getTargetBlock(); + + if ( tBlock != null && tBlock.getMinedBlock() != null && + tBlock.getPrisonBlock() != null && + tBlock.getPrisonBlock().getBlockName() != null ) { SpigotBlock minedBlock = ((SpigotBlock) pmEvent.getTargetBlock().getMinedBlock()); // Only add the minedBlock to the blocks list if it matches the expected targetBlock name, which // indicates it has not been replaced by something else, such as the result of a block event. - if ( pmEvent.getTargetBlock().getPrisonBlock().getBlockName().equalsIgnoreCase( minedBlock.getBlockName() )) { + if ( tBlock.getPrisonBlock().getBlockName().equalsIgnoreCase( minedBlock.getBlockName() )) { blocks.add( minedBlock ); - pmEvent.getTargetBlock().setAirBroke( true ); -// pmEvent.getTargetBlock().setMinedBlock( null ); + tBlock.setAirBroke( true ); } } @@ -316,7 +318,6 @@ private List finalizeBreakTheBlocksCollectEm( PrisonMinesBlockBreak blocks.add( minedBlock ); targetBlock.setAirBroke( true ); -// targetBlock.setMinedBlock( null ); } } @@ -371,7 +372,7 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) StringBuilder debugInfo = pmEvent.getDebugInfo(); - debugInfo.append( "{br}|| validateEvent:: " ); + debugInfo.append( "{br}|| validateEvent:: " ); SpigotBlock sBlockHit = pmEvent.getSpigotBlock(); @@ -391,6 +392,13 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) debugInfo.append( "itemInHand=[" + ( itemInHand == null ? "AIR" : itemInHand.getDebugInfo()) + "] "); + boolean validateBlocksWerePlacedByPrison = isBoolean( AutoFeatures.validateBlocksWerePlacedByPrison ); + if ( !validateBlocksWerePlacedByPrison ) { + pmEvent.setDebugColorCodeWarning(); + debugInfo.append( "(TargetBlock match requirement is disabled [validateBlocksWerePlacedByPrison: false]) " ); + pmEvent.setDebugColorCodeDebug(); + } + // Since BlastUseEvent (crazy enchant) does not identify the block that is initially // broke, an explosion for them is greater than 1. @@ -399,7 +407,10 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) boolean hasOriginalBLockIncluded = pmEvent.getBlockEventType() == BlockEventType.CEXplosion || pmEvent.getBlockEventType() == BlockEventType.RevEnExplosion || - pmEvent.getBlockEventType() == BlockEventType.RevEnJackHammer; + pmEvent.getBlockEventType() == BlockEventType.RevEnJackHammer || + pmEvent.getBlockEventType() == BlockEventType.EntityExplodeEvent || + pmEvent.getBlockEventType() == BlockEventType.PEExplosive + ; boolean isExplosionEvent = pmEvent.getUnprocessedRawBlocks().size() > (hasOriginalBLockIncluded ? 0 : 1); @@ -411,6 +422,7 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) int monitorNotAir = 0; int noTargetBlock = 0; int blockTypeNotExpected = 0; + int preventedDrops = 0; boolean targetBlockAlreadyMined = false; @@ -438,7 +450,8 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) // If MONITOR or BLOCKEVENTS or etc... and block does not match, and if the block is AIR, // and the block has not been mined before, then allow the breakage by // setting bypassMatchedBlocks to true to allow normal processing: - if ( !matchedBlocks && + if ( !validateBlocksWerePlacedByPrison || + !matchedBlocks && targetBlock != null && !targetBlock.isMined() && sBlockHit.isAir() && @@ -477,7 +490,7 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) // NOTE: for the primary block pmEvent.getSpigotBlock() the unbreakable will be checked later: if ( targetBlock != null && sBlockHit != null ) { - if ( !targetBlock.isMined() || !targetBlock.isAirBroke() ) { + if ( !validateBlocksWerePlacedByPrison || !targetBlock.isMined() || !targetBlock.isAirBroke() ) { // The field isMined() is used to "reserve" a block to indicate that it is in // the stages of being processed, since much later in the processing will the @@ -491,9 +504,19 @@ protected boolean validateEvent( PrisonMinesBlockBreakEvent pmEvent ) if ( pbBlockHit != null && (matchedBlocks || !matchedBlocks && bypassMatchedBlocks )) { - - // Confirmed the block is correct... so get the drops... - collectBukkitDrops( pmEvent.getBukkitDrops(), targetBlock, pmEvent.getItemInHand(), sBlockHit, pmEvent.getSpigotPlayer() ); + + if ( pbTargetBlock != null && pbTargetBlock.isPreventDrops() ) { + + debugInfo.append( " &dPreventDrops:&b" ) + .append( pbTargetBlock.getBlockName() ) + .append( " " ); + preventedDrops++; + } + else { + + // Confirmed the block is correct... so get the drops... + collectBukkitDrops( pmEvent.getBukkitDrops(), targetBlock, pmEvent.getItemInHand(), sBlockHit, pmEvent.getSpigotPlayer() ); + } // If a chain reaction on explosions, this will prevent the same block from // being processed more than once: @@ -633,13 +656,13 @@ else if ( pmEvent.getBbPriority().isMonitor() && sBlockMined.isEmpty() && noTargetBlock++; } - else if ( targetExplodedBlock.isMined() ) { + else if ( validateBlocksWerePlacedByPrison && targetExplodedBlock.isMined() ) { alreadyMined++; } else { - if ( !targetExplodedBlock.isMined() ) { + if ( !validateBlocksWerePlacedByPrison || !targetExplodedBlock.isMined() ) { // Check to make sure the block is the same block that was placed there. // If not, then do not process it. @@ -652,8 +675,19 @@ else if ( targetExplodedBlock.isMined() ) { ( matchedExplodedBlocks || !matchedExplodedBlocks && bypassMatchedBlocks ) ) { - // Confirmed the block is correct... so get the drops... - collectBukkitDrops( pmEvent.getBukkitDrops(), targetExplodedBlock, pmEvent.getItemInHand(), sBlockMined, pmEvent.getSpigotPlayer() ); + if ( pBlockMined != null && pBlockMined.isPreventDrops() ) { + + debugInfo.append( " &dPreventDrops:&b" ) + .append( pBlockMined.getBlockName() ) + .append( " " ); + preventedDrops++; + } + else { + + // Confirmed the block is correct... so get the drops... + collectBukkitDrops( pmEvent.getBukkitDrops(), targetExplodedBlock, pmEvent.getItemInHand(), sBlockMined, pmEvent.getSpigotPlayer() ); + } + // If a chain reaction on explosions, this will prevent the same block from // being processed more than once: @@ -748,6 +782,15 @@ else if ( targetExplodedBlock.isMined() ) { pmEvent.setDebugColorCodeDebug(); } + if ( preventedDrops > 0 ) { + + // The prevented drops will be added to total drops later in the processing to + // confirm if the whole event was successful or not. + pmEvent.setPreventedDrops( preventedDrops ); + + debugInfo.append( "TOTAL_PreventedDrops (" + preventedDrops + " ) " ); + } + // Need to compress the drops to eliminate duplicates: pmEvent.setBukkitDrops( mergeDrops( pmEvent.getBukkitDrops() ) ); @@ -930,16 +973,6 @@ else if ( results && pmEvent.getBbPriority().isMonitor() && mine != null ) { boolean isPlayerAutosellEnabled = pmEvent.getSpigotPlayer().isAutoSellEnabled( pmEvent.getDebugInfo() ); -// (!sellAllUtil.isAutoSellPerUserToggleable || -// sellAllUtil.isSellallPlayerUserToggleEnabled( -// pmEvent.getPlayer() )); - - -// boolean isPlayerAutoSellByPerm = pmEvent.getSpigotPlayer() -// .isAutoSellByPermEnabled( isPlayerAutosellEnabled, pmEvent.getDebugInfo() ); - - - // AutoSell on full inventory when using BLOCKEVENTS: if ( isBoolean( AutoFeatures.isAutoSellIfInventoryIsFullForBLOCKEVENTSPriority ) && @@ -1015,23 +1048,6 @@ else if ( results && pmEvent.getBbPriority().isMonitor() && mine != null ) { } -// if ( results ) { -// // Collect the bukkit drops && cancel the drops if needed -// -// collectBukkitDrops( pmEvent.getBukkitDrops(), pmEvent.getTargetBlock(), -// pmEvent.getItemInHand() ); -// -// for ( MineTargetPrisonBlock targetBlock : pmEvent.getTargetExplodedBlocks() ) -// { -// collectBukkitDrops( pmEvent.getBukkitDrops(), targetBlock, -// pmEvent.getItemInHand() ); -// -// } -// -// // Need to compress the drops to eliminate duplicates: -// pmEvent.setBukkitDrops( mergeDrops( pmEvent.getBukkitDrops() ) ); -// } - if ( results ) { debugInfo.append( "(PassedValidation) " ); @@ -1043,86 +1059,11 @@ else if ( results && pmEvent.getBbPriority().isMonitor() && mine != null ) { } -// debugInfo.append( "{br}|| " ); - return results; } -// private boolean collectBukkitDrops( List bukkitDrops, MineTargetPrisonBlock targetBlock, -// SpigotItemStack itemInHand, SpigotBlock sBlockMined ) -// { -// boolean results = false; -// -//// if ( sBlockMined == null && targetBlock.getMinedBlock() != null ) { -//// sBlockMined = (SpigotBlock) targetBlock.getMinedBlock(); -//// } -// //SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); -// -// if ( sBlockMined != null && targetBlock.getPrisonBlock().equals( sBlockMined.getPrisonBlock() ) ) { -// -// List drops = SpigotUtil.getDrops(sBlockMined, itemInHand); -// -// bukkitDrops.addAll( drops ); -// -//// // This clears the drops for the given block, so if the event is not canceled, it will -//// // not result in duplicate drops. -//// if ( isBoolean( AutoFeatures.cancelAllBlockEventBlockDrops ) ) { -//// sBlock.clearDrops(); -//// } -// -// results = true; -// -// } -// else if ( sBlockMined != null) { -// Output.get().logWarn( "collectBukkitDrops: block was changed and not what was expected. " + -// "Block: " + sBlockMined.getBlockName() + " expecting: " + targetBlock.getPrisonBlock().getBlockName() ); -// } -// -// return results; -// } - - -// private void clearBukkitDrops( List bukkitDrops, MineTargetPrisonBlock targetBlock ) -// { -// -// SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); -// sBlock.clearDrops(); -// -// } - -// /** -// *

    The List of drops must have only one ItemStack per block type (name). -// * This function combines multiple occurrences together and adds up their -// * counts to properly represent the total quantity in the original drops collection -// * that had duplicate entries. -// *

    -// * -// * @param List of SpigotItemStack drops with duplicate entries -// * @return List of SpigotItemStack drops without duplicates -// */ -// private List mergeDrops( List drops ) -// { -// TreeMap results = new TreeMap<>(); -// -// for ( SpigotItemStack drop : drops ) { -// String key = drop.getName(); -// if ( !results.containsKey( key ) ) { -// results.put( key, drop ); -// } -// else { -// SpigotItemStack sItemStack = results.get( key ); -// -// sItemStack.setAmount( sItemStack.getAmount() + drop.getAmount() ); -// } -// } -// -// return new ArrayList<>( results.values() ); -// } - - - @@ -1186,21 +1127,30 @@ private void processPrisonBlockEventCommands( if ( pmEvent.getMine() != null && spigotBlock != null ) { + int blockEventsRan = 0; + Mine mine = pmEvent.getMine(); MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( spigotBlock ); if ( targetBlock != null ) { - processPrisonBlockEventCommands( pmEvent, targetBlock ); + blockEventsRan += + processPrisonBlockEventCommands( pmEvent, targetBlock ); } + + pmEvent.getDebugInfo().append( " (blockEventsRan:" ) + .append( blockEventsRan ) + .append( ")" ); } } - private void processPrisonBlockEventCommands( PrisonMinesBlockBreakEvent pmEvent, + private int processPrisonBlockEventCommands( PrisonMinesBlockBreakEvent pmEvent, MineTargetPrisonBlock targetBlock ) { + int blockEventsRan = 0; + // Do not allow MONITOR or ACCESSMONITOR to process the block events: if ( targetBlock != null && pmEvent.getMine() != null && pmEvent.getBbPriority() != BlockBreakPriority.MONITOR && @@ -1211,7 +1161,7 @@ private void processPrisonBlockEventCommands( PrisonMinesBlockBreakEvent pmEvent SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); PrisonBlock pBlock = sBlock == null ? null : sBlock.getPrisonBlock(); - mine.processBlockBreakEventCommands( pBlock, + blockEventsRan = mine.processBlockBreakEventCommands( pBlock, targetBlock, pmEvent.getSpigotPlayer(), pmEvent.getBlockEventType(), @@ -1219,48 +1169,10 @@ private void processPrisonBlockEventCommands( PrisonMinesBlockBreakEvent pmEvent } + return blockEventsRan; } -// public boolean doActionX( PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo ) { -// boolean cancel = false; -// debugInfo.append( "(doAction: starting EventCore) " ); -// -// -// AutoManagerFeatures aMan = SpigotPrison.getInstance().getAutoFeatures(); -// -// -// // Do not have to check if auto manager is enabled because it isn't if it's calling this function: -//// boolean isAutoManagerEnabled = aMan.isBoolean( AutoFeatures.isAutoManagerEnabled ); -// boolean isProcessNormalDropsEnabled = isBoolean( AutoFeatures.handleNormalDropsEvents ); -// -// int drop = 1; -// -// if ( isProcessNormalDropsEnabled ) { -// -// debugInfo.append( "(doAction calculateNormalDrop) " ); -// -// // Drop the contents of the individual block breaks -// drop = aMan.calculateNormalDrop( pmEvent ); -// -// } -// -// if ( drop > 0 ) { -// debugInfo.append( "(doAction processBlockBreakage) " ); -// -// aMan.processBlockBreakage( pmEvent, drop, true, debugInfo ); -// -// cancel = true; -// -// aMan.autosellPerBlockBreak( pmEvent.getPlayer() ); -// } -// -// if ( pmEvent.getMine() != null ) { -// aMan.checkZeroBlockReset( pmEvent.getMine() ); -// } -// -// return cancel; -// } /** @@ -1277,7 +1189,11 @@ private void processPrisonBlockEventCommands( PrisonMinesBlockBreakEvent pmEvent public boolean doAction( PrisonMinesBlockBreakEvent pmEvent ) { AutoManagerFeatures aMan = SpigotPrison.getInstance().getAutoFeatures(); - int totalDrops = aMan.calculateNormalDrop( pmEvent ); + + boolean isNormalSmelt = false; + boolean isNormalBlock = false; + + int totalDrops = aMan.calculateNormalDrop( pmEvent, isNormalSmelt, isNormalBlock ); pmEvent.getDebugInfo().append( "(normalDrops totalDrops: " + totalDrops + ") "); @@ -1297,15 +1213,11 @@ public boolean applyDropsBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, int processBlockBreakage( pmEvent ); -// forcedAutoRankups( pmEvent, debugInfo ); - -// autosellPerBlockBreak( pmEvent.getPlayer() ); - -// if ( pmEvent.getMine() != null ) { -// checkZeroBlockReset( pmEvent.getMine() ); -// } - if ( totalDrops > 0 ) { + // NOTE: totalDrops must be greater than zero to have been a success. + // But if there were prevented drops, then they should be included + // in the count since the player was successful in breaking that block. + if ( (totalDrops + pmEvent.getPreventedDrops()) > 0 ) { success = true; } else { @@ -1319,93 +1231,6 @@ public boolean applyDropsBlockBreakage( PrisonMinesBlockBreakEvent pmEvent, int -// private void forcedAutoRankups(PrisonMinesBlockBreakEvent pmEvent, StringBuilder debugInfo) { -// -// PlayerAutoRankupTask.autoSubmitPlayerRankupTask( pmEvent.getSpigotPlayer(), debugInfo ); -// -// } - -// /** -// *

    This function is processed when auto manager is disabled and process crazy enchant explosions -// * is enabled. This function is overridden in AutoManager when auto manager is enabled. -// *

    -// * -// * -// * @param mine -// * @param e -// * @param teExplosiveBlocks -// */ -// public void doAction( Mine mine, BlastUseEvent e, List explodedBlocks ) { -// -// if ( mine == null || mine != null && !e.isCancelled() ) { -// -// int totalCount = 0; -// -// -// SpigotItemStack itemInHand = SpigotPrison.getInstance().getCompatibility().getPrisonItemInMainHand( e.getPlayer() ); -// -// AutoManagerFeatures aMan = SpigotPrison.getInstance().getAutoFeatures(); -// -// // Do not have to check if auto manager is enabled because it isn't if it's calling this function: -//// boolean isAutoManagerEnabled = aMan.isBoolean( AutoFeatures.isAutoManagerEnabled ); -// boolean isCEBlockExplodeEnabled = isBoolean( AutoFeatures.isProcessCrazyEnchantsBlockExplodeEvents ); -// -// -// if ( isCEBlockExplodeEnabled ) { -// -//// StringBuilder sb = new StringBuilder(); -//// for ( SpigotBlock spigotBlock : explodedBlocks ) -//// { -//// sb.append( spigotBlock.toString() ).append( " " ); -//// } -// -//// Output.get().logInfo( "#### OnBlockBreakEventListener.doAction: BlastUseEvent: :: " + mine.getName() + " e.blocks= " + -//// e.getBlockList().size() + " blockSize : " + explodedBlocks.size() + -//// " blocks remaining= " + -//// mine.getRemainingBlockCount() + " [" + sb.toString() + "]" -//// ); -// -// // The CrazyEnchants block list have already been validated as being within the mine: -// for ( SpigotBlock spigotBlock : explodedBlocks ) { -// -// // Drop the contents of the individual block breaks -// int drop = aMan.calculateNormalDrop( itemInHand, spigotBlock ); -// totalCount += drop; -// -// if ( drop > 0 ) { -// -// aMan.processBlockBreakage( spigotBlock, mine, e.getPlayer(), drop, BlockEventType.CEXplosion, null, -// itemInHand ); -// -// } -// } -// -// if ( mine != null ) { -// aMan.checkZeroBlockReset( mine ); -// } -// -// if ( totalCount > 0 ) { -// -// // Set the broken block to AIR and cancel the event -// e.setCancelled(true); -// -// } -// -// } -// -// } -// } - -// private void doActionMonitor( Mine mine, BlastUseEvent e, List explodedBlocks ) { -// if ( mine != null ) { -// -// // Checks to see if the mine ran out of blocks, and if it did, then -// // it will reset the mine: -// mine.checkZeroBlockReset(); -// } -// } - - private void processBlockBreakage( PrisonMinesBlockBreakEvent pmEvent ) { @@ -1454,113 +1279,11 @@ private void processBlockBreakage( PrisonMinesBlockBreakEvent pmEvent ) } -// if ( pmEvent.getMine() != null ) { -// // Record the block break: -// -// // apply to ALL blocks including exploded: -// applyBlockFinalizations( pmEvent, pmEvent.getTargetBlock() ); -// -// -// for ( MineTargetPrisonBlock teBlock : pmEvent.getTargetExplodedBlocks() ) { -// -// applyBlockFinalizations( pmEvent, teBlock ); -// } -// -// checkZeroBlockReset( pmEvent.getMine() ); -// } - } } - // Warning: The following is now obsolete since there is now a sellall function that will sell on a - // per SpigotItemStack so it eliminates a ton of overhead. It also supports thousands of - // items per stack. -// public boolean autosellPerBlockBreak( Player player ) { -// boolean enabled = false; -// -// -//// if (isBoolean(AutoFeatures.isAutoSellPerBlockBreakEnabled) || -//// pmEvent.isForceAutoSell() ) { -//// -//// SellAllUtil.get().sellAllSell( player, itemStack, true, false, false ); -//// } -// -// -// // This won't try to sell on every item stack, but assuming that sellall will hit on very block -// // break, then the odds of inventory being overflowed on one explosion would be more rare than anything -// if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakEnabled ) ) { -// -// enabled = true; -// -// // Run sell all -// if ( isBoolean( AutoFeatures.isAutoSellPerBlockBreakInlinedEnabled ) ) { -// // run sellall inline with the block break event: -// if (PrisonSpigotSellAllCommands.get() != null) { -// PrisonSpigotSellAllCommands.get().sellAllSellWithDelayCommand(new SpigotPlayer(player)); -// } -// } -// else { -// // Submit sellall to run in the future (0 ticks in the future): -// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell silent" ); -// Bukkit.dispatchCommand(player, registeredCmd); -// } -// } -// -// return enabled; -// } - -// -// public void checkZeroBlockReset( Mine mine ) { -// if ( mine != null ) { -// -// // submit a mine sweeper task. It will only run if it is enabled and another -// // mine sweeper task has not been submitted. -// mine.submitMineSweeperTask(); -// -// // Checks to see if the mine ran out of blocks, and if it did, then -// // it will reset the mine: -// mine.checkZeroBlockReset(); -// } -// } -// -// private void applyBlockFinalizations( PrisonMinesBlockBreakEvent pmEvent, -// MineTargetPrisonBlock targetBlock ) { -// -// if ( targetBlock != null ) { -// -// Mine mine = pmEvent.getMine(); -// -// // Increment the block break counts if they have not been processed before. -// // Since the function return true if it can count the block, then we can -// // then have the player counts be incremented. -// if ( mine.incrementBlockMiningCount( targetBlock ) ) { -// -// // Now in AutoManagerFeatures.autoPickup and calculateNormalDrop: -// PlayerCache.getInstance().addPlayerBlocks( pmEvent.getSpigotPlayer(), -// mine.getName(), targetBlock.getPrisonBlock(), 1 ); -// -// } -// -// // Do not allow MONITOR or ACCESSMONITOR to process the block events: -// if ( pmEvent.getBbPriority() != BlockBreakPriority.MONITOR && -// pmEvent.getBbPriority() != BlockBreakPriority.ACCESSMONITOR ) { -// -// SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); -// PrisonBlock pBlock = sBlock == null ? null : sBlock.getPrisonBlock(); -// -// mine.processBlockBreakEventCommands( pBlock, -// targetBlock, pmEvent.getSpigotPlayer(), pmEvent.getBlockEventType(), pmEvent.getTriggered() ); -// -// } -// -// } -// -// //TODO What about zero-block reset and mine sweeper? -// -// } -// protected int xpCalculateXP( PrisonMinesBlockBreakEvent pmEvent ) { int xp = 0; @@ -1651,8 +1374,6 @@ protected void xpGivePlayerXp(SpigotPlayer player, int totalXp, StringBuilder de if ( giveXpOrbs ) { player.dropXPOrbs( totalXp ); -// tech.mcprison.prison.util.Location dropPoint = player.getLocation().add( player.getLocation().getDirection()); -// ((ExperienceOrb) player.getWorld().spawn(dropPoint, ExperienceOrb.class)).setExperience(xp); } else { player.giveExp( totalXp ); @@ -1987,8 +1708,6 @@ protected void itemLoreCounter( SpigotItemStack itemInHand, String itemLore, int itemLore = Text.translateAmpColorCodes( itemLore.trim() + " "); ItemMeta meta = itemInHand.getBukkitStack().getItemMeta(); -// String prisonBlockBroken = itemLore.getLore(); - if (meta.hasLore()) { lore = meta.getLore(); @@ -2022,189 +1741,16 @@ protected void itemLoreCounter( SpigotItemStack itemInHand, String itemLore, int meta.setLore(lore); itemInHand.getBukkitStack().setItemMeta(meta); - // incrementCounterInName( itemInHand, meta ); - } } } -// -// -// /** -// *

    Checks to see if mcMMO is able to be enabled, and if it is, then call it's registered -// * function that will do it's processing before prison will process the blocks. -// *

    -// * -// *

    This adds mcMMO support within mines for herbalism, mining, woodcutting, and excavation. -// *

    -// * -// * @param e -// */ -// private void registerMCMMO() { -// -// if ( !isMCMMOChecked ) { -// -// boolean isProcessMcMMOBlockBreakEvents = isBoolean( AutoFeatures.isProcessMcMMOBlockBreakEvents ); -// -// if ( isProcessMcMMOBlockBreakEvents ) { -// -// for ( RegisteredListener rListener : BlockBreakEvent.getHandlerList().getRegisteredListeners() ) { -// -// if ( rListener.getPlugin().isEnabled() && -// rListener.getPlugin().getName().equalsIgnoreCase( "mcMMO" ) ) { -// -// registeredListenerMCMMO = rListener; -// } -// } -// -// } -// -// isMCMMOChecked = true; -// } -// } -// -// private void checkMCMMO( Player player, Block block ) { -// if ( registeredListenerMCMMO != null ) { -// BlockBreakEvent bEvent = new BlockBreakEvent( block, player ); -// checkMCMMO( bEvent ); -// } -// } -// -// private void checkMCMMO( BlockBreakEvent e ) { -// if ( registeredListenerMCMMO != null ) { -// -// try { -// registeredListenerMCMMO.callEvent( e ); -// } -// catch ( EventException e1 ) { -// e1.printStackTrace(); -// } -// } -// } -// -// -// -// /** -// *

    Checks to see if mcMMO is able to be enabled, and if it is, then call it's registered -// * function that will do it's processing before prison will process the blocks. -// *

    -// * -// *

    This adds mcMMO support within mines for herbalism, mining, woodcutting, and excavation. -// *

    -// * -// * @param e -// */ -// private void registerEZBlock() { -// -// if ( !isEZBlockChecked ) { -// -// boolean isProcessMcMMOBlockBreakEvents = isBoolean( AutoFeatures.isProcessEZBlocksBlockBreakEvents ); -// -// if ( isProcessMcMMOBlockBreakEvents ) { -// -// for ( RegisteredListener rListener : BlockBreakEvent.getHandlerList().getRegisteredListeners() ) { -// -// if ( rListener.getPlugin().isEnabled() && -// rListener.getPlugin().getName().equalsIgnoreCase( "EZBlocks" ) ) { -// -// registeredListenerEZBlock = rListener; -// } -// } -// -// } -// -// isEZBlockChecked = true; -// } -// } -// -// private void checkEZBlock( Player player, Block block ) { -// if ( registeredListenerEZBlock != null ) { -// BlockBreakEvent bEvent = new BlockBreakEvent( block, player ); -// checkEZBlock( bEvent ); -// } -// } -// -// private void checkEZBlock( BlockBreakEvent e ) { -// if ( registeredListenerEZBlock != null ) { -// -// try { -// registeredListenerEZBlock.callEvent( e ); -// } -// catch ( EventException e1 ) { -// e1.printStackTrace(); -// } -// } -// } -// - - - -// private int checkCrazyEnchant( Player player, Block block, ItemStack item ) { -// int bonusXp = 0; -// -// try { -// if ( isCrazyEnchantEnabled() == null ) { -// Class.forName( -// "tech.mcprison.prison.spigot.integrations.IntegrationCrazyEnchantmentsPickaxes", false, -// this.getClass().getClassLoader() ); -// setCrazyEnchantEnabled( Boolean.TRUE ); -// } -// -// if ( isCrazyEnchantEnabled() != null && isCrazyEnchantEnabled().booleanValue() && -// item != null && IntegrationCrazyEnchantmentsPickaxes.getInstance().isEnabled() ) { -// -// bonusXp = IntegrationCrazyEnchantmentsPickaxes.getInstance() -// .getPickaxeEnchantmentExperienceBonus( player, block, item ); -// } -// } -// catch ( NoClassDefFoundError | Exception e ) { -// setCrazyEnchantEnabled( Boolean.FALSE ); -// } -// -// return bonusXp; -// } -// - - - -// @SuppressWarnings( "unused" ) -// private synchronized String incrementUses(Long elapsedNano) { -// String message = null; -// usesElapsedTimeNano += elapsedNano; -// -// if ( ++uses >= 100 ) { -// double avgNano = usesElapsedTimeNano / uses; -// double avgMs = avgNano / 1000000; -// message = String.format( "OnBlockBreak: count= %s avgNano= %s avgMs= %s ", -// Integer.toString(uses), Double.toString(avgNano), Double.toString(avgMs) ); -// -// uses = 0; -// usesElapsedTimeNano = 0L; -// } -// return message; -// } -// -// private boolean isTeExplosionTriggerEnabled() { -// return teExplosionTriggerEnabled; -// } -// -// private void setTeExplosionTriggerEnabled( boolean teExplosionTriggerEnabled ) { -// this.teExplosionTriggerEnabled = teExplosionTriggerEnabled; -// } - public Random getRandom() { return random; } -// public Boolean isCrazyEnchantEnabled() { -// return crazyEnchantEnabled; -// } -// public void setCrazyEnchantEnabled( Boolean crazyEnchantEnabled ) { -// this.crazyEnchantEnabled = crazyEnchantEnabled; -// } - } 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 f693a3c41..89b12686b 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 @@ -12,6 +12,7 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerBlockBreakEvents; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerCrazyEnchants; +import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerEntityExplodeEvents; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerPrisonEnchants; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerPrisonsExplosiveBlockBreakEvents; import tech.mcprison.prison.spigot.autofeatures.events.AutoManagerRevEnchantsExplosiveEvent; @@ -105,6 +106,8 @@ public class OnBlockBreakEventListener private AutoManagerBlockBreakEvents bbEvents; private AutoManagerPrisonsExplosiveBlockBreakEvents pebbEvents; + private AutoManagerEntityExplodeEvents eeEvents; + private AutoManagerCrazyEnchants ceEvents; private AutoManagerPrisonEnchants peEvents; @@ -221,7 +224,8 @@ private void registerEvents() { // Prison's own internal event and listener: pebbEvents = new AutoManagerPrisonsExplosiveBlockBreakEvents(); - ceEvents = new AutoManagerCrazyEnchants(); + eeEvents = new AutoManagerEntityExplodeEvents(); + ceEvents = new AutoManagerCrazyEnchants(); @@ -252,6 +256,11 @@ private void registerEvents() { // Prison's own internal event and listener: pebbEvents.registerEvents(); + + // Bukkit's EntityExplodeEvent: + eeEvents.registerEvents(); + + ceEvents.registerEvents(); peEvents.registerEvents(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakExternalEvents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakExternalEvents.java index 5bed7545c..bb408f566 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakExternalEvents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/OnBlockBreakExternalEvents.java @@ -11,7 +11,7 @@ import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig; import tech.mcprison.prison.autofeatures.AutoFeaturesFileConfig.AutoFeatures; import tech.mcprison.prison.autofeatures.AutoFeaturesWrapper; -import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; +import tech.mcprison.prison.util.BluesSemanticVersionComparator; public class OnBlockBreakExternalEvents { @@ -41,7 +41,7 @@ private OnBlockBreakExternalEvents() { super(); // if mc version is greater than or equal to 1.13.0. - if ( new BluesSpigetSemVerComparator().compareMCVersionTo("1.13.0") >= 0 ) { + if ( new BluesSemanticVersionComparator().compareMCVersionTo("1.13.0") >= 0 ) { this.isDropItemsSupported = true; } @@ -49,15 +49,6 @@ private OnBlockBreakExternalEvents() { } public static OnBlockBreakExternalEvents getInstance() { -// if ( instance != null ) { -// synchronized(OnBlockBreakExternalEvents.class) { -// -// if ( instance != null ) { -// instance = new OnBlockBreakExternalEvents(); -// -// } -// } -// } return instance; } @@ -112,60 +103,9 @@ public void registerAllExternalEvents() { } - - - // Removed because there is a directly callable target with /prison debug now: -// if ( Output.get().isDebug( DebugTarget.blockBreakListeners ) ) { -// -// String eventType = "BlockBreakEvent"; -// -// RegisteredListener[] listeners = BlockBreakEvent.getHandlerList().getRegisteredListeners(); -// -// ChatDisplay display = new ChatDisplay("Event Dump: " + eventType ); -// display.addText("&8All registered EventListeners (%d):", listeners.length ); -// -// for ( RegisteredListener eventListner : listeners ) { -// String plugin = eventListner.getPlugin().getName(); -// EventPriority priority = eventListner.getPriority(); -// String listener = eventListner.getListener().getClass().getName(); -// -// String message = String.format( "&3 Plugin: &7%s %s &3(%s)", -// plugin, priority.name(), listener); -// -// display.addText( message ); -// } -// -// display.toLog( LogLevel.DEBUG ); -// } - } -// private void registerPriorityEvents() { -// -// // First priority plugins: -// List fpPlugins = getListString( AutoFeatures.firstPriorityBlockBreakEventPlugins ); -// -// -// // gather all plugins within the event: -// TreeMap registeredPlugins = new TreeMap<>(); -// -// -// HandlerList handlers = BlockBreakEvent.getHandlerList(); -// -// for ( RegisteredListener handler : handlers.getRegisteredListeners() ) { -// -// Plugin plugin = handler.getPlugin(); -// String pluginName = plugin.getName(); -// -// if ( !registeredPlugins.containsKey( pluginName ) ) { -// -// registeredPlugins.put( pluginName, plugin ); -// } -// } -// -// //handlers.get -// } public StringBuilder checkAllExternalEvents( BlockBreakEvent e ) { 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 a99068edd..bacd2cfc1 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 @@ -5,8 +5,10 @@ import java.util.TreeMap; import java.util.UUID; +import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.entity.Player; +import org.bukkit.metadata.MetadataValue; import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; @@ -24,11 +26,12 @@ import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.api.PrisonMinesBlockBreakEvent; +import tech.mcprison.prison.spigot.game.SpigotLocation; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.utils.BlockUtils; import tech.mcprison.prison.tasks.PrisonCommandTaskData; -import tech.mcprison.prison.tasks.PrisonCommandTasks; import tech.mcprison.prison.tasks.PrisonCommandTaskData.TaskMode; +import tech.mcprison.prison.tasks.PrisonCommandTasks; public class OnBlockBreakMines extends OnBlockBreakEventCoreMessages @@ -39,6 +42,7 @@ public class OnBlockBreakMines enum EventResultsReasons { result_reason_not_yet_set, results_passed, + cancel_event__block_is_null, cancel_event__block_is_locked, ignore_event__block_is_not_in_a_mine, cancel_event__mine_mutex__mine_resetting, @@ -46,7 +50,14 @@ enum EventResultsReasons { ignore_event__block_already_counted, cancel_event__block_already_counted, ignore_event__monitor_priority_but_not_AIR, - cancel_event__player_has_no_access + cancel_event__player_has_no_access, + cancel_event__block_is_not_mappable_to_target_block, + + results_passed__access_priority__player_has_access, + cancel_event__access_priority__block_is_not_in_a_mine, + cancel_event__access_priority__player_has_no_access, + + cancel_event__player_is_vanished ; } @@ -65,7 +76,9 @@ public class MinesEventResults { private boolean cancelEvent = false; private boolean ignoreEvent = false; - BlockBreakPriority bbPriority; + private String eventName; + + private BlockBreakPriority bbPriority; private Mine mine = null; private SpigotPlayer sPlayer; @@ -82,9 +95,12 @@ public MinesEventResults( BlockBreakPriority bbPriority, SpigotPlayer sPlayer, B } public void logDebugInfo() { - if ( isIgnoreEvent() && + if ( (isIgnoreEvent() || isCancelEvent()) && Output.get().isDebug() ) { + String eventName = getEventName() != null && getEventName().trim().length() > 0 ? + "[event: " + getEventName() + "] " : ""; + String blockName = getSpigotBlock() == null ? "noPrisonBlock" : getSpigotBlock().getBlockName(); @@ -92,7 +108,8 @@ public void logDebugInfo() { "" : getSpigotBlock().getLocation().toWorldCoordinates(); - Output.get().logInfo( "Prison AutoFeatures Fast-Fail: %s %s %s %s%s", + Output.get().logInfo( "Prison AutoFeatures Fast-Fail: %s%s %s %s %s%s", + eventName, getResultsReason().name(), //getBbPriority().name(), getSpigotPlayer().getName(), @@ -115,7 +132,7 @@ public String getDebugInfo() { getSpigotBlock().getLocation().toWorldCoordinates(); return String.format( - "{br}|| EventInfo: %s %s Mine: %s %s %s ", + " EventInfo: %s %s Mine: %s %s %s ", getResultsReason().name(), // getBbPriority().name(), getSpigotPlayer().getName(), @@ -132,6 +149,13 @@ public void setResultsReason(EventResultsReasons resultsReason) { this.resultsReason = resultsReason; } + public String getEventName() { + return eventName; + } + public void setEventName(String eventName) { + this.eventName = eventName; + } + public BlockBreakPriority getBbPriority() { return bbPriority; } @@ -183,19 +207,38 @@ public void setSpigotBlock(SpigotBlock spigotBlock) { } + public Mine findMineIncludeTopBottomOfMine( SpigotPlayer player, SpigotBlock sBlock, + List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) + { + return findMine( player.getUniqueId(), sBlock, altBlocksSource, pmEvent, false ); + } + + public Mine findMine( SpigotPlayer player, SpigotBlock sBlock, + List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) + { + return findMine( player.getUniqueId(), sBlock, altBlocksSource, pmEvent, true ); + } + public Mine findMine( Player player, SpigotBlock sBlock, List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) { - return findMine( player.getUniqueId(), sBlock, altBlocksSource, pmEvent ); + return findMine( player.getUniqueId(), sBlock, altBlocksSource, pmEvent, true ); } - public Mine findMine( UUID playerUUID, SpigotBlock sBlock, List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) + public Mine findMine( UUID playerUUID, SpigotBlock sBlock, + List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent ) { + return findMine( playerUUID, sBlock, altBlocksSource, pmEvent, true ); + } + public Mine findMine( UUID playerUUID, SpigotBlock sBlock, + List altBlocksSource, PrisonMinesBlockBreakEvent pmEvent, boolean exact ) { - Long playerUUIDLSB = Long.valueOf( playerUUID.getLeastSignificantBits() ); +// Long playerUUIDLSB = Long.valueOf( playerUUID.getLeastSignificantBits() ); // Get the cached mine, if it exists: - Mine mine = getPlayerCache().get( playerUUIDLSB ); + Mine mine = getPlayerCache().get( playerUUID.toString() ); - if ( mine == null || sBlock != null && !mine.isInMineExact( sBlock.getLocation() ) ) + if ( mine == null || sBlock != null && + ( exact && !mine.isInMineExact( sBlock.getLocation() ) || + !exact && !mine.isInMineIncludeTopBottomOfMine( sBlock.getLocation() ) ) ) { // Look for the correct mine to use. // Set mine to null so if cannot find the right one it will return a @@ -214,7 +257,10 @@ public Mine findMine( UUID playerUUID, SpigotBlock sBlock, List altBlocks for ( Block bBlock : altBlocksSource ) { SpigotBlock sBlockAltBlock = SpigotBlock.getSpigotBlock( bBlock ); - mine = findMineLocation( sBlockAltBlock ); + + mine = exact ? + findMineLocation( sBlockAltBlock ) : + findMineLocationIncludeTopBottomOfMine( sBlockAltBlock ); if ( mine != null ) { @@ -231,7 +277,8 @@ public Mine findMine( UUID playerUUID, SpigotBlock sBlock, List altBlocks // Store the mine in the player cache if not null: if ( mine != null ) { - getPlayerCache().put( playerUUIDLSB, mine ); + getPlayerCache().put( playerUUID.toString(), mine ); +// getPlayerCache().put( playerUUIDLSB, mine ); } } @@ -262,6 +309,203 @@ public Mine findMine( UUID playerUUID, SpigotBlock sBlock, List altBlocks // return eventResults.isIgnoreEvent(); // } + + public List removeAllInvalidBlocks( Player player, + List blocks, + BlockBreakPriority bbPriority, + boolean ignoreBlockReuse ) { + + List goodBlocks = new ArrayList<>(); + + if ( blocks.size() == 0 || getPrisonMineManager() == null ) { + // Mines are not enabled, so exit with request to ignore event: + return goodBlocks; + } + + + + // searching for mines is expensive because it's has to check each and every block + // against all possible mines. + + // So first find the "center" of the block list by taking the averages of all blocks's x, y, and z coordinates: + Location locAvgBukkit = getCenterLocationOfBlocks(blocks, player); + + + // next we need to find the greatest distance from the average: + double locAvgRadius = getGreatestDistanceFromLocation(blocks, locAvgBukkit); + + + SpigotLocation locAvg = new SpigotLocation( locAvgBukkit ); + + + // Next we need to find all mines that are within the max distance of the mine, + // to ensure we don't miss the outer corners, take the mine's distance to a corner + // and mult by 1.3 which will potentially include mines that are outside of the + // list of blocks: + List minesShortList = getAllMinesWithinTheRadialDistance( locAvg, locAvgRadius ); + + + + // If no mines are found, then obviously no blocks will be within the mines: + if ( minesShortList.size() == 0 ) { + return goodBlocks; + } + + +// SpigotPlayer sPlayer = new SpigotPlayer( player ); + + + // All blocks must be not be null, and the blocks cannot be identified as an + // unbreakable block, which is usually part of an explosion event such as a + // block decay. + Mine lastMine = null; + + for (Block block : blocks) { + + SpigotBlock sBlock = SpigotBlock.getSpigotBlock( block ); + + if ( block != null && !BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + + // If a block is in the same mine as the 'lastMine', then add it to the + // goodBlocks list. + if ( lastMine != null && lastMine.isInMine(sBlock) ) { + goodBlocks.add(block); + } + + // else if lastMine is null or the block is not in the lastMine, then + // need to check all mines in the short list to see if the block is in + // mine. If it is, then capture it in the goodBlocks list. + else { + + for (Mine mine : minesShortList) { + if ( mine.isInMineExact(locAvg) ) { + lastMine = mine; + + goodBlocks.add(block); + break; + } + } + } + + } + } + +// // Purge all blocks in the parameter List: +// blocks.clear(); +// +// // Add only the goodBlocks back to the parameter's variable: +// blocks.addAll( goodBlocks ); + + return goodBlocks; + } + + + /** + *

    This function will take a list of blocks, and calculate the average location, + * which will be the center of the group of blocks. The group of blocks can be + * any shape, and it will still find the center. + *

    + * + *

    The way this function works, is that it adds all x's, all y's, and all z's. + * Then divides all these values by the number of blocks that were summed together. + * Basically finding the common vector or everything. + *

    + * + * @param blocks + * @param player + * @return + */ + private Location getCenterLocationOfBlocks(List blocks, Player player) { + long xT = 0; + long yT = 0; + long zT = 0; + int count = 0; + for (Block block : blocks) { + xT += block.getX(); + yT += block.getY(); + zT += block.getZ(); + count++; + } + + double xAvg = (double) xT / count; + double yAvg = (double) yT / count; + double zAvg = (double) zT / count; + Location locAvgBukkit = new Location( player.getWorld(), xAvg, yAvg, zAvg ); + return locAvgBukkit; + } + + + /** + *

    This function, given the a location, which should be the center of all blocks + * (See function `getCenterLocationOfBlocks()`), will return the greatest distance + * of all of the included blocks. This will be the outer radius of all the blocks, + * based upon the 'centerLocation'. + *

    + * + * @param blocks + * @param locAvgBukkit + * @return + */ + private double getGreatestDistanceFromLocation(List blocks, Location centerLocation ) { + double locAvgRadius = 0; + for (Block block : blocks) { + double d = centerLocation.distance( block.getLocation() ); + if ( d > locAvgRadius ) { + locAvgRadius = d; + } + } + return locAvgRadius; + } + + /** + *

    This function, given a location, and the radius of a sphere around that location, find all + * mines that that has at least one block that will fall within the range of this the location's + * sphere. To ensure a mine is not missed by a block or two, the 'maxPossibleDistance' has + * four added to it. This will help ensure that more mines are included in this list, even if it + * may miss the farthest block by a couple of blocks. It's far better to be more inclusive, than + * to exclude too many. + *

    + * + *

    This function basically behaves as if we have two points and spheres around each point. The + * spheres would be the radius from each location, to form a sphere for each location. Between the + * two spheres, we only need to use in our calculations, the closest point on each sphere, such that + * the two chosen points (one of each sphere) are the closest to each other, out of the whole surface + * of those two spheres. Basically, these two points, also happen to be on the line that is formed + * from one location to the other location. And the two points on that line, which represents the + * spheres surface, would be consider intersecting with each other if the distance between the points + * is less than zero. If they don't intersect then the distance will be greater than zero. + *

    + * + *

    So basically, the total distance should be less than the two radiuses added together (plus 4.0) + * which indicates there is a probable chance a block may be within that mine. All mines that + * meet this requirement is returned in a List. + *

    + * + * @param locAvg + * @param locAvgRadius + * @return + */ + private List getAllMinesWithinTheRadialDistance( SpigotLocation location, double locationRadius ) { + List minesShortList = new ArrayList<>(); + for (Mine m : getPrisonMineManager().getMines() ) { + if ( !m.isVirtual() ) { + + double mineRadius = m.getBounds().getRadius(); + double maxPossibleDistance = mineRadius + locationRadius + 4; + + double distanceFromMine = m.getBounds().getDistance3d( location ); + + + if ( distanceFromMine <= maxPossibleDistance ) { + minesShortList.add( m ); + } + } + } + return minesShortList; + } + + + /** *

    If the event is canceled, it still needs to be processed because of the MONITOR events: @@ -271,9 +515,16 @@ public Mine findMine( UUID playerUUID, SpigotBlock sBlock, List altBlocks * or if the targetBlock has been set to ignore all block events which * means the block has already been processed. *

    - * - * @param player - * @param block + * + * @param player The player that caused the event by mining or breaking blocks + * @param block The "target" block that was initially broke by the player. Note that sometimes + * this is not the actual block, since the event does not preserve that information. + * @param bbPriority The priority that prison was listening at for this event. + * @param ignoreBlockReuse If set to true, then if the block was already counted, then prison + * will still process the blocks. Otherwise if the block has been already counted, then + * prison will ignore the event, which can have a huge impact if it's an explosion and + * there are many other blocks that "should" be processed, but ignoring the whole event + * would be skipping a lot of block processing. * @return */ protected MinesEventResults ignoreMinesBlockBreakEvent( Player player, @@ -288,12 +539,77 @@ protected MinesEventResults ignoreMinesBlockBreakEvent( Player player, SpigotBlock sBlock = SpigotBlock.getSpigotBlock( block ); results.setSpigotBlock( sBlock ); - if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { + + // If player is vanished (ie PremiumVanish) then ignore all actions from player: + if ( isVanished( player ) ) { + + results.setResultsReason( EventResultsReasons.cancel_event__player_is_vanished ); + + results.setCancelEvent( true ); + results.setIgnoreEvent( true ); + } + else if ( block == null ) { + + results.setResultsReason( EventResultsReasons.cancel_event__block_is_null ); + + results.setCancelEvent( true ); + results.setIgnoreEvent( true ); + } + + else if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { results.setResultsReason( EventResultsReasons.cancel_event__block_is_locked ); results.setCancelEvent( true ); results.setIgnoreEvent( true ); } + else if ( bbPriority.isAccess() ) { + + Mine mine = findMine( player, sBlock, null, null ); + results.setMine( mine ); + + if ( mine == null ) { + // Prison is unable to process blocks outside of mines right now, so exit: + results.setResultsReason( EventResultsReasons + .cancel_event__access_priority__block_is_not_in_a_mine ); + + results.setCancelEvent( true ); + results.setIgnoreEvent( true ); + } + else if ( !mine.hasMiningAccess(sPlayer) ) { + + results.setResultsReason( EventResultsReasons + .cancel_event__access_priority__player_has_no_access ); + results.setIgnoreEvent( true ); + results.setCancelEvent( true ); + + if ( sPlayer != null && + AutoFeaturesWrapper.getInstance() + .isBoolean( AutoFeatures.eventPriorityACCESSFailureTPToCurrentMine ) ) { + // run the `/mines tp` command for the player which will TP them to a + // mine they can access: + + String debugInfo = String.format( + "ACCESS failed: teleport %s to valid mine.", + sPlayer.getName() ); + + PrisonCommandTaskData cmdTask = new PrisonCommandTaskData( debugInfo, + "mines tp", 0 ); + cmdTask.setTaskMode( TaskMode.syncPlayer ); + + PrisonCommandTasks.submitTasks( sPlayer, cmdTask ); + + } + + } + else { + results.setResultsReason( EventResultsReasons + .results_passed__access_priority__player_has_access ); + + // Not sure why that was here? This looks like they should have access?] + results.setIgnoreEvent( true ); + } + + } else if ( bbPriority.isMonitor() && !sBlock.isEmpty() && AutoFeaturesWrapper.getInstance().isBoolean( AutoFeatures.processMonitorEventsOnlyIfPrimaryBlockIsAIR ) ) { @@ -324,32 +640,34 @@ else if ( bbPriority.isMonitor() && !sBlock.isEmpty() && results.setCancelEvent( true ); } - else if ( bbPriority.isAccess() && !mine.hasMiningAccess(sPlayer) ) { +// else if ( bbPriority.isAccess() && !mine.hasMiningAccess(sPlayer) ) { +// +// results.setResultsReason( EventResultsReasons.cancel_event__player_has_no_access ); +// results.setIgnoreEvent( true ); +// results.setCancelEvent( true ); +// +// if ( sPlayer != null && +// AutoFeaturesWrapper.getInstance() +// .isBoolean( AutoFeatures.eventPriorityACCESSFailureTPToCurrentMine ) ) { +// // run the `/mines tp` command for the player which will TP them to a +// // mine they can access: +// +// String debugInfo = String.format( +// "ACCESS failed: teleport %s to valid mine.", +// sPlayer.getName() ); +// +// PrisonCommandTaskData cmdTask = new PrisonCommandTaskData( debugInfo, +// "mines tp", 0 ); +// cmdTask.setTaskMode( TaskMode.syncPlayer ); +// +// PrisonCommandTasks.submitTasks( sPlayer, cmdTask ); +// +// } +// +// } + else if ( AutoFeaturesWrapper.getInstance().isBoolean( AutoFeatures.validateBlocksWerePlacedByPrison ) ) { - results.setResultsReason( EventResultsReasons.cancel_event__player_has_no_access ); - results.setIgnoreEvent( true ); - results.setCancelEvent( true ); - - if ( sPlayer != null && - AutoFeaturesWrapper.getInstance() - .isBoolean( AutoFeatures.eventPriorityACCESSFailureTPToCurrentMine ) ) { - // run the `/mines tp` command for the player which will TP them to a - // mine they can access: - - String debugInfo = String.format( - "ACCESS failed: teleport %s to valid mine.", - sPlayer.getName() ); - - PrisonCommandTaskData cmdTask = new PrisonCommandTaskData( debugInfo, - "mines tp", 0 ); - cmdTask.setTaskMode( TaskMode.syncPlayer ); - - PrisonCommandTasks.submitTasks( sPlayer, cmdTask ); - - } - - } - else { + // validate if the block being targeted is the one prison placed in the mine: MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); @@ -382,6 +700,15 @@ else if ( !ignoreBlockReuse && targetBlock.isCounted() ) { } } } + else { + // A targetBlock could not be found for the current block. + // So it must be invalid: + + // Do not cancel the event... + results.setResultsReason( EventResultsReasons.cancel_event__block_is_not_mappable_to_target_block ); + + results.setCancelEvent( true ); + } } @@ -392,89 +719,33 @@ else if ( !ignoreBlockReuse && targetBlock.isCounted() ) { results.setResultsReason( EventResultsReasons.results_passed ); } - results.logDebugInfo(); + //results.logDebugInfo(); return results; } -// /** -// *

    Warning... this is a temp copy of the real function and will be removed -// * if PEExplosionEvent adds the interface Cancellable. -// *

    -// * -// * @param event -// * @param player -// * @param block -// * @return -// */ -// protected boolean processMinesBlockBreakEvent( PEExplosionEvent event, Player player, Block block ) { -// boolean processEvent = true; -// -// SpigotBlock sBlock = new SpigotBlock( block ); -// if ( BlockUtils.getInstance().isUnbreakable( sBlock ) ) { -// event.setCancelled( true ); -// processEvent = false; -// } -// -// Mine mine = findMine( player, sBlock, null, null ); -// -// if ( mine == null ) { -// // Prison is unable to process blocks outside of mines right now, so exit: -// processEvent = false; -// } -// -// // If not minable, then display message and exit. -// if ( !mine.getMineStateMutex().isMinable() ) { -// -// SpigotPlayer sPlayer = new SpigotPlayer( player ); -// sPlayer.setActionBar( "Mine " + mine.getTag() + " is being reset... please wait." ); -// event.setCancelled( true ); -// processEvent = false; -// } -// MineTargetPrisonBlock targetBlock = mine.getTargetPrisonBlock( sBlock ); -// -// // If ignore all block events, then exit this function without logging anything: -// if ( targetBlock.isIgnoreAllBlockEvents() ) { -// event.setCancelled( true ); -// processEvent = false; -// } -// -// -// return processEvent; -// } - /** - *

    If mine is not null, then it will check for a zero-block reset (reset-threshold). + *

    Checks to see if a player is vanished when using PremiumVanish, SuperVanish, + * EssentialsX, VanishNoPacket and many more vanish plugins. *

    * - * @param mine - */ - public void checkZeroBlockReset( Mine mine ) { - if ( mine != null ) { - - // Checks to see if the mine ran out of blocks, and if it did, then - // it will reset the mine: - mine.checkZeroBlockReset(); - } - } - - - /** - *

    If mine is not null, then it will perform a mine sweeper - * for the mine, if it is enabled. + *

    See the API for Devs section on their spigotmc.org page. + * + * Premium Vanish at spigotmc.org + * *

    * - * @param mine + * @param player + * @return */ - public void checkMineSweeper( Mine mine ) { - if ( mine != null ) { - - // submit a mine sweeper task. It will only run if it is enabled and another - // mine sweeper task has not been submitted. - mine.submitMineSweeperTask(); - } - } + private boolean isVanished(Player player) { + for (MetadataValue meta : player.getMetadata("vanished")) { + if (meta.asBoolean()) return true; + } + return false; +} + @@ -537,6 +808,25 @@ public boolean isBlockAMatch( MineTargetPrisonBlock targetBlock, PrisonBlock pbB *

    The function isBlockAMatch() should be used prior to calling this function. *

    * + *

    Note, it is now possible that block validation can be disabled. If that is the case, then + * the blocks may not match the same type as the targetBlock, or may not have been place in the + * mine by prison (ie.. a player or admin). + * Therefore, actions should be based upon the actual block and not the targetBlock. + * For this function, the targetBlock is only being used to identify if it were a custom + * block type. May want to remove dependency upon targetBlock for this check. Like maybe use the + * mined block to get the "core" prison block type to make that determination. + *

    + * + *

    Note: if the target block is a custom block, but yet the actual block is not, calling the + * custom block's getDrop() will not produce the wrong drops. It depends on the plugin handling + * the drops, but it may return the bukkit drops, or no drops. + *

    + * + *

    NOTE: to better handle the situation where falling sand may not get the correct target block, + * it may make sense to tag all placed blocks with an NBT tag to identify it's original location, + * then use that location for the correct target block. + *

    + * * @param bukkitDrops * @param targetBlock * @param itemInHand @@ -549,6 +839,7 @@ public boolean collectBukkitDrops( List bukkitDrops, MineTarget boolean results = false; if ( targetBlock != null && + targetBlock.getPrisonBlock() != null && targetBlock.getPrisonBlock().getBlockType().isCustomBlockType() ) { List cbIntegrations = @@ -569,11 +860,6 @@ public boolean collectBukkitDrops( List bukkitDrops, MineTarget - // if ( sBlockMined == null && targetBlock.getMinedBlock() != null ) { - // sBlockMined = (SpigotBlock) targetBlock.getMinedBlock(); - // } - // SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); - // If in the mine, then need a targetBlock, otherwise if it's null then get drops anyway: if ( !results && sBlockMined != null // && ( targetBlock == null || @@ -595,12 +881,6 @@ public boolean collectBukkitDrops( List bukkitDrops, MineTarget results = true; } -// else if ( !results && sBlockMined != null ) -// { -// Output.get().logWarn( "collectBukkitDrops: block was changed and not what was expected. " + "Block: " + -// sBlockMined.getBlockName() + " expecting: " + -// (targetBlock == null ? "(nothing)" : targetBlock.getPrisonBlock().getBlockName()) ); -// } return results; } @@ -623,10 +903,14 @@ private void getSpigotDrops( List bukkitDrops, SpigotBlock sBlo public void clearBukkitDrops( List bukkitDrops, MineTargetPrisonBlock targetBlock ) { + if ( targetBlock != null ) { + SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); - SpigotBlock sBlock = (SpigotBlock) targetBlock.getMinedBlock(); - sBlock.clearDrops(); - + if ( sBlock != null ) { + + sBlock.clearDrops(); + } + } } @@ -670,10 +954,15 @@ private Mine findMineLocation( SpigotBlock block ) { null : getPrisonMineManager().findMineLocationExact( block.getLocation() ); } + private Mine findMineLocationIncludeTopBottomOfMine( SpigotBlock block ) { + return getPrisonMineManager() == null || block == null || block.getLocation() == null ? + null : getPrisonMineManager().findMineLocationIncludeTopBottomOfMine( block.getLocation() ); + } + - private TreeMap getPlayerCache() { + private TreeMap getPlayerCache() { return getPrisonMineManager() == null ? - new TreeMap() : + new TreeMap() : getPrisonMineManager().getPlayerCache(); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java index 0ace4bf8c..e9840230f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlock.java @@ -44,7 +44,6 @@ */ public class SpigotBlock extends PrisonBlock -// implements Block { private org.bukkit.block.Block bBlock; @@ -57,86 +56,88 @@ public class SpigotBlock */ private transient Set prisonBlockTypes; - private SpigotBlock( String blockName, org.bukkit.block.Block bBlock ) { - super( blockName ); - - this.bBlock = bBlock; - - this.prisonBlockTypes = new HashSet<>(); - - } + private SpigotBlock(String blockName, org.bukkit.block.Block bBlock) { + super(blockName); - private SpigotBlock( PrisonBlockType blockType, String blockName, org.bukkit.block.Block bBlock ) { - super( blockType, blockName ); - - this.bBlock = bBlock; - - this.prisonBlockTypes = new HashSet<>(); - - } + this.bBlock = bBlock; + + this.prisonBlockTypes = new HashSet<>(); - public SpigotBlock( org.bukkit.block.Block bBlock, PrisonBlock targetBlockType ) { - this( targetBlockType.getBlockName(), bBlock ); } - public static SpigotBlock getSpigotBlock( org.bukkit.block.Block bukkitBlock) { - SpigotBlock sBlock = null; - - if (bukkitBlock != null ) { - - XMaterial xMat = SpigotCompatibility.getInstance().getXMaterial( bukkitBlock ); - - if ( xMat == null ) { - for ( CustomBlockIntegration custIntegration : Prison.get().getIntegrationManager().getCustomBlockIntegrations() ) { - - if ( custIntegration.isRegistered() ) { - - if ( custIntegration instanceof CustomItems ) { - CustomItems cItems = (CustomItems) custIntegration; - - String blockId = cItems.getCustomBlockId(bukkitBlock); - - if ( blockId != null ) { - - sBlock = new SpigotBlock( cItems.getBlockType(), blockId, bukkitBlock ); - } - } - } - } - - } - - else if ( xMat != null ) { - sBlock = new SpigotBlock( xMat.name(), bukkitBlock ); - } - } - - -// SpigotBlock sBlock = SpigotCompatibility.getInstance().getPrisonBlock( bBlock ); - -// super( SpigotCompatibility.getInstance().getPrisonBlock( bBlock ) ); -// super( XMaterial.matchXMaterial( bBlock.getType() ).name() ); -// super( XBlock. .getType( bBlock ).name() ); - - return sBlock; - } + private SpigotBlock(PrisonBlockType blockType, String blockName, org.bukkit.block.Block bBlock) { + super(blockType, blockName); + + this.bBlock = bBlock; + + this.prisonBlockTypes = new HashSet<>(); + + } + + public SpigotBlock(org.bukkit.block.Block bBlock, PrisonBlock targetBlockType) { + this(targetBlockType.getBlockName(), bBlock); + } + + public static SpigotBlock getSpigotBlock(org.bukkit.block.Block bukkitBlock) { + SpigotBlock sBlock = null; + + if (bukkitBlock != null) { + + XMaterial xMat = SpigotCompatibility.getInstance().getXMaterial(bukkitBlock); + + if (xMat == null) { + for (CustomBlockIntegration custIntegration : Prison.get().getIntegrationManager() + .getCustomBlockIntegrations()) { + + if (custIntegration.isRegistered()) { + + if (custIntegration instanceof CustomItems) { + CustomItems cItems = (CustomItems) custIntegration; + + String blockId = cItems.getCustomBlockId(bukkitBlock); + + if (blockId != null) { + + sBlock = new SpigotBlock(cItems.getBlockType(), blockId, bukkitBlock); + } + } + } + } + + } + + else if (xMat != null) { + sBlock = new SpigotBlock(xMat.name(), bukkitBlock); + } + } + + return sBlock; + } - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - sb.append( getPrisonBlock().getBlockName() ).append( " " ) - .append( getLocation().toWorldCoordinates() ); - - - return sb.toString(); - } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append(getPrisonBlock().getBlockNameSearch()).append(" ").append(getLocation().toWorldCoordinates()); + + if (getChance() > 0) { + sb.append(" chance:").append(Double.toString(getChance())); + } + + if (getSalePrice() > 0) { + sb.append(" sell:").append(Double.toString(getSalePrice())); + } + + if (getPurchasePrice() > 0) { + sb.append(" purch:").append(Double.toString(getPurchasePrice())); + } -// public String getBlockName() { -// return super.getBlockName(); -// } + return sb.toString(); + } + + @Override public Location getLocation() { return getWrapper() == null ? null : SpigotUtil.bukkitLocationToPrison(getWrapper().getLocation()); @@ -149,69 +150,35 @@ public String toString() { face.name()))); } -// @Override public BlockType getType() { -// return SpigotCompatibility.getInstance().getBlockType( getWrapper() ); -//// return SpigotUtil.materialToBlockType(bBlock.getType()); -// } - -// @Override - public PrisonBlock getPrisonBlock() { - - return this; - -// PrisonBlock results = null; -// -// if ( getPrisonBlockTypes() != null ) { -// -// // Need to see if any PrisonBlockTypes exist in the mine where this block is located. -// for ( PrisonBlockType blockType : getPrisonBlockTypes() ) { -// -// results = getPrisonBlockFromCustomBlockIntegration( blockType ); -// if ( results != null ) { -// -// break; -// } -// } -// } -// -// if ( results == null && getWrapper() != null ) { -// results = SpigotCompatibility.getInstance().getPrisonBlock( getWrapper() ); -// } -// -// if ( results != null && results.getLocation() == null && getLocation() != null ) { -// // Clone the block that was found in the mine. This will allow us to -// // set the location: -// results = new PrisonBlock( results ); -// -// results.setLocation( getLocation() ); -// } -// -// return results; - } + + public PrisonBlock getPrisonBlock() { + + return this; + } @SuppressWarnings("unused") - private PrisonBlock getPrisonBlockFromCustomBlockIntegration( PrisonBlockType blockType ) { + private PrisonBlock getPrisonBlockFromCustomBlockIntegration(PrisonBlockType blockType) { PrisonBlock results = null; - - switch ( blockType ) - { - case minecraft: - // No special processing for minecraft types since that will be the fallback later on: - - case CustomItems: - case ItemsAdder: - { - CustomBlockIntegration customItemsIntegration = - PrisonAPI.getIntegrationManager().getCustomBlockIntegration( blockType ); - // NOTE: This would be the situation where the admin added the Custom Items plugin, added blocks - // then removed the plugin. So if it's null, ignore it. - if ( customItemsIntegration != null ) { - results = customItemsIntegration.getCustomBlock( this ); - } - } - - break; - + + switch (blockType) { + case minecraft: + // No special processing for minecraft types since that will be the fallback + // later on: + + case CustomItems: + case ItemsAdder: { + CustomBlockIntegration customItemsIntegration = PrisonAPI.getIntegrationManager() + .getCustomBlockIntegration(blockType); + // NOTE: This would be the situation where the admin added the Custom Items + // plugin, added blocks + // then removed the plugin. So if it's null, ignore it. + if (customItemsIntegration != null) { + results = customItemsIntegration.getCustomBlock(this); + } + } + + break; + // case ItemsAdder: // { // CustomBlockIntegration customItemsIntegration = @@ -224,13 +191,13 @@ private PrisonBlock getPrisonBlockFromCustomBlockIntegration( PrisonBlockType bl // } // // break; - - default: - break; + + default: + break; } - - return results; - } + + return results; + } public Set getPrisonBlockTypes() { @@ -240,178 +207,112 @@ public void setPrisonBlockTypes( Set prisonBlockTypes ) { this.prisonBlockTypes = prisonBlockTypes; } - public void setPrisonBlock( XMaterial xMat ) { - setPrisonBlock( SpigotUtil.getPrisonBlock( xMat.name() ) ); - + public void setPrisonBlock(XMaterial xMat) { + setPrisonBlock(SpigotUtil.getPrisonBlock(xMat.name())); + } - public void setPrisonBlock( PrisonBlock prisonBlock ) { - - if ( prisonBlock == null ) { - prisonBlock = PrisonBlock.AIR; - } - - switch ( prisonBlock.getBlockType() ) - { - case minecraft: - - SpigotCompatibility.getInstance(). - updateSpigotBlock( prisonBlock, getWrapper() ); - - break; - - case CustomItems: - case ItemsAdder: - { - CustomBlockIntegration customItemsIntegration = - PrisonAPI.getIntegrationManager().getCustomBlockIntegration( prisonBlock.getBlockType() ); - - Block results = customItemsIntegration.setCustomBlockId( this, prisonBlock.getBlockName(), false ); - if ( results != null ) { - this.bBlock = ((SpigotBlock) results).getWrapper(); - } - else { - Output.get().logInfo( "SpigotBLock.setPrisonBlock: Failed to set a custom block %s ", prisonBlock.getBlockNameFormal() ); - } - } - - break; - - default: - break; + public void setPrisonBlock(PrisonBlock prisonBlock) { + + if (prisonBlock == null) { + prisonBlock = PrisonBlock.AIR; } - - - } + + switch (prisonBlock.getBlockType()) { + case minecraft: + + SpigotCompatibility.getInstance().updateSpigotBlock(prisonBlock, getWrapper()); + + break; + + case CustomItems: + case ItemsAdder: { + CustomBlockIntegration customItemsIntegration = PrisonAPI.getIntegrationManager() + .getCustomBlockIntegration(prisonBlock.getBlockType()); + + Block results = customItemsIntegration.setCustomBlockId(this, prisonBlock.getBlockName(), false); + if (results != null) { + this.bBlock = ((SpigotBlock) results).getWrapper(); + } else { + Output.get().logInfo("SpigotBLock.setPrisonBlock: Failed to set a custom block %s ", + prisonBlock.getBlockNameFormal()); + } + } + + break; + + default: + break; + } + + } - public void setBlockFace( BlockFace blockFace ) { - - SpigotCompatibility.getInstance() - .setBlockFace( getWrapper(), blockFace ); - } + public void setBlockFace(BlockFace blockFace) { + + SpigotCompatibility.getInstance().setBlockFace(getWrapper(), blockFace); + } -// /** -// *

    When setting the Data and Type, turn off apply physics which will reduce the over head on block updates -// * by about 1/3. Really do not need to apply physics in the mines especially if no air blocks and nothing -// * that could fall (sand) or flow is placed. -// *

    -// */ -// @Override -// public void setType( PrisonBlock blockType) { -// -// SpigotCompatibility.getInstance() -// .updateSpigotBlock( blockType, getWrapper() ); -// -//// if ( type != null && type != BlockType.IGNORE ) { -//// -//// Material mat = SpigotUtil.getMaterial( type ); -//// if ( mat != null ) { -//// bBlock.setType( mat, false ); -//// } -//// -////// Optional xMatO = XMaterial.matchXMaterial( type.name() ); -////// -////// if ( xMatO.isPresent() ) { -////// XMaterial xMat = xMatO.get(); -////// Optional matO = xMat.parseMaterial(); -////// -////// if ( matO.isPresent() ) { -////// Material mat = matO.get(); -////// -////// bBlock.setType( mat, false ); -////// -////// } -////// } -//// else { -//// // spigot 1.8.8 support for XMaterial: -//// // MOSS_STONE LAPIS_LAZULI_ORE LAPIS_LAZULI_BLOCK PILLAR_QUARTZ_BLOCK -//// // -//// -//// Output.get().logWarn( "SpigotBlock.setType: could not match BlockType " + -//// type.name() + " defaulting to AIR instead."); -//// -//// mat = SpigotUtil.getMaterial( BlockType.AIR ); -//// if ( mat != null ) { -//// bBlock.setType( mat, false ); -//// } -//// } -//// -////// try { -////// MaterialData materialData = SpigotUtil.blockTypeToMaterial(type); -////// bBlock.setType(materialData.getItemType(), false); -////// if ( type.getMaterialVersion() == MaterialVersion.v1_8) { -////// -////// bBlock.setData(materialData.getData(), false); -////// } -////// } -////// catch ( Exception e ) { -////// Output.get().logError( -////// String.format( "BlockType could not be set: %s %s ", -////// (type == null ? "(null)" : type.name()), e.getMessage()) ); -////// } -//// } -// } - @Override - public BlockState getState() { - - BlockState results = null; - - XMaterial xMat = SpigotUtil.getXMaterial( getPrisonBlock() ); - - switch ( xMat ) { - case LEVER: - results = new SpigotLever(this); - break; - case ACACIA_SIGN: - case ACACIA_WALL_SIGN: - case BIRCH_SIGN: - case BIRCH_WALL_SIGN: - case CRIMSON_SIGN: - case CRIMSON_WALL_SIGN: - case DARK_OAK_SIGN: - case DARK_OAK_WALL_SIGN: - case JUNGLE_SIGN: - case JUNGLE_WALL_SIGN: - case OAK_SIGN: - case OAK_WALL_SIGN: - case SPRUCE_SIGN: - case SPRUCE_WALL_SIGN: - case WARPED_SIGN: - case WARPED_WALL_SIGN: - results = new SpigotSign(this); - break; - - case ACACIA_DOOR: - case BIRCH_DOOR: - case CRIMSON_DOOR: - case DARK_OAK_DOOR: - case IRON_DOOR: - case JUNGLE_DOOR: - case OAK_DOOR: - case SPRUCE_DOOR: - case WARPED_DOOR: - results = new SpigotDoor(this); - break; - - default: - results = new SpigotBlockState(this); - } - - return results; - } + @Override + public BlockState getState() { + + BlockState results = null; + + XMaterial xMat = SpigotUtil.getXMaterial(getPrisonBlock()); + + switch (xMat) { + case LEVER: + results = new SpigotLever(this); + break; + case ACACIA_SIGN: + case ACACIA_WALL_SIGN: + case BIRCH_SIGN: + case BIRCH_WALL_SIGN: + case CRIMSON_SIGN: + case CRIMSON_WALL_SIGN: + case DARK_OAK_SIGN: + case DARK_OAK_WALL_SIGN: + case JUNGLE_SIGN: + case JUNGLE_WALL_SIGN: + case OAK_SIGN: + case OAK_WALL_SIGN: + case SPRUCE_SIGN: + case SPRUCE_WALL_SIGN: + case WARPED_SIGN: + case WARPED_WALL_SIGN: + results = new SpigotSign(this); + break; + + case ACACIA_DOOR: + case BIRCH_DOOR: + case CRIMSON_DOOR: + case DARK_OAK_DOOR: + case IRON_DOOR: + case JUNGLE_DOOR: + case OAK_DOOR: + case SPRUCE_DOOR: + case WARPED_DOOR: + results = new SpigotDoor(this); + break; + + default: + results = new SpigotBlockState(this); + } - @Override - public boolean breakNaturally() { - boolean results = false; - - if ( getWrapper() != null ) { - - results = getWrapper().breakNaturally(); - } - - return results; - } + return results; + } + + @Override + public boolean breakNaturally() { + boolean results = false; + + if (getWrapper() != null) { + + results = getWrapper().breakNaturally(); + } + + return results; + } @Override public List getDrops() { @@ -452,32 +353,22 @@ public List getDrops(ItemStack tool) { return ret; } - /** - *

    This clears the drops for the given block, so if the event is not canceled, it will - * not result in duplicate drops. + /** + *

    + * This clears the drops for the given block, so if the event is not canceled, + * it will not result in duplicate drops. *

    - */ - public void clearDrops() { + */ + public void clearDrops() { - if ( getWrapper() != null && getWrapper().getDrops() != null ) { - for ( org.bukkit.inventory.ItemStack iStack : getWrapper().getDrops() ) - { - iStack.setAmount( 0 ); + if (getWrapper() != null && getWrapper().getDrops() != null) { + for (org.bukkit.inventory.ItemStack iStack : getWrapper().getDrops()) { + iStack.setAmount(0); } -// getWrapper().getDrops().clear(); - } - } + } + } -// public List getDrops(SpigotItemStack tool) { -// List ret = new ArrayList<>(); -// -// bBlock.getDrops(SpigotUtil.prisonItemStackToBukkit(tool)) -// .forEach(itemStack -> ret.add(SpigotUtil.bukkitItemStackToPrison(itemStack))); -// -// return ret; -// } - public org.bukkit.block.Block getWrapper() { return bBlock; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlockGetAtLocation.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlockGetAtLocation.java index f23774b06..92de07415 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlockGetAtLocation.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlockGetAtLocation.java @@ -12,46 +12,44 @@ public class SpigotBlockGetAtLocation { - /** - *

    This should be the ONLY usage in the whole Prison plugin that gets the - * bukkit block from the world and converts it to a SpigotBlock.. - *

    - * - *

    This gets the actual block from the world, but it only reads, and does not - * update. I cannot say this is safe to run asynchronously, but so far I have - * not see any related problems when it is. - * - */ - public Block getBlockAt( Location location, boolean containsCustomBlocks, - SpigotWorld world ) { - SpigotBlock sBlock = null; - - if ( location != null ) { - - org.bukkit.Location bLocation = world.getBukkitLocation( location ); - org.bukkit.block.Block bBlock = world.getWrapper().getBlockAt( bLocation ); - - - sBlock = SpigotCompatibility.getInstance().getSpigotBlock( bBlock ); - - if ( sBlock == null ) { - - sBlock = new SpigotBlock( bBlock, PrisonBlock.AIR.clone() ); - } - - - if ( containsCustomBlocks ) { - - List cbIntegrations = - PrisonAPI.getIntegrationManager().getCustomBlockIntegrations(); - - for ( CustomBlockIntegration customBlock : cbIntegrations ) - { - PrisonBlock pBlock = customBlock.getCustomBlock( sBlock ); - - if ( pBlock != null ) { - - //if ( Output.get().isDebug() ) + /** + *

    + * This should be the ONLY usage in the whole Prison plugin that gets the bukkit + * block from the world and converts it to a SpigotBlock.. + *

    + * + *

    + * This gets the actual block from the world, but it only reads, and does not + * update. I cannot say this is safe to run asynchronously, but so far I have + * not see any related problems when it is. + * + */ + public Block getBlockAt(Location location, boolean containsCustomBlocks, SpigotWorld world) { + SpigotBlock sBlock = null; + + if (location != null) { + + org.bukkit.Location bLocation = world.getBukkitLocation(location); + org.bukkit.block.Block bBlock = world.getWrapper().getBlockAt(bLocation); + + sBlock = SpigotCompatibility.getInstance().getSpigotBlock(bBlock); + + if (sBlock == null) { + + sBlock = new SpigotBlock(bBlock, PrisonBlock.AIR.clone()); + } + + if (containsCustomBlocks) { + + List cbIntegrations = PrisonAPI.getIntegrationManager() + .getCustomBlockIntegrations(); + + for (CustomBlockIntegration customBlock : cbIntegrations) { + PrisonBlock pBlock = customBlock.getCustomBlock(sBlock); + + if (pBlock != null) { + + // if ( Output.get().isDebug() ) // { // // String message = String.format( @@ -62,19 +60,17 @@ public Block getBlockAt( Location location, boolean containsCustomBlocks, // // Output.get().logInfo( message ); // } - - sBlock.setBlockName( pBlock.getBlockName() ); - sBlock.setBlockType( customBlock.getBlockType() ); - break; - } - } - } - - - } - - return sBlock; - } - - + + sBlock.setBlockName(pBlock.getBlockName()); + sBlock.setBlockType(customBlock.getBlockType()); + break; + } + } + } + + } + + return sBlock; + } + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlockSetSynchronously.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlockSetSynchronously.java index dd1056e88..d8b13600b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlockSetSynchronously.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotBlockSetSynchronously.java @@ -47,7 +47,6 @@ public void run() { Location location = tBlock.getLocation(); SpigotBlock sBlock = (SpigotBlock) world.getBlockAt( location ); -// SpigotBlock sBlock = (SpigotBlock) location.getBlockAt(); sBlock.setPrisonBlock( pBlock ); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java index a35990cd1..69b0903b5 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/block/SpigotItemStack.java @@ -25,17 +25,12 @@ public class SpigotItemStack extends ItemStack { private org.bukkit.inventory.ItemStack bukkitStack; -// private NBTItem nbtBukkitStack; -// private boolean nbtChecked = false; -// private org.bukkit.inventory.ItemStack bukkitStack; - private org.bukkit.inventory.ItemStack deserialize; public SpigotItemStack( org.bukkit.inventory.ItemStack bukkitStack ) throws PrisonItemStackNotSupportedRuntimeException { super(); this.bukkitStack = bukkitStack; -// this.nbtBukkitStack = null; setupBukkitStack( bukkitStack ); } @@ -56,13 +51,6 @@ private void setupBukkitStack( org.bukkit.inventory.ItemStack bukkitStack ) { } } -// if ( xMat != XMaterial.AIR ) { -// -// NBTItem nbtItemStack = new NBTItem( bukkitStack, true ); -// -// this.nbtBukkitStack = nbtItemStack; -//// this.bukkitStack = bukkitStack; -// } if (bukkitStack == null || bukkitStack.getType().equals(Material.AIR)) { @@ -82,20 +70,11 @@ private void setupBukkitStack( org.bukkit.inventory.ItemStack bukkitStack ) { - -// BlockType type = SpigotCompatibility.getInstance() -// .getBlockType( bukkitStack ); -// BlockType type = materialToBlockType(bukkitStack.getType()); - - String displayName = null; if (meta.hasDisplayName()) { displayName = meta.getDisplayName(); } -// else if ( type != null ) { -// displayName = type.getBlockName().toLowerCase(); -// } PrisonBlock type = SpigotUtil.getPrisonBlock( xMat, displayName ); @@ -106,7 +85,7 @@ private void setupBukkitStack( org.bukkit.inventory.ItemStack bukkitStack ) { if ( meta.hasLore() ) { for ( String lore : meta.getLore() ) { lores.add( lore ); - } + } } setAmount( amount ); @@ -134,126 +113,82 @@ public SpigotItemStack(String displayName, int amount, PrisonBlock material, Str } } - public SpigotItemStack(int amount, PrisonBlock material, String... lore) { - super( amount, material, lore ); - - SpigotItemStack sItemStack = SpigotUtil.getSpigotItemStack( material, amount ); - - this.bukkitStack = sItemStack.getBukkitStack(); - - if ( bukkitStack != null ) { - setupBukkitStack( bukkitStack ); - } - } + public SpigotItemStack(int amount, PrisonBlock material, String... lore) { + super(amount, material, lore); + + SpigotItemStack sItemStack = SpigotUtil.getSpigotItemStack(material, amount); + + this.bukkitStack = sItemStack.getBukkitStack(); + + if (bukkitStack != null) { + setupBukkitStack(bukkitStack); + } + } - public void setPrisonBlock( PrisonBlock pBlock ) { - - String displayName = pBlock.getBlockName(); - - if ( pBlock.getDisplayName() != null ) { - displayName = pBlock.getDisplayName(); - } - - setDisplayName( displayName ); - - setMaterial( pBlock ); - } + public SpigotItemStack(ItemStack iStack) { + super(iStack); + + org.bukkit.inventory.ItemStack bStack = (iStack instanceof SpigotItemStack + ? ((SpigotItemStack) iStack).getBukkitStack() + : null); + + if (bStack == null) { + + XMaterial xMat = SpigotCompatibility.getInstance().getXMaterial(getMaterial()); + if (xMat != null) { + bStack = xMat.parseItem(); + } + } + + if (bStack != null) { + + this.bukkitStack = bStack.clone(); + + if (bukkitStack != null) { + setupBukkitStack(bukkitStack); + } + } + + } -// /** -// *

    This will check to see if the nbt library is active on this itemStack, -// * of which there are some items and blocks that it cannot be used with. -// * If it has not been checked before, it will attempt a check. -// *

    -// * -// * @return -// */ -// public boolean isNBTEnabled() { -// -// if ( !nbtChecked && bukkitStack != null && bukkitStack.getType() != Material.AIR ) { -// -// try { -// NBTItem nbtItemStack = new NBTItem( bukkitStack, true ); -// -// this.nbtBukkitStack = nbtItemStack; -// } catch (Exception e) { -// // ignore - the bukkit item stack is not compatible with the NBT library -// } -// -// this.nbtChecked = true; -// } -// -// return nbtBukkitStack != null; -// } -// public NBTItem getNBT() { -// NBTItem nbtItemStack = null; -// -// if ( getBukkitStack() != null && getBukkitStack().getType() != Material.AIR ) { -// try { -// nbtItemStack = new NBTItem( getBukkitStack(), true ); -// -// nbtDebugLog( nbtItemStack, "getNbt" ); -// } catch (Exception e) { -// // ignore - the bukkit item stack is not compatible with the NBT library -// } -// } -// -// return nbtItemStack; -// } + public void setPrisonBlock(PrisonBlock pBlock) { + + String displayName = pBlock.getBlockName(); + + if (pBlock.getDisplayName() != null) { + displayName = pBlock.getDisplayName(); + } + + setDisplayName(displayName); + + setMaterial(pBlock); + } -// private void applyNbt( NBTItem nbtItem ) { -// if ( nbtItem != null && getBukkitStack() != null ) { -// -//// nbtItem.applyNBT( getBukkitStack() ); -// -// nbtDebugLog( nbtItem, "applyNbt" ); -// } -// } -// private void nbtDebugLog( NBTItem nbtItem, String desc ) { -// if ( Output.get().isDebug() ) { -// org.bukkit.inventory.ItemStack iStack = nbtItem.getItem(); -// -// int sysId = System.identityHashCode(iStack); -// -// String message = String.format( -// "NBT %s ItemStack for %s: %s sysId: %d", -// desc, -// iStack.hasItemMeta() && iStack.getItemMeta().hasDisplayName() ? -// iStack.getItemMeta().getDisplayName() : -// iStack.getType().name(), -// nbtItem.toString(), -// sysId ); -// -// Output.get().logInfo( message ); -// -// Output.get().logInfo( "NBT: " + new NBTItem( getBukkitStack() ) ); -// -// } -// } - public boolean hasNBTKey( String key ) { - boolean results = PrisonNBTUtil.hasNBTString( getBukkitStack(), key); - + public boolean hasNBTKey(String key) { + boolean results = PrisonNBTUtil.hasNBTString(getBukkitStack(), key); + // NBTItem nbtItem = getNBT(); // if ( nbtItem != null ) { // results = nbtItem.hasKey( key ); // } - - return results; - } + + return results; + } - public String getNBTString( String key ) { - String results = PrisonNBTUtil.getNBTString( getBukkitStack(), key); - + public String getNBTString(String key) { + String results = PrisonNBTUtil.getNBTString(getBukkitStack(), key); + // NBTItem nbtItem = getNBT(); // if ( nbtItem != null ) { // results = nbtItem.getString( key ); // } - return results; - } + return results; + } public void setNBTString( String key, String value ) { PrisonNBTUtil.setNBTString( getBukkitStack(), key, value ); @@ -267,80 +202,13 @@ public void setNBTString( String key, String value ) { - public String getNBTItemStackInfo() { - - String results = PrisonNBTUtil.nbtDebugString(getBukkitStack()) ; - - return results; - } - -// public int getNBTInt( String key ) { -// int results = -1; -// -// NBTItem nbtItem = getNBT(); -// if ( nbtItem != null ) { -// results = nbtItem.getInteger( key ); -// } -// return results; -// } -// public void setNBTInt( String key, int value ) { -// -// NBTItem nbtItem = getNBT(); -// if ( nbtItem != null ) { -// nbtItem.setInteger( key, value ); -// nbtDebugLog( nbtItem, "setNBTInt" ); -// } -// } - -// public double getNBTDouble( String key ) { -// double results = -1d; -// -// NBTItem nbtItem = getNBT(); -// if ( nbtItem != null ) { -// results = nbtItem.getDouble( key ); -// } -// return results; -// } -// public void setNBTDouble( String key, double value ) { -// -// NBTItem nbtItem = getNBT(); -// if ( nbtItem != null ) { -// nbtItem.setDouble( key, value ); -// nbtDebugLog( nbtItem, "setNBTDouble" ); -// } -// } - -// public boolean getNBTBoolean( String key ) { -// boolean results = false; -// -// NBTItem nbtItem = getNBT(); -// if ( nbtItem != null ) { -// results = nbtItem.getBoolean( key ); -// } -// return results; -// } -// public void setNBTBoolean( String key, boolean value ) { -// -// NBTItem nbtItem = getNBT(); -// if ( nbtItem != null ) { -// nbtItem.setBoolean( key, value ); -// nbtDebugLog( nbtItem, "setNBTBoolean" ); -// } -// } - + public String getNBTItemStackInfo() { + + String results = PrisonNBTUtil.nbtDebugString(getBukkitStack()); + + return results; + } -// -// public void setNbtString( org.bukkit.inventory.ItemStack bItemStack, String key, String value ) { -// NBTItem nbt = new NBTItem( bItemStack ); -// nbt.setString( key, value ); -// nbt.applyNBT( bItemStack ); -// } -// -// public String getNbtValue( org.bukkit.inventory.ItemStack bItemStack, String key ) { -// NBTItem nbt = new NBTItem( bItemStack ); -// return nbt.getString( key ); -// } -// /** *

    This function overrides the Prison's ItemStack class's setAmount() to perform the @@ -371,11 +239,14 @@ public void addToAmount( int i ) { private ItemMeta getMeta() { - ItemMeta meta; - if (!bukkitStack.hasItemMeta()) { - meta = Bukkit.getItemFactory().getItemMeta(bukkitStack.getType()); - } else { - meta = bukkitStack.getItemMeta(); + ItemMeta meta = null; + + if ( getBukkitStack() != null ) { + if (!getBukkitStack().hasItemMeta()) { + meta = Bukkit.getItemFactory().getItemMeta(getBukkitStack().getType()); + } else { + meta = getBukkitStack().getItemMeta(); + } } return meta; @@ -384,33 +255,43 @@ private ItemMeta getMeta() { @Override public void setDisplayName( String displayName ) { - ItemMeta meta = getMeta(); - if ( meta != null && displayName != null && displayName.trim().length() > 0 ) { + if ( getBukkitStack() != null ) { - meta.setDisplayName( Text.translateAmpColorCodes(displayName) ); + ItemMeta meta = getMeta(); + if ( meta != null && displayName != null && displayName.trim().length() > 0 ) { + + meta.setDisplayName( Text.translateAmpColorCodes(displayName) ); + + getBukkitStack().setItemMeta( meta ); + } } - - getBukkitStack().setItemMeta( meta ); super.setDisplayName( displayName ); } @Override public void setLore( List lores ) { - List updatedLores = new ArrayList<>(); - ItemMeta meta = getMeta(); - if ( meta != null && lores != null && lores.size() > 0 ) { + if ( getBukkitStack() != null ) { - for ( String lore : lores ) { - updatedLores.add( Text.translateAmpColorCodes(lore) ); + ItemMeta meta = getMeta(); + if ( meta != null && lores != null && lores.size() > 0 ) { + + List updatedLores = new ArrayList<>(); + + for ( String lore : lores ) { + updatedLores.add( Text.translateAmpColorCodes(lore) ); + } + + meta.setLore( updatedLores ); + + getBukkitStack().setItemMeta( meta ); + + getLore().addAll( updatedLores ); + } - - meta.setLore( updatedLores ); } - getBukkitStack().setItemMeta( meta ); - //super.setLore( updatedLores ); } @@ -434,10 +315,6 @@ public boolean isBlock() { if ( getBukkitStack() != null ) { results = getBukkitStack().getType().isBlock(); -// XMaterial xMat = XMaterial.matchXMaterial( getBukkitStack() ); -// if ( xMat != null ) { -// results = xMat.parseMaterial().isBlock(); -// } } return results; @@ -451,16 +328,10 @@ public org.bukkit.inventory.ItemStack getBukkitStack() { public void setBukkitStack( org.bukkit.inventory.ItemStack bukkitStack ) { this.bukkitStack = bukkitStack; -// this.nbtBukkitStack = null; setupBukkitStack( bukkitStack ); } - -// public NBTItem getNbtBukkitStack() { -// return nbtBukkitStack; -// } - @@ -515,31 +386,34 @@ public String getDebugInfo() { sb.append( getName() ); - ItemMeta meta = getMeta(); - if ( meta != null && - meta.getEnchants() != null && - meta.getEnchants().size() > 0 ) { - sb.append( " " ); + if ( getBukkitStack() != null ) { - StringBuilder sbE = new StringBuilder(); - Set keys = meta.getEnchants().keySet(); - for (Enchantment key : keys) { - if ( sbE.length() > 0 ) { - sbE.append(","); + ItemMeta meta = getMeta(); + if ( meta != null && + meta.getEnchants() != null && + meta.getEnchants().size() > 0 ) { + sb.append( " " ); + + StringBuilder sbE = new StringBuilder(); + Set keys = meta.getEnchants().keySet(); + for (Enchantment key : keys) { + if ( sbE.length() > 0 ) { + sbE.append(","); + } + String name = key.toString(); + name = name.substring(name.indexOf(" ") + 1, name.length() - 1); + + Integer level = meta.getEnchants().get(key); + sbE.append( name ); + sbE.append(":"); + sbE.append( level ); } - String name = key.toString(); - name = name.substring(name.indexOf(" ") + 1, name.length() - 1); - Integer level = meta.getEnchants().get(key); - sbE.append( name ); - sbE.append(":"); - sbE.append( level ); - } - - if ( sbE.length() > 0 ) { - sb.append("("); - sb.append( sbE ); - sb.append(")"); + if ( sbE.length() > 0 ) { + sb.append("("); + sb.append( sbE ); + sb.append(")"); + } } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bstats/PrisonBStats.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bstats/PrisonBStats.java index 6b36cc4eb..459289213 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bstats/PrisonBStats.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/bstats/PrisonBStats.java @@ -37,7 +37,6 @@ public class PrisonBStats { private List reportPermissions; private List reportEconomy; private List reportPlaceholders; -// private List reportVault; private List reportEnchantments; private List reportAdminTools; private List reportConflicts; @@ -57,7 +56,6 @@ public PrisonBStats( SpigotPrison spigotPrison ) { this.reportEconomy = new ArrayList<>(); this.reportPlaceholders = new ArrayList<>(); -// this.reportVault = new ArrayList<>(); this.reportEnchantments = new ArrayList<>(); this.reportAdminTools = new ArrayList<>(); this.reportConflicts = new ArrayList<>(); @@ -83,9 +81,6 @@ public void initMetricsOnLoad() { int pluginId = 657; setbStatsMetrics( new Metrics( spigotPrison, pluginId ) );; -// bStatsMetrics = new PrisonMetrics( this, pluginId ); - -// Metrics metrics = new Metrics( this, pluginId ); } public void initMetricsOnEnable() { @@ -98,7 +93,6 @@ public void initMetricsOnEnable() { int pluginId = 657; setbStatsMetrics( new Metrics( spigotPrison, pluginId ) ); -// bStatsMetrics = new PrisonMetrics( this, pluginId ); } // Report the modules being used @@ -145,7 +139,6 @@ public void initMetricsOnEnable() { int defaultRankCount = prisonRanks.getDefaultLadderRankCount(); -// int defaultRankCount = prisonRanksOpt.map(module -> ((PrisonRanks) module).getDefaultLadderRankCount()).orElse(0); return Integer.toString( defaultRankCount ); }) ); 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 5c8648c2c..4e48d0874 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 @@ -30,8 +30,6 @@ private void backpackMainCommand(CommandSender sender, if (sender.hasPermission("prison.admin") || sender.isOp()){ sender.dispatchCommand("backpack help"); -// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand("backpack help"); -// sender.dispatchCommand(registeredCmd); return; } @@ -278,79 +276,6 @@ 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(); -// } private boolean isDisabledWorld(Player p) { String worldName = p.getWorld().getName(); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java index 141a2b09a..1cc7be701 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotBaseCommands.java @@ -27,21 +27,21 @@ public MessagesConfig getMessages() { protected boolean isConfig( String configId ) { - String config = getConfig().getString( configId ); + String config = getConfig().getString( configId ); return config != null && config.equalsIgnoreCase( "true" ); } protected boolean isPrisonConfig( String configId ) { - return SpigotPrison.getInstance().isPrisonConfig( configId ); + return SpigotPrison.getInstance().isPrisonConfig( configId ); } protected String getConfig( String configId ) { - String config = getConfig().getString( configId ); - - return config == null ? "" : config; + String config = getConfig().getString( configId ); + + return config == null ? "" : config; } @@ -57,11 +57,11 @@ protected Player getSpigotPlayer( CommandSender sender ) { Player player = null; if ( sender instanceof SpigotCommandSender ) { - SpigotCommandSender cmdSender = (SpigotCommandSender) sender; - - if (cmdSender.getWrapper() instanceof Player) { - player = (Player) cmdSender.getWrapper(); - } + SpigotCommandSender cmdSender = (SpigotCommandSender) sender; + + if (cmdSender.getWrapper() instanceof Player) { + player = (Player) cmdSender.getWrapper(); + } } return player; } 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 index 8c8f3a7d8..fb113e0a2 100644 --- 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 @@ -76,7 +76,6 @@ private void backpackListGUICommand(CommandSender sender){ 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; } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java index c93825121..903ecfdee 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotGUICommands.java @@ -43,19 +43,16 @@ private void prisonManagerGUI(CommandSender sender) { Player player = getSpigotPlayer(sender); - if (player == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); - return; - } - - if (player.hasPermission("prison.admin")) { + if (player != null && player.hasPermission("prison.admin")) { SpigotPrisonGUI gui = new SpigotPrisonGUI(player); gui.open(); return; } // If the player will be shown the /gui help, then force close any open inventory: - player.closeInventory(); + if (player != null ) { + player.closeInventory(); + } sender.dispatchCommand("gui help"); } @@ -98,8 +95,8 @@ protected void cmdPrisonManagerPrestiges( CommandSender sender, int page, String if ( ranksModule == null || ranksModule != null && !ranksModule.isEnabled() ) { - Output.get().sendWarn( sender, "The command '/gui prestiges' is disabled because the Ranks module is not active." ); - return; + Output.get().sendWarn( sender, "The command '/gui prestiges' is disabled because the Ranks module is not active." ); + return; } Player player = getSpigotPlayer( sender ); @@ -111,7 +108,6 @@ protected void cmdPrisonManagerPrestiges( CommandSender sender, int page, String SpigotPlayerRanksGUI gui = new SpigotPlayerRanksGUI( player, "prestiges", page, cmdPage, cmdReturn ); -// SpigotPlayerPrestigesGUI gui = new SpigotPlayerPrestigesGUI( player, page, cmdPage, cmdReturn ); gui.open(); } @@ -123,7 +119,7 @@ private void prisonManagerMines(CommandSender sender, "page 1.", def = "1" ) int page ) { - cmdPrisonManagerMines( sender, page, "gui mines", "close" ); + cmdPrisonManagerMines( sender, page, "gui mines", "close" ); } protected void cmdPrisonManagerMines( CommandSender sender, int page, String cmdPage, String cmdReturn ) { @@ -169,35 +165,19 @@ private void prisonManagerAdminMines(CommandSender sender, } protected void cmdPrisonManagerAdminMines( CommandSender sender, int page, String cmdPage, String cmdReturn ) { - Player player = getSpigotPlayer(sender); - - if (player == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); - return; - } - - if ( !player.hasPermission("prison.admin") ) { + Player player = getSpigotPlayer(sender); + + if (player == null) { + Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); + return; + } + + if ( !player.hasPermission("prison.admin") ) { return; - } - -// if ( !isPrisonConfig("prison-gui-enabled") || !isConfig("Options.Mines.GUI_Enabled") ){ -// Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_mines_or_gui_disabled))); -// return; -// } - - -// if ( isConfig("Options.Mines.Permission_GUI_Enabled") ){ -// String perm = getConfig( "Options.Mines.Permission_GUI"); -// -// if ( !sender.hasPermission( perm ) ){ -// Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + -// perm + "]")); -// return; -// } -// } - - SpigotMinesGUI gui = new SpigotMinesGUI( player, page, cmdPage, cmdReturn ); - gui.open(); + } + + SpigotMinesGUI gui = new SpigotMinesGUI( player, page, cmdPage, cmdReturn ); + gui.open(); } @Command( identifier = "gui ranks", description = "GUI Ranks", @@ -241,8 +221,8 @@ protected void cmdPrisonManagerRanks(CommandSender sender, int page, String cmdP if ( module == null || module != null && !module.isEnabled() ) { - Output.get().sendWarn( sender, "The command '/gui ranks' is disabled because the Ranks module is not active." ); - return; + Output.get().sendWarn( sender, "The command '/gui ranks' is disabled because the Ranks module is not active." ); + return; } SpigotPlayerRanksGUI gui = new SpigotPlayerRanksGUI( player, "default", page, cmdPage, cmdReturn ); @@ -267,56 +247,40 @@ private void prisonManagerAdminRanks(CommandSender sender, } protected void cmdPrisonManagerAdminRanks(CommandSender sender, String ladder, int page, String cmdPage, String cmdReturn ) { - Player player = getSpigotPlayer(sender); - - if (player == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); - return; - } - - if ( !player.hasPermission("prison.admin") ) { - return; + Player player = getSpigotPlayer(sender); + + if (player == null) { + Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); + return; + } + + if ( !player.hasPermission("prison.admin") ) { + return; } - - + + Module ranksModule = Prison.get().getModuleManager().getModule( PrisonRanks.MODULE_NAME ); if ( ranksModule == null || ranksModule != null && !ranksModule.isEnabled() ) { - - Output.get().sendWarn( sender, "The command '/gui admin ranks' is disabled because the Ranks module is not active." ); - return; + + Output.get().sendWarn( sender, "The command '/gui admin ranks' is disabled because the Ranks module is not active." ); + return; } - // ladder - RankLadder rLadder = PrisonRanks.getInstance().getLadderManager().getLadder( ladder ); - if ( rLadder == null ) { - - SpigotPlayer sPlayer = new SpigotPlayer(player); - sPlayer.setActionBar( "Invalid ladder name" ); - player.closeInventory(); - return; - } + // ladder + RankLadder rLadder = PrisonRanks.getInstance().getLadderManager().getLadder( ladder ); + if ( rLadder == null ) { + + SpigotPlayer sPlayer = new SpigotPlayer(player); + sPlayer.setActionBar( "Invalid ladder name" ); + player.closeInventory(); + return; + } -// if (!isPrisonConfig("prison-gui-enabled") || !isConfig("Options.Ranks.GUI_Enabled")) { -// Output.get().sendInfo(sender, SpigotPrison.format(String.format(String.format( -// getMessages().getString(MessagesConfig.StringID.spigot_message_ranks_or_gui_disabled), -// getPrisonConfig("prison-gui-enabled"), getConfig("Options.Ranks.GUI_Enabled") )))); -// return; -// } -// -// if (isConfig("Options.Ranks.Permission_GUI_Enabled")) { -// String perm = getConfig( "Options.Ranks.Permission_GUI"); -// if (!sender.hasPermission(perm)) { -// -// Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_missing_permission) + " [" + -// perm + "]")); -// return; -// } -// } - SpigotRanksGUI gui = new SpigotRanksGUI( player, rLadder, page, cmdPage, cmdReturn ); - //SpigotPlayerRanksGUI gui = new SpigotPlayerRanksGUI( player, page, cmdPage, cmdReturn ); - gui.open(); + SpigotRanksGUI gui = new SpigotRanksGUI( player, rLadder, page, cmdPage, cmdReturn ); + //SpigotPlayerRanksGUI gui = new SpigotPlayerRanksGUI( player, page, cmdPage, cmdReturn ); + gui.open(); } @Command( identifier = "gui ladders", @@ -329,57 +293,48 @@ private void prisonManagerLadders(CommandSender sender, "page 1.", def = "1" ) int page ) { - cmdPrisonManagerLadders( sender, page, "gui ladders", "close" ); + cmdPrisonManagerLadders( sender, page, "gui ladders", "close" ); } protected void cmdPrisonManagerLadders(CommandSender sender, int page, String cmdPage, String cmdReturn ) { - Player player = getSpigotPlayer(sender); - - if (player == null) { - Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); - return; - } - - if (!isPrisonConfig("prison-gui-enabled") || !isConfig("Options.Ranks.GUI_Enabled")) { - Output.get().sendInfo(sender, SpigotPrison.format(String.format(String.format( - getMessages().getString(MessagesConfig.StringID.spigot_message_ranks_or_gui_disabled), - getPrisonConfig("prison-gui-enabled"), getConfig("Options.Ranks.GUI_Enabled") )))); - return; - } - - if (isConfig("Options.Ranks.Permission_GUI_Enabled")) { - String perm = getConfig( "Options.Ranks.Permission_GUI"); - if (!sender.hasPermission(perm)) { - - Output.get().sendInfo(sender, SpigotPrison.format( - getMessages().getString(MessagesConfig.StringID.spigot_message_missing_permission) -// + " [" + perm + "]" - )); - return; - } - } + Player player = getSpigotPlayer(sender); + + if (player == null) { + Output.get().sendInfo(sender, SpigotPrison.format( getMessages().getString(MessagesConfig.StringID.spigot_message_console_error))); + return; + } + + if (!isPrisonConfig("prison-gui-enabled") || !isConfig("Options.Ranks.GUI_Enabled")) { + Output.get().sendInfo(sender, SpigotPrison.format(String.format(String.format( + getMessages().getString(MessagesConfig.StringID.spigot_message_ranks_or_gui_disabled), + getPrisonConfig("prison-gui-enabled"), getConfig("Options.Ranks.GUI_Enabled") )))); + return; + } + + if (isConfig("Options.Ranks.Permission_GUI_Enabled")) { + String perm = getConfig( "Options.Ranks.Permission_GUI"); + if (!sender.hasPermission(perm)) { + + Output.get().sendInfo(sender, SpigotPrison.format( + getMessages().getString(MessagesConfig.StringID.spigot_message_missing_permission) + )); + return; + } + } Module ranksModule = Prison.get().getModuleManager().getModule( PrisonRanks.MODULE_NAME ); if ( ranksModule == null || ranksModule != null && !ranksModule.isEnabled() ) { - Output.get().sendWarn( sender, "The command '/gui ladders' is disabled because the Ranks module is not active." ); - return; + Output.get().sendWarn( sender, "The command '/gui ladders' is disabled because the Ranks module is not active." ); + return; } - SpigotLaddersGUI gui = new SpigotLaddersGUI( player, page, cmdPage, cmdReturn ); - gui.open(); + SpigotLaddersGUI gui = new SpigotLaddersGUI( player, page, cmdPage, cmdReturn ); + gui.open(); } -// @Command(identifier = "gui sellall", description = "SellAll GUI command", onlyPlayers = true) -// private void sellAllGuiCommandNew(CommandSender sender){ -// -// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall gui" ); -// sender.dispatchCommand(registeredCmd); -// } - - // Backpack GUI commands got moved to the Backpacks class so they won't be loaded if backpacks are disabled. @Command(identifier = "gui reload", description = "Reload GUIs and sellall", permissions = "prison.admin", 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 index e9bfee34c..69c8fefce 100644 --- 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 @@ -29,7 +29,6 @@ private void sellAllGuiCommand(CommandSender sender, 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; @@ -44,9 +43,7 @@ private void sellAllGuiCommand(CommandSender sender, // 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)); + new SpigotVariousGuiMessages().sellallGUIIsDisabledMsg(sender); } } } @@ -60,18 +57,18 @@ private void sellAllGuiBlocksCommand(CommandSender sender, "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(); + 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/PrisonSpigotMinesCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotMinesCommands.java index a68113bdc..6dc16381f 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotMinesCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotMinesCommands.java @@ -22,19 +22,18 @@ public void minesGUICommand(CommandSender sender, if (isPrisonConfig("prison-gui-enabled") && isConfig("Options.Mines.GUI_Enabled")){ - Object regCommand = Prison.get().getCommandHandler() - .getRegisteredCommandClass( PrisonSpigotGUICommands.class ); - if ( regCommand != null ) { - PrisonSpigotGUICommands psGUICmd = (PrisonSpigotGUICommands) regCommand; - psGUICmd.cmdPrisonManagerMines( sender, page, "gui mines", "close" ); - - return; - } -// sender.dispatchCommand("gui mines"); + Object regCommand = Prison.get().getCommandHandler() + .getRegisteredCommandClass( PrisonSpigotGUICommands.class ); + if ( regCommand != null ) { + PrisonSpigotGUICommands psGUICmd = (PrisonSpigotGUICommands) regCommand; + psGUICmd.cmdPrisonManagerMines( sender, page, "gui mines", "close" ); + + return; + } } else { - sender.dispatchCommand("mines help"); + sender.dispatchCommand("mines help"); } } else { 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 688191607..77424fe24 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 @@ -37,8 +37,8 @@ public void prestigesGUICommand(CommandSender sender) { if ( ranksModule == null || ranksModule != null && !ranksModule.isEnabled() ) { - Output.get().sendWarn( sender, "The command '/prestiges' is disabled because the Ranks module is not active." ); - return; + Output.get().sendWarn( sender, "The command '/prestiges' is disabled because the Ranks module is not active." ); + return; } if ( isConfig( "Options.Prestiges.GUI_Enabled") ) { @@ -61,134 +61,25 @@ public void prisonManagerPrestige(CommandSender sender, "shown in the prestige confirmation GUI. This should not be used directly." ) String lores) { - if ( lores == null || lores.trim().length() == 0 ) { - sender.sendMessage( "Invalid use of `/gui prestigeConfirm`. Please use `/prestige` instead." ); - return; - } - - List lore = new ArrayList<>(); - - for ( String loreRaw : lores.split( " " ) ) { - String loreValue = loreRaw.replace( "_", " ").trim(); - if ( loreValue.length() > 0 ) { - lore.add( loreValue ); - } - } - - Player player = getSpigotPlayer( sender ); - + if ( lores == null || lores.trim().length() == 0 ) { + sender.sendMessage( "Invalid use of `/gui prestigeConfirm`. Please use `/prestige` instead." ); + return; + } + + List lore = new ArrayList<>(); + + for ( String loreRaw : lores.split( " " ) ) { + String loreValue = loreRaw.replace( "_", " ").trim(); + if ( loreValue.length() > 0 ) { + lore.add( loreValue ); + } + } + + Player player = getSpigotPlayer( sender ); + SpigotConfirmPrestigeGUI gui = new SpigotConfirmPrestigeGUI( player, lore ); gui.open(); } - -// @Command(identifier = "prestige", onlyPlayers = true) -// public void prestigesPrestigeCommand(CommandSender sender) { -// -// if ( isPrisonConfig( "prestiges" ) || isPrisonConfig( "prestige.enabled" ) ) { -// -// -// Optional ranksModule = Prison.get().getModuleManager().getModule( PrisonRanks.MODULE_NAME ); -// if ( !ranksModule.isPresent() || ranksModule.isPresent() && !ranksModule.get().isEnabled() ) { -// -// Output.get().sendWarn( sender, "The command '/prestige' is disabled because the Ranks module is not active." ); -// return; -// } -// -// -// prisonManagerPrestige(sender); -// } -// } - -// @Command( identifier = "gui prestige", description = "GUI Prestige", -// aliases = {"prisonmanager prestige"} ) -// public void prisonManagerPrestige(CommandSender sender ) { -// -// if ( isPrisonConfig( "prestige.enabled" ) ) { -// -// -// Optional ranksModule = Prison.get().getModuleManager().getModule( PrisonRanks.MODULE_NAME ); -// if ( !ranksModule.isPresent() || ranksModule.isPresent() && !ranksModule.get().isEnabled() ) { -// -// Output.get().sendWarn( sender, "The command '/gui prestiges' is disabled because the Ranks module is not active." ); -// return; -// } -// -// if ( PrisonRanks.getInstance().getLadderManager().getLadder("prestiges") == null ) { -// Bukkit.dispatchCommand(Bukkit.getConsoleSender(), -// Prison.get().getCommandHandler().findRegisteredCommand( "ranks ladder create prestiges" )); -// } -// -// PrisonRanks rankPlugin; -// -// ModuleManager modMan = Prison.get().getModuleManager(); -// Module module = modMan == null ? null : modMan.getModule( PrisonRanks.MODULE_NAME ).orElse( null ); -// -// if ( module != null ) { -// -// rankPlugin = (PrisonRanks) module; -// -// LadderManager lm = null; -// if (rankPlugin != null) { -// lm = rankPlugin.getLadderManager(); -// -// RankLadder ladderDefault = lm.getLadder("default"); -// if ( ( ladderDefault == null || -// !(ladderDefault.getLowestRank().isPresent()) || -// ladderDefault.getLowestRank().get().getName() == null)) { -// Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_ladder_default_empty))); -// return; -// } -// -// RankLadder ladderPrestiges = lm.getLadder("prestiges"); -// if ( ( ladderPrestiges == null || -// !(ladderPrestiges.getLowestRank().isPresent()) || -// ladderPrestiges.getLowestRank().get().getName() == null)) { -// Output.get().sendInfo(sender, SpigotPrison.format(messages.getString(MessagesConfig.StringID.spigot_message_prestiges_empty))); -// return; -// } -// } -// -// -// if ( isPrisonConfig( "prestige.confirmation-enabled") && isPrisonConfig( "prestige.prestige-confirm-gui") ) { -// try { -// -// Player player = getSpigotPlayer( sender ); -// -// SpigotConfirmPrestigeGUI gui = new SpigotConfirmPrestigeGUI( player ); -// gui.open(); -// } catch (Exception ex) { -// prestigeByChat( sender ); -// } -// } -// else if ( isPrisonConfig( "prestige.confirmation-enabled") ) { -// prestigeByChat( sender ); -// } -// else { -// // Bypassing prestige confirmations: -// Bukkit.dispatchCommand(Bukkit.getConsoleSender(), -// Prison.get().getCommandHandler().findRegisteredCommand( "rankup prestiges" )); -// } -// } -// } -// else { -// sender.sendMessage( "Prestiges are disabled. Refresh and then reconfigure config.yml and try again." ); -// } -// } - -// private void prestigeByChat(CommandSender sender) { -// -// ListenersPrisonManager listenersPrisonManager = ListenersPrisonManager.get(); -// listenersPrisonManager.chatEventActivator(); -// -// Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_gui_lore_prestige_warning_1) + " " -// + messages.getString(MessagesConfig.StringID.spigot_gui_lore_prestige_warning_2) + " " + messages.getString(MessagesConfig.StringID.spigot_gui_lore_prestige_warning_3)); -// -// Output.get().sendInfo(sender, "&a" + messages.getString(MessagesConfig.StringID.spigot_message_prestiges_confirm)); -// Output.get().sendInfo(sender, "&c" + messages.getString(MessagesConfig.StringID.spigot_message_prestiges_cancel)); -// -// final Player player = getSpigotPlayer( sender ); -// listenersPrisonManager.chatInteractData(player, ListenersPrisonManager.ChatMode.Prestige); -// } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotRanksCommands.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotRanksCommands.java index 608a0bcd4..48097002a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotRanksCommands.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/commands/PrisonSpigotRanksCommands.java @@ -33,8 +33,8 @@ public void ranksGUICommand(CommandSender sender, if ( ranksModule == null || ranksModule != null && !ranksModule.isEnabled() ) { - Output.get().sendWarn( sender, "The command '/ranks' is disabled because the Ranks module is not active." ); - return; + Output.get().sendWarn( sender, "The command '/ranks' is disabled because the Ranks module is not active." ); + return; } if (!sender.hasPermission("ranks.admin")) { @@ -52,15 +52,14 @@ public void ranksGUICommand(CommandSender sender, if ((ladderName.equalsIgnoreCase("default") || ladderName.equalsIgnoreCase("ranks")) && isConfig("Options.Ranks.GUI_Enabled")) { - Object regCommand = Prison.get().getCommandHandler() - .getRegisteredCommandClass( PrisonSpigotGUICommands.class ); - if ( regCommand != null ) { - PrisonSpigotGUICommands psGUICmd = (PrisonSpigotGUICommands) regCommand; - psGUICmd.cmdPrisonManagerRanks( sender, page, "ranks", "close" ); - return; - } + Object regCommand = Prison.get().getCommandHandler() + .getRegisteredCommandClass( PrisonSpigotGUICommands.class ); + if ( regCommand != null ) { + PrisonSpigotGUICommands psGUICmd = (PrisonSpigotGUICommands) regCommand; + psGUICmd.cmdPrisonManagerRanks( sender, page, "ranks", "close" ); + return; + } -// sender.dispatchCommand("gui ranks"); } else if (ladderName.equalsIgnoreCase("prestiges") && isConfig( "Options.Prestiges.GUI_Enabled")) { @@ -72,7 +71,6 @@ public void ranksGUICommand(CommandSender sender, return; } -// sender.dispatchCommand("gui 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 73e671b1b..6562aa3b3 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 @@ -1,6 +1,5 @@ package tech.mcprison.prison.spigot.commands; -import java.lang.reflect.Method; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; @@ -16,6 +15,7 @@ import tech.mcprison.prison.Prison; import tech.mcprison.prison.PrisonAPI; +import tech.mcprison.prison.bombs.MineBombs; import tech.mcprison.prison.commands.Arg; import tech.mcprison.prison.commands.Command; import tech.mcprison.prison.commands.Wildcard; @@ -34,9 +34,11 @@ import tech.mcprison.prison.spigot.configs.MessagesConfig; import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.game.SpigotPlayerUtil; +import tech.mcprison.prison.spigot.nbt.PrisonNBTUtil; import tech.mcprison.prison.spigot.sellall.SellAllBlockData; import tech.mcprison.prison.spigot.sellall.SellAllUtil; import tech.mcprison.prison.spigot.utils.tasks.PlayerAutoRankupTask; +import tech.mcprison.prison.util.Text; /** * @author GABRYCA @@ -53,7 +55,7 @@ public class PrisonSpigotSellAllCommands extends PrisonSpigotBaseCommands { * */ public static boolean isEnabled() { - return SpigotPrison.getInstance().isSellAllEnabled(); + return SpigotPrison.getInstance().isSellAllEnabled(); } /** @@ -98,13 +100,9 @@ private void sellAllCommands(CommandSender sender) { } if (sender.hasPermission("prison.admin")) { - sender.dispatchCommand("sellall help"); -// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall help" ); -// sender.dispatchCommand(registeredCmd); + sender.dispatchCommand("sellall help"); } else { - sender.dispatchCommand("sellall sell"); -// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall sell" ); -// sender.dispatchCommand(registeredCmd); + sender.dispatchCommand("sellall sell"); } } @@ -119,7 +117,7 @@ private void sellAllDelay(CommandSender sender, def = "false") String enable){ if ( !isEnabled() ){ - return; + return; } SellAllUtil sellAllUtil = SellAllUtil.get(); @@ -186,7 +184,7 @@ private void sellAllAutoSell(CommandSender sender, def = "true") String enable){ if ( !isEnabled() ){ - return; + return; } SellAllUtil sellAllUtil = SellAllUtil.get(); @@ -201,7 +199,7 @@ private void sellAllAutoSell(CommandSender sender, } boolean enableBoolean = getBoolean(enable); - if (sellAllUtil.isAutoSellEnabled == enableBoolean){ + if ( SellAllUtil.isAutoSellEnabled() == enableBoolean ) { if (enableBoolean){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_already_enabled)); } else { @@ -233,7 +231,7 @@ private void sellAllAutoSellPerUserToggleable(CommandSender sender, def = "") String enable){ if (!isEnabled() ){ - return; + return; } SellAllUtil sellAllUtil = SellAllUtil.get(); @@ -270,7 +268,7 @@ public void sellAllSellCommand(CommandSender sender, "'silent' suppresses all notifications. [silent]") String notification ){ if ( !isEnabled() ) { - return; + return; } Player p = getSpigotPlayer(sender); @@ -280,35 +278,35 @@ public void sellAllSellCommand(CommandSender sender, 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 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(); + // 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 sell %s]", playerName ); - } - else { - - Output.get().sendInfo(sender, "&cSorry but you can't use that from the console!"); - } + if ( getPlayerByName( playerName ) != null ) { + + sender.sendMessage( String.format( "&cSorry but the specified player must be online " + + "[/sellall sell %s]", playerName ) ); + } + else { + + sender.sendMessage( "&cSorry but you can't use that command from the console."); + } return; @@ -320,22 +318,22 @@ else if (p == null){ } SellAllUtil sellAllUtil = SellAllUtil.get(); -// if (sellAllUtil.isPlayerInDisabledWorld(p)) return; if (sellAllUtil.isSellAllSellPermissionEnabled){ String permission = sellAllUtil.permissionSellAllSell; if (permission == null || !p.hasPermission(permission)){ - Output.get().sendWarn(new SpigotPlayer(p), + sender.sendMessage( messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) -// + " [" + permission + "]" ); return; } } boolean notifications = (notification != null && "silent".equalsIgnoreCase( notification )); - - sellAllUtil.sellAllSell(p, false, notifications, true, true, false, true); + boolean delayNotifications = false; + boolean delayNotificationsEarnings = false; + + sellAllUtil.sellAllSell(p, false, notifications, true, delayNotifications, delayNotificationsEarnings, true); SpigotPlayer sPlayer = new SpigotPlayer( p ); PlayerAutoRankupTask.autoSubmitPlayerRankupTask( sPlayer, null ); @@ -352,25 +350,22 @@ public void sellAllSellHandCommand(CommandSender sender){ SellAllUtil sellAllUtil = SellAllUtil.get(); if (!sellAllUtil.isSellAllHandEnabled){ - Output.get().sendWarn(sender, "The command /sellall hand is disabled from the config!"); + sender.sendMessage( "The command /sellall hand is disabled from the config!"); return; } Player p = getSpigotPlayer(sender); if (p == null){ - Output.get().sendInfo(sender, "&cSorry but you can't use that from the console!"); + sender.sendMessage( "&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), + sender.sendMessage( messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) -// + " [" + permission + "]" ); return; } @@ -399,14 +394,11 @@ public void sellAllSell(Player p){ } -// 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; } @@ -431,7 +423,7 @@ public void sellAllValueOfCommand(CommandSender sender, ){ if ( !isEnabled() ) { - return; + return; } SellAllUtil sellAllUtil = SellAllUtil.get(); @@ -441,35 +433,32 @@ public void sellAllValueOfCommand(CommandSender 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(); + // 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 ) { + if ( getPlayerByName( playerName ) != null ) { - Output.get().sendInfo(sender, "&cSorry but the specified player must be online " - + "[/sellall valueOf %s]", playerName ); + sender.sendMessage( + String.format( "&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!"); + sender.sendMessage( "&cSorry but you can't use that from the console!"); } @@ -477,14 +466,11 @@ else if (p == null){ } -// if (sellAllUtil.isPlayerInDisabledWorld(p)) return; - if (sellAllUtil.isSellAllSellPermissionEnabled){ String permission = sellAllUtil.permissionSellAllSell; if (permission == null || !p.hasPermission(permission)){ - Output.get().sendWarn(new SpigotPlayer(p), + sender.sendMessage( messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) -// + " [" + permission + "]" ); return; } @@ -511,25 +497,23 @@ public void sellAllValueOfHandCommand(CommandSender sender){ SellAllUtil sellAllUtil = SellAllUtil.get(); if (!sellAllUtil.isSellAllHandEnabled){ - Output.get().sendWarn(sender, "The command `/sellall valueOfHand` is disabled from the config! (SellAllHandEnabled)"); + sender.sendMessage( "The command `/sellall valueOfHand` is disabled in the configs! (SellAllHandEnabled)"); return; } Player p = getSpigotPlayer(sender); if (p == null){ - Output.get().sendInfo(sender, "&cSorry but you can't use that from the console!"); + sender.sendMessage( "&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), + sender.sendMessage( messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) -// + " [" + permission + "]" ); return; } @@ -553,7 +537,7 @@ public void sellAllValueOfHandCommand(CommandSender sender){ public void sellAllSellWithDelayCommand(CommandSender sender){ if ( !isEnabled() ) { - return; + return; } SellAllUtil sellAllUtil = SellAllUtil.get(); @@ -565,14 +549,11 @@ public void sellAllSellWithDelayCommand(CommandSender sender){ } -// 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; } @@ -600,7 +581,7 @@ public void sellAllSellWithDelayCommand(CommandSender sender){ private void sellAllAutoEnableUser(CommandSender sender){ if ( !isEnabled() ) { - return; + return; } StringBuilder debugInfo = new StringBuilder(); debugInfo.append( "[sellall autoSellToggle] " ); @@ -617,20 +598,15 @@ private void sellAllAutoEnableUser(CommandSender sender){ } -// if (sellAllUtil.isPlayerInDisabledWorld(p)) return; - if (!sellAllUtil.isAutoSellPerUserToggleable){ return; } boolean hasAutosellPerms = sPlayer.checkAutoSellTogglePerms( debugInfo ); -// String permission = sellAllUtil.permissionAutoSellPerUserToggleable; if ( sellAllUtil.isAutoSellPerUserToggleablePermEnabled && !hasAutosellPerms ) { -// if (sellAllUtil.isAutoSellPerUserToggleablePermEnabled && (permission != null && !p.hasPermission(permission))){ Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) -// + " [" + permission + "]" ); return; } @@ -640,12 +616,12 @@ private void sellAllAutoEnableUser(CommandSender sender){ if ( isplayerAutosellEnabled ){ String msg = messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_disabled); - Output.get().sendInfo( sPlayer, msg ); + Output.get().sendInfo( sPlayer, msg ); } else { - String msg = messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_enabled); - - Output.get().sendInfo( sPlayer, msg ); + String msg = messages.getString(MessagesConfig.StringID.spigot_message_sellall_auto_enabled); + + Output.get().sendInfo( sPlayer, msg ); } } @@ -653,65 +629,6 @@ private void sellAllAutoEnableUser(CommandSender sender){ Output.get().logInfo( debugInfo.toString() ); } } -// -// @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 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. " @@ -725,45 +642,110 @@ private void sellAllAddCommand(CommandSender sender, @Arg(name = "Value", description = "The value of the item.") Double value){ if ( !isEnabled() ){ - return; + return; } SellAllUtil sellAllUtil = SellAllUtil.get(); if (itemID == null){ - Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); + sender.sendMessage( messages.getString( + MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); return; } itemID = itemID.toUpperCase(); if (value == null){ - Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_price)); + sender.sendMessage( messages.getString( + MessagesConfig.StringID.spigot_message_sellall_item_missing_price)); return; } if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) != null){ - Output.get().sendWarn(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_already_added)); + sender.sendMessage( itemID + " " + + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_already_added)); return; } - try { - XMaterial blockAdd; - try { - blockAdd = XMaterial.matchXMaterial(itemID).orElse(null); - } catch (IllegalArgumentException ex){ - Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); - return; - } - - if (sellAllUtil.addSellAllBlock(blockAdd, value)){ - Output.get().sendInfo(sender, "&3 ITEM [" + itemID + ", " + value + "] " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_add_success)); - } - - } catch (IllegalArgumentException ex){ - Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); + if (sellAllUtil.addSellAllBlock( itemID, null, value )) { + sender.sendMessage( "&3 ITEM [" + itemID + ", " + value + "] " + + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_add_success)); } + } + + + @Command(identifier = "sellall items addHand", + description = "Adds an item that the player is holding to sellall ", + permissions = "prison.admin", + onlyPlayers = false) + private void sellAllAddHandItemCommand(CommandSender sender, + @Arg(name = "Value", description = "The value of the item.") Double value ) { + + if ( !isEnabled() ) { + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); + + + SpigotPlayer sPlayer = (SpigotPlayer) sender.getPlatformPlayer(); + + if ( sPlayer == null ) { + String msg = String.format( + "Only online players can add what they're holding." + ); + sender.sendMessage(msg); + } + else { + + SpigotPlayerUtil sUtil = new SpigotPlayerUtil( sPlayer ); + + SpigotItemStack iStack = sUtil.getItemInHand(); + + if ( iStack == null || iStack.isAir() ) { + + String msg = String.format( + "Nothing to add to sellall. You're not holding anything other than air." + ); + sender.sendMessage(msg); + } + else { + + if (value == null){ + sender.sendMessage( messages.getString( + MessagesConfig.StringID.spigot_message_sellall_item_missing_price)); + return; + } + + + PrisonBlock pBlock = iStack.getMaterial(); + + String displayName = iStack.getDisplayName(); + if ( displayName != null && displayName.trim().length() > 0 ) { + pBlock.setDisplayName( displayName.trim() ); + } + + String sellallName = pBlock.getBlockNameSearch(); + + + if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + sellallName.toUpperCase()) != null){ + sender.sendMessage( sellallName + " " + + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_already_added)); + return; + } + + + + if (sellAllUtil.addSellAllBlock( sellallName, value, pBlock )){ + sender.sendMessage( "&3 ITEM [" + sellallName + ", " + value + "] " + + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_add_success)); + } + + + } + } + } + /** *

    This will add the XMaterial and value to the sellall. * This will update even if the sellall has not been enabled. @@ -788,7 +770,8 @@ public void sellAllAddCommand(XMaterial blockAdd, Double value){ if (sellAllUtil.addSellAllBlock(blockAdd, value)) return; - Output.get().logInfo("&3 ITEM [" + itemID + ", " + value + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_add_success)); + Output.get().logInfo("&3 ITEM [" + itemID + ", " + value + "] " + + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_add_success)); } @Command(identifier = "sellall items delete", @@ -796,10 +779,10 @@ public void sellAllAddCommand(XMaterial blockAdd, Double value){ + "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){ + @Arg(name = "Item_ID", description = "The Item_ID you want to remove.") String itemID ) { if ( !isEnabled() ) { - return; + return; } SellAllUtil sellAllUtil = SellAllUtil.get(); @@ -815,11 +798,10 @@ private void sellAllDeleteCommand(CommandSender sender, return; } - if (XMaterial.matchXMaterial(itemID).isPresent()) { - if (sellAllUtil.removeSellAllBlock(XMaterial.matchXMaterial(itemID).get())) { - Output.get().sendInfo(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_delete_success)); - } + if (sellAllUtil.removeSellAllBlock(itemID)) { + Output.get().sendInfo(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_delete_success)); } + } @Command(identifier = "sellall items edit", @@ -830,7 +812,7 @@ private void sellAllEditCommand(CommandSender sender, @Arg(name = "Value", description = "The value of the item.") Double value){ if ( !isEnabled() ) { - return; + return; } SellAllUtil sellAllUtil = SellAllUtil.get(); @@ -851,20 +833,11 @@ private void sellAllEditCommand(CommandSender sender, return; } - try { - XMaterial blockAdd; - try{ - blockAdd = XMaterial.matchXMaterial(itemID).orElse(null); - } catch (IllegalArgumentException ex){ - Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); - return; - } - - if (sellAllUtil.editPrice(blockAdd, value)){ - Output.get().sendInfo(sender, "&3ITEM [" + itemID + ", " + value + "] " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_edit_success)); - } - - } catch (IllegalArgumentException ex){ + if ( sellAllUtil.editPrice( itemID, null, value ) ){ + Output.get().sendInfo(sender, "&3ITEM [" + itemID + ", " + value + "] " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_edit_success)); + } + else { + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); } } @@ -882,194 +855,243 @@ private void sellAllAllowLoreCommand(CommandSender sender, def = "false") String isLoreAllowed ){ - if ( !isEnabled() ) { - return; - } - SellAllUtil sellAllUtil = SellAllUtil.get(); - - if (itemID == null){ - Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); - return; - } - itemID = itemID.toUpperCase(); - - - if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) == null){ - Output.get().sendWarn(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_not_found)); - return; - } - - boolean allowLore = false; - - if ( isLoreAllowed != null && - ("true".equalsIgnoreCase(isLoreAllowed) || "allow".equalsIgnoreCase(isLoreAllowed)) ) { - allowLore = true; - } - - -// sender.sendMessage("not yet enabled"); -// return; - - try { - XMaterial blockAdd; - try { - blockAdd = XMaterial.matchXMaterial(itemID).orElse(null); - } catch (IllegalArgumentException ex){ - Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); - return; - } + if ( !isEnabled() ) { + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); + + if (itemID == null){ + Output.get().sendWarn(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_missing_name)); + return; + } + itemID = itemID.toUpperCase(); + + + if (sellAllUtil.sellAllConfig.getConfigurationSection("Items." + itemID) == null){ + Output.get().sendWarn(sender, itemID + " " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_not_found)); + return; + } + + boolean allowLore = false; + + if ( isLoreAllowed != null && + ("true".equalsIgnoreCase(isLoreAllowed) || "allow".equalsIgnoreCase(isLoreAllowed)) ) { + allowLore = true; + } + - if (sellAllUtil.editAllowLore(blockAdd, allowLore )) { - - Output.get().sendInfo(sender, "&3ITEM [" + itemID + ", allowLore= " + allowLore + "] " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_edit_success)); - } - - } catch (IllegalArgumentException ex){ - Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); - } + + try { + + PrisonBlock pBlock = Prison.get().getPlatform().getPrisonBlock( itemID ); + + + if (sellAllUtil.editAllowLore( pBlock, allowLore )) { + + Output.get().sendInfo(sender, "&3ITEM [" + itemID + ", allowLore= " + allowLore + "] " + messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_edit_success)); + } + + } catch (IllegalArgumentException ex){ + Output.get().sendError(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_item_id_not_found) + " [" + itemID + "]"); + } } - @Command(identifier = "sellall items inspect", description = "Inspects what the player is holding and provides a dump of all related " + "information.", permissions = "prison.admin", onlyPlayers = false) private void sellAllItemInspectCommand(CommandSender sender) { - if ( !isEnabled() ) { - return; - } - SellAllUtil sellAllUtil = SellAllUtil.get(); - - - SpigotPlayer sPlayer = (SpigotPlayer) sender.getPlatformPlayer(); - - if ( sPlayer == null ) { - String msg = String.format( - "Only online players can see what they're holding." - ); - sender.sendMessage(msg); - } - else { - - SpigotPlayerUtil sUtil = new SpigotPlayerUtil( sPlayer ); - - SpigotItemStack iStack = sUtil.getItemInHand(); - - if ( iStack == null || iStack.isAir() ) { - - String msg = String.format( - "Nothing to report. You're not holding anything other than air." - ); - sender.sendMessage(msg); - } - else { - - - ChatDisplay chatDisplay = new ChatDisplay("&bSellall Items inspect: " ); - - List msg = new ArrayList<>(); - - String name = iStack.getName(); - String nameFull = iStack.getDisplayName() == null ? "" : iStack.getDisplayName(); - - PrisonBlock pBlock = iStack.getMaterial(); - - int amount = iStack.getAmount(); - - List lore = iStack.getLore(); - Map enchants = iStack.getEnchantments(); - - String nbtInfo = iStack.getNBTItemStackInfo(); - - - chatDisplay.addText( "Item: %-14s (%s)", name, nameFull ); - chatDisplay.addText( "Qty: %5s PrisonItem: %s", - Integer.toString(amount), pBlock.getBlockNameFormal() ); - - if ( lore.size() == 0 ) { - - chatDisplay.addText( "No Lore." ); - } - else { - chatDisplay.addText( "Lore:" ); - - for (String l : lore) { - chatDisplay.addText( " %s", l ); - } - } - - if ( enchants == null || enchants.size() == 0 ) { - - chatDisplay.addText( "No Enchantments." ); - } - else { - chatDisplay.addText( "Enchantments:" ); - - Set keys = enchants.keySet(); - for (Enchantment ench : keys ) { - - Integer value = enchants.get( ench ); - - String namespace = ""; - String targetName = ""; - - try { - - // NOTE: This is for spigot 1.13.x and higher: - if ( ench.getClass().getMethod( "getKey" ) != null ) { - namespace = ench.getKey() == null ? - "---" : - ench.getKey().toString(); - } - else if ( ench.getClass().getMethod( "getName" ) != null ) { - // Versions of spigot prior to 1.13.x: - namespace = ench.getName(); - - } - - - if ( ench.getClass().getMethod( "getItemTarget" ) != null && - ench.getItemTarget() != null ) { - targetName = ench.getItemTarget().name(); - } - - } catch (Exception e) { - } - - if ( namespace == null || namespace.trim().length() == 0 ) { - namespace = ench.toString(); - } - - chatDisplay.addText( " %-10s %s %s (%s - %s)", - //ench.toString(), - namespace, - targetName, - - value.toString(), - Integer.toString( ench.getStartLevel()), - Integer.toString( ench.getMaxLevel()) - ); + if ( !isEnabled() ) { + return; + } + SellAllUtil sellAllUtil = SellAllUtil.get(); + + + SpigotPlayer sPlayer = (SpigotPlayer) sender.getPlatformPlayer(); + + if ( sPlayer == null ) { + String msg = String.format( + "Only online players can see what they're holding." + ); + sender.sendMessage(msg); + } + else { + + SpigotPlayerUtil sUtil = new SpigotPlayerUtil( sPlayer ); + + SpigotItemStack iStack = sUtil.getItemInHand(); + + if ( iStack == null || iStack.isAir() ) { + + String msg = String.format( + "Nothing to report. You're not holding anything other than air." + ); + sender.sendMessage(msg); + } + else { + + PrisonBlock pBlock = iStack.getMaterial(); + boolean iStackHasLore = iStack.getLore() != null && iStack.getLore().size() > 0; + + ChatDisplay chatDisplay = new ChatDisplay("&bSellall Items inspect: " ); + + List msg = new ArrayList<>(); + + String name = iStack.getName(); + String nameSellall = pBlock.getBlockNameSearch(); + String nameFull = iStack.getDisplayName() == null ? "" : + "(" + Text.stripColor( iStack.getDisplayName()) + ")"; + + + int amount = iStack.getAmount(); + + List lore = iStack.getLore(); + + Map enchants = iStack.getEnchantments(); + + String nbtInfo = iStack.getNBTItemStackInfo(); + + + + chatDisplay.addText( "Item: %-14s %s", name, nameFull ); + chatDisplay.addText( "Sellall Name: &7%s &3(use this value when adding to sellall)", nameSellall ); + + + PrisonBlock sellallItem = sellAllUtil.getSellAllItems().get( nameSellall ); + boolean sellallItemAllowLore = sellallItem != null && sellallItem.isLoreAllowed(); + + if ( sellallItem != null && iStackHasLore == sellallItemAllowLore ) { + + String itemPrice = sellallItem.getSalePrice() == null ? "---" : + Prison.getDecimalFormatStaticInt().format( + sellallItem.getSalePrice().doubleValue() ); + chatDisplay.addText( " Item Price: &7%s", itemPrice ); + + if ( sellallItem.getPurchasePrice() != null ) { + + String purchasePrice = sellallItem.getPurchasePrice() == null ? "---" : + Prison.getDecimalFormatStaticInt().format( + sellallItem.getPurchasePrice().doubleValue() ); + chatDisplay.addText( " Purchase Price: &7%s", purchasePrice ); + } + + if ( sellallItem.isLoreAllowed() ) { + + chatDisplay.addText( " Allow Lore when sold: &7true" ); + } + } + + + chatDisplay.addText( "Quanty: %5s PrisonItem: %s", + Integer.toString(amount), pBlock.getBlockNameFormal() ); + + if ( lore.size() == 0 ) { + + chatDisplay.addText( "No Lore." ); + } + else { + chatDisplay.addText( "Lore:" ); + + for (String l : lore) { + String loreEscaped = l.replace(Text.COLOR_CHAR, '&'); + + chatDisplay.addText( " %s :: [\\Q%s\\E]", l, loreEscaped ); + } + } + + if ( enchants == null || enchants.size() == 0 ) { + + chatDisplay.addText( "No Enchantments." ); + } + else { + chatDisplay.addText( "Enchantments:" ); + + Set keys = enchants.keySet(); + for (Enchantment ench : keys ) { + + Integer value = enchants.get( ench ); + + String namespace = ""; + String targetName = ""; + + try { + + // NOTE: This is for spigot 1.13.x and higher: + if ( ench.getClass().getMethod( "getKey" ) != null ) { + namespace = ench.getKey() == null ? + "---" : + ench.getKey().toString(); + } + else if ( ench.getClass().getMethod( "getName" ) != null ) { + // Versions of spigot prior to 1.13.x: + namespace = ench.getName(); + + } + + + if ( ench.getClass().getMethod( "getItemTarget" ) != null && + ench.getItemTarget() != null ) { + targetName = ench.getItemTarget().name(); + } + + } catch (Exception e) { + } + + if ( namespace == null || namespace.trim().length() == 0 ) { + namespace = ench.toString(); + } + + chatDisplay.addText( " %-10s %s %s (%s - %s)", + //ench.toString(), + namespace, + targetName, + + value.toString(), + Integer.toString( ench.getStartLevel()), + Integer.toString( ench.getMaxLevel()) + ); } - - - } - - if ( nbtInfo == null || nbtInfo.trim().length() == 0 ) { - - chatDisplay.addText( " No NBT." ); - } - else { - - chatDisplay.addText( " %s", nbtInfo ); - } -// chatDisplay.addText( " ", ); - - chatDisplay.send( sender );; - } - - } + + + } + + + try { + String bombName = PrisonNBTUtil.getNBTString( iStack.getBukkitStack(), + MineBombs.MINE_BOMBS_NBT_KEY ); + + if ( bombName != null && bombName.trim().length() == 0 ) { + bombName = null; + } + + if ( bombName != null ) { + chatDisplay.addText( " Mine Bomb Name: %s", bombName ); + + } + } + catch (Exception | Error e) { + // Ignore... not a mine bomb. + } + + + if ( nbtInfo == null || nbtInfo.trim().length() == 0 ) { + + chatDisplay.addText( " No NBT." ); + } + else { + + chatDisplay.addText( " %s", nbtInfo ); + } + + chatDisplay.send( sender ); + + // Send to the console too: + chatDisplay.sendtoOutputLogInfo(); + } + + } } @Command(identifier = "sellall multiplier list", @@ -1094,17 +1116,17 @@ private void sellAllMultiplierCommand(CommandSender sender, } - if ( !PrisonRanks.getInstance().isEnabled() ) { - Output.get().sendWarn(sender, "Cannot use command `/sellall multiplier addLadder` since ranks 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; + - int displayColumns = 10; - String ladderName = ""; - RankLadder rLadder = null; - - - // pull columns out of the options, if it has been specified: + // pull columns out of the options, if it has been specified: String colsStr = extractParameter("cols=", options); if ( colsStr != null ) { options = options.replace( colsStr, "" ).trim(); @@ -1125,24 +1147,20 @@ private void sellAllMultiplierCommand(CommandSender sender, } - List ladders = new ArrayList<>(); - - if ( rLadder == null ) { - ladders = PrisonRanks.getInstance().getLadderManager().getLadders(); - } - else { - ladders.add( rLadder ); - } - + 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); - TreeMap mults = new TreeMap<>( sellAllUtil.getPrestigeMultipliers() ); -// TreeMap items = new TreeMap<>( sellAllUtil.getSellAllBlocks() ); DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); DecimalFormat iFmt = Prison.get().getDecimalFormat("#,##0"); @@ -1168,13 +1186,13 @@ private void sellAllMultiplierCommand(CommandSender sender, for (RankLadder ladder : ladders ) { - StringBuilder sb = new StringBuilder(); - - int lines = 0; - int columns = 0; - for ( Rank rank : ladder.getRanks() ) { - String key = rank.getName(); - + 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 ) { @@ -1183,67 +1201,36 @@ private void sellAllMultiplierCommand(CommandSender sender, 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; - } + 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() ); + 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 ) { @@ -1278,6 +1265,9 @@ else if ( tryLowerCase ) { "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. " + + "Please note that sellall rank multiplers will NOT apply to higher ranks. " + + "If there is a sellall rank multiplier for P1 and not P2, and when the player ranks " + + "up to P2, they will not get the multiplier from P1. " + "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 " @@ -1289,7 +1279,15 @@ else if ( tryLowerCase ) { permissions = "prison.admin", onlyPlayers = false) private void sellAllAddMultiplierCommand(CommandSender sender, @Arg(name = "rank", description = "The rank name for the multiplier.") String rank, - @Arg(name = "multiplier", description = "Multiplier value.") Double multiplier) { + @Arg(name = "multiplier", description = "Multiplier value.") Double multiplier, + @Arg(name = "options", def = "Use '*applyToHigherRanks*' to copy this " + + "multipler to all higher ranks above this rank. This will apply the multipler " + + "through to the last rank, or until it hits a higher rank that already has a " + + "multipler defined. Example: If you have a multiplier set for P20 and you " + + "add one at P10 with this option enabled, then P11 through P19 will get the " + + "same multiplier that is given to P10.", + description = "") String options + ) { if (!isEnabled() ) { return; @@ -1301,11 +1299,13 @@ private void sellAllAddMultiplierCommand(CommandSender sender, return; } - if (sellAllUtil.addSellallRankMultiplier(rank, multiplier)){ + boolean applyToHigherRanks = options != null && "*applyToHigherRanks*".equalsIgnoreCase(options); + + if (sellAllUtil.addSellallRankMultiplier(rank, multiplier, applyToHigherRanks)){ Output.get().sendInfo(sender, messages.getString(MessagesConfig.StringID.spigot_message_sellall_multiplier_add_success)); } else { - Output.get().sendInfo( sender, "Failed to add sellall rank multiplier." ); + Output.get().sendInfo( sender, "Failed to add sellall rank multiplier." ); } } @@ -1364,19 +1364,19 @@ private void sellAllMultiplierDeleteLadderCommand( } if ( !PrisonRanks.getInstance().isEnabled() ) { - Output.get().sendWarn(sender, "Cannot use command `/sellall multiplier deleteLadder` since ranks are disabled" ); - return; + 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; + 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"); @@ -1425,59 +1425,59 @@ private void sellAllMultiplierAddLadderCommand( ) { - if ( !isEnabled() ) { - return; - } - SellAllUtil sellAllUtil = SellAllUtil.get(); + if ( !isEnabled() ) { + 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; + } - 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++; + } + + } - 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) - ) ); + 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) + ) ); } @@ -1494,14 +1494,12 @@ private void sellAllToolsTriggerToggle(CommandSender sender, @Arg(name = "Boolean", description = "Enable or disable", def = "true") String enable){ if (!isEnabled() ) { - return; + return; } SellAllUtil sellAllUtil = SellAllUtil.get(); if (enable.equalsIgnoreCase("null")){ - sender.dispatchCommand("sellall toolsTrigger help"); -// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall toolsTrigger help" ); -// sender.dispatchCommand(registeredCmd); + sender.dispatchCommand("sellall toolsTrigger help"); return; } @@ -1614,7 +1612,7 @@ private void sellAllTriggerDelete(CommandSender sender, private void sellAllSetDefaultCommand(CommandSender sender){ if ( !isEnabled() ) { - return; + return; } // Setup all the prices in sellall: @@ -1631,11 +1629,18 @@ private void sellAllSetDefaultCommand(CommandSender sender){ @Command(identifier = "sellall list", description = "SellAll list all items", permissions = "prison.admin", onlyPlayers = false) - private void sellAllListItems( CommandSender sender ) { + private void sellAllListItems( CommandSender sender, + @Arg(name = "filter", def = "", + description = "Optionally, you can provide a filter word fragment " + + "that will include only sellall items that 'contains' the fragment. " + + "Example: 'gold', 'old', 'raw', 'ore'.") String filter ) { if ( !isEnabled() ) { return; } + + filter = filter == null || filter.trim().length() == 0 ? "" : filter.trim(); + SellAllUtil sellAllUtil = SellAllUtil.get(); TreeMap items = new TreeMap<>( sellAllUtil.getSellAllItems() ); @@ -1647,49 +1652,52 @@ private void sellAllListItems( CommandSender sender ) { int maxLenVal = 0; int maxLenCode = 0; 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 ).getSalePrice() ); - if ( val.length() > maxLenVal ) { - maxLenVal = val.length(); - } + + if ( filter.length() == 0 || key.contains( filter ) ) { + + if ( key.length() > maxLenCode ) { + maxLenCode = key.length(); + } + String val = fFmt.format( items.get( key ).getSalePrice() ); + if ( val.length() > maxLenVal ) { + maxLenVal = val.length(); + } + } } ChatDisplay chatDisplay = new ChatDisplay("&bSellall Item 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 = items.get( key ).getSalePrice(); - - if ( !first ) { - sb.append( " " ); - } - - sb.append( String.format( "%-" + maxLenCode + "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 ( !first ) { - chatDisplay.addText( sb.toString() ); - - if ( ++lines % 10 == 0 && lines > 1 ) { - chatDisplay.addText( " " ); - } - - sb.setLength( 0 ); - } + if ( filter.length() == 0 || key.contains( filter ) ) { + + Double cost = items.get( key ).getSalePrice(); + + if ( sb.length() > 0 ) { + sb.append( " " ); + } + + sb.append( String.format( "%-" + maxLenCode + "s %" + maxLenVal + "s", + key, fFmt.format( cost ) ) ); + + if ( ++columns >= 3 ) { + 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.addText( sb.toString() ); } chatDisplay.send( sender ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java index ce342617a..2f64f9fc8 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Compatibility.java @@ -27,6 +27,7 @@ import org.bukkit.inventory.PlayerInventory; import tech.mcprison.prison.spigot.block.SpigotItemStack; +import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; /** @@ -53,19 +54,29 @@ public interface Compatibility public SpigotItemStack getPrisonItemInMainHand(Player player); + public SpigotItemStack getPrisonItemInMainHand(SpigotPlayer player); + public SpigotItemStack getPrisonItemInOffHand(Player player); + + public SpigotItemStack getPrisonItemInOffHand(SpigotPlayer player); public ItemStack getItemInOffHand(PlayerInteractEvent e); public ItemStack getItemInOffHand(Player player); + + public ItemStack getItemInOffHandStrict(Player player); public ItemStack getItemInOffHand(PlayerInventory playerInventory); public void setItemStackInMainHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ); public void setItemInMainHand(Player p, ItemStack itemStack); + + public void setItemInMainHand(SpigotPlayer p, ItemStack itemStack); public void setItemStackInOffHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ); + + public void setItemStackInOffHandStrict( Player player, ItemStack itemStack ); public void breakItemInMainHand(Player player); 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 8b1be84a3..c57157f77 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 @@ -14,22 +14,15 @@ public interface CompatibilityBlocks extends CompatibilityPlayer { -// public BlockType getBlockType(Block spigotBlock); - public SpigotBlock getSpigotBlock(Block spigotBlock); public XMaterial getXMaterial( Block spigotBlock ); public XMaterial getXMaterial( PrisonBlock prisonBlock ); -// public XMaterial getXMaterial( BlockType blockType ); - -// public BlockType getBlockType( ItemStack spigotStack ); -// public void updateSpigotBlock( BlockType blockType, Block spigotBlock ); - public void updateSpigotBlock( PrisonBlock prisonBlock, Block spigotBlock ); public void updateSpigotBlock( XMaterial xMat, Block spigotBlock ); @@ -38,12 +31,6 @@ public interface CompatibilityBlocks public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Location location ); -// public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ); -// -// public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ); -// -// public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ); - public BlockTestStats testCountAllBlockTypes(); @@ -57,10 +44,6 @@ public interface CompatibilityBlocks public boolean setDurability( SpigotItemStack itemStack, int newDurability ); -// public int getDurability( SpigotItemStack itemInHand ); -// -// public void setDurability( SpigotItemStack itemInHand, int newDurability ); - public void setBlockFace( Block bBlock, BlockFace blockFace ); public ItemStack getLapisItemStack(); @@ -102,5 +85,26 @@ public interface CompatibilityBlocks */ public void setCustomModelData( ItemStack itemStack, int customModelData ); + + /** + *

    With spigot 1.14 and newer, there is a function on a block that + * identifies if a block is passable. The description in the api docs are: + *

    + * + *
    +	 * Checks if this block is passable.
    +
    +A block is passable if it has no colliding parts that would prevent 
    +players from moving through it.
    +
    +Examples: Tall grass, flowers, signs, etc. are passable, but open doors, 
    +fence gates, trap doors, etc. are not because they still have parts that 
    +can be collided with.
    +	 * 

    + * + * @param bBlock + * @return + */ + public boolean isPassable( Block bBlock ); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java index d03d50497..eb4019ad7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/CompatibilityCache.java @@ -23,8 +23,6 @@ public class CompatibilityCache { public static final XMaterial NULL_TOKEN = XMaterial.VOID_AIR; -// private Map blockTypeCache; - private Map xMaterialCache; @@ -34,7 +32,6 @@ public class CompatibilityCache { public CompatibilityCache() { super(); -// this.blockTypeCache = new TreeMap<>(); this.xMaterialCache = new TreeMap<>(); initializeForcedCache(); @@ -56,44 +53,6 @@ private void initializeForcedCache() { } -// public BlockType getCachedBlockType( Block spigotBlock, byte data ) { -// String key = spigotBlock.getType().name() + ( data <= 0 ? "" : ":" +data); -// -// BlockType blockType = blockTypeCache.get( key ); -// -// return blockType; //blockType == BlockType.NULL_BLOCK ? null : blockType; -// } -// public void putCachedBlockType( Block spigotBlock, byte data, BlockType blockType ) { -// if ( spigotBlock != null ) { -// String key = spigotBlock.getType().name() + ( data <= 0 ? "" : ":" + data); -// -// if ( !blockTypeCache.containsKey( key ) ) { -// blockTypeCache.put( key, blockType == null ? BlockType.NULL_BLOCK : blockType ); -// } -// } -// } - - -// public BlockType getCachedBlockType( ItemStack spigotStack, byte data ) { -// String key = spigotStack.getType().name() + ( data <= 0 ? "" : ":" + data); -// -// BlockType blockType = blockTypeCache.get( key ); -// -// return blockType; // blockType == BlockType.NULL_BLOCK ? null : blockType; -// } -// public void putCachedBlockType( ItemStack spigotStack, byte data, BlockType blockType ) { -// if ( spigotStack != null ) { -// String key = spigotStack.getType().name() + ( data <= 0 ? "" : ":" + data); -// -// if ( !blockTypeCache.containsKey( key ) ) { -// blockTypeCache.put( key, blockType == null ? BlockType.NULL_BLOCK : blockType ); -// } -// } -// } - - - - public XMaterial getCachedXMaterial( tech.mcprison.prison.internal.block.Block prisonBlock ) { String key = prisonBlock.getBlockName(); @@ -131,23 +90,6 @@ public void putCachedXMaterial( Block spigotBlock, byte data, XMaterial xMat ) { } } -// public XMaterial getCachedXMaterial( BlockType blockType, byte data ) { -// String key = blockType.name() + ( data <= 0 ? "" : ":" +data); -// -// XMaterial xMat = xMaterialCache.get( key ); -// -// // Using VOID_AIR as temp placeholder for null values: -// return xMat; // xMat == XMaterial.VOID_AIR ? null : xMat; -// } -// public void putCachedXMaterial( BlockType blockType, byte data, XMaterial xMat ) { -// String key = blockType.name() + ( data <= 0 ? "" : ":" +data); -// -// if ( !xMaterialCache.containsKey( key ) ) { -// // Using VOID_AIR as temp placeholder for null values: -// xMaterialCache.put( key, xMat == null ? NULL_TOKEN : xMat ); -// } -// } - public SpigotPrison getPlugin() { return plugin; } 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 ce98af5fa..f0e217d0c 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 @@ -1,8 +1,8 @@ package tech.mcprison.prison.spigot.compat; import tech.mcprison.prison.output.Output; -import tech.mcprison.prison.spigot.spiget.BluesSemanticVersionData; -import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; +import tech.mcprison.prison.util.BluesSemanticVersionComparator; +import tech.mcprison.prison.util.BluesSemanticVersionData; public class SpigotCompatibility { @@ -23,7 +23,7 @@ private static synchronized void setup() { Compatibility results = null; - String bukkitVersion = new BluesSpigetSemVerComparator().getBukkitVersion(); + String bukkitVersion = new BluesSemanticVersionComparator().getBukkitVersion(); if ( bukkitVersion == null ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotNMSPlayer.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotNMSPlayer.java index 0c6288e16..4a6d1813b 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotNMSPlayer.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/SpigotNMSPlayer.java @@ -151,9 +151,9 @@ public String getLocale( org.bukkit.entity.Player player ) { } } catch (IllegalAccessException | InvocationTargetException ex) { - supported = false; - - Output.get().logInfo("Could not get locale of player " + player.getName(), ex); + supported = false; + + Output.get().logInfo("Could not get locale of player " + player.getName(), ex); } catch ( Exception ex ) { supported = false; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13.java index c14d3a370..0d3c1f55c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13.java @@ -11,6 +11,7 @@ import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.SpigotItemStack; +import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; public class Spigot_1_13 @@ -28,11 +29,11 @@ public EquipmentSlot getHand(PlayerInteractEvent e) { @Override public EquipmentSlot getHand(BlockPlaceEvent e) { - if (e.getHand() == null) { - return null; - } else { - return EquipmentSlot.valueOf(e.getHand().name()); - } + if (e.getHand() == null) { + return null; + } else { + return EquipmentSlot.valueOf(e.getHand().name()); + } } @Override @@ -42,28 +43,38 @@ public ItemStack getItemInMainHand(PlayerInteractEvent e) { @Override public ItemStack getItemInMainHand(Player player) { - return getItemInMainHand( player.getInventory() ); + return getItemInMainHand( player.getInventory() ); } @Override public ItemStack getItemInMainHand(PlayerInventory playerInventory) { - return playerInventory.getItemInMainHand(); + return playerInventory.getItemInMainHand(); } @Override public SpigotItemStack getPrisonItemInMainHand(PlayerInteractEvent e) { - return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( e ) ); + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( e ) ); } @Override public SpigotItemStack getPrisonItemInMainHand(Player player) { - return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); } + @Override + public SpigotItemStack getPrisonItemInMainHand(SpigotPlayer player) { + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player.getWrapper() ) ); + } + @Override public SpigotItemStack getPrisonItemInOffHand(Player player) { return SpigotUtil.bukkitItemStackToPrison( getItemInOffHand( player ) ); } + + @Override + public SpigotItemStack getPrisonItemInOffHand(SpigotPlayer player) { + return SpigotUtil.bukkitItemStackToPrison( getItemInOffHand( player.getWrapper() ) ); + } @Override public ItemStack getItemInOffHand(PlayerInteractEvent e) { @@ -72,19 +83,37 @@ public ItemStack getItemInOffHand(PlayerInteractEvent e) { @Override public ItemStack getItemInOffHand(Player player ) { - return getItemInOffHand(player.getInventory()); + return getItemInOffHand(player.getInventory()); } @Override public ItemStack getItemInOffHand(PlayerInventory playerInventory) { - return playerInventory.getItemInOffHand(); + return playerInventory.getItemInOffHand(); } + /** + * 1.9 and higher supports off-hand: + */ + @Override + public ItemStack getItemInOffHandStrict(Player player) { + return getItemInOffHand(player.getInventory()); + } + + /** + * 1.9 and higher supports off-hand: + */ + @Override + public void setItemStackInOffHandStrict(Player player, ItemStack itemStack) { + + player.getInventory().setItemInOffHand(itemStack); + } + + @Override public void setItemStackInMainHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ) { - ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) - .setItemInMainHand( itemStack.getBukkitStack() ); + ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) + .setItemInMainHand( itemStack.getBukkitStack() ); } @Override @@ -92,13 +121,18 @@ public void setItemInMainHand(Player p, ItemStack itemStack){ p.getInventory().setItemInMainHand(itemStack); } + @Override + public void setItemInMainHand(SpigotPlayer p, ItemStack itemStack){ + p.getWrapper().getInventory().setItemInMainHand(itemStack); + } + @Override public void setItemStackInOffHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ) { - ItemStack iStack = itemStack == null ? null : itemStack.getBukkitStack(); - - ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) - .setItemInOffHand( iStack ); + ItemStack iStack = itemStack == null ? null : itemStack.getBukkitStack(); + + ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) + .setItemInOffHand( iStack ); } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13_Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13_Blocks.java index f0d86452b..5c70c23e7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13_Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_13_Blocks.java @@ -15,6 +15,7 @@ import tech.mcprison.prison.internal.block.PrisonBlock; import tech.mcprison.prison.internal.block.PrisonBlockTypes.InternalBlockTypes; import tech.mcprison.prison.output.Output; +import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.SpigotBlock; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.util.Location; @@ -23,30 +24,6 @@ public abstract class Spigot_1_13_Blocks extends Spigot_1_9_Player implements CompatibilityBlocks { -// @Override -// public BlockType getBlockType(Block spigotBlock) { -// BlockType results = getCachedBlockType( spigotBlock, NO_DATA_VALUE ); -// -// if ( results == null ) { -// if ( spigotBlock != null ) { -// -// results = BlockType.getBlock( spigotBlock.getType().name() ); -// -//// if ( results == null ) { -//// Output.get().logInfo( "#### 1.13 getBlockType() Cannot map block from spigot to prison:" + -//// " spigotBlock.getType().name() = %s " + -//// " BlockType.getBlock() = %s ", -//// spigotBlock.getType().name(), -//// (results == null ? "" : results.name() )); -//// } -// -// putCachedBlockType( spigotBlock, NO_DATA_VALUE, results ); -// } -// } -// -// return results == BlockType.NULL_BLOCK ? null : results; -// } - /** *

    This function should never be accessed directly. Use the function * getBlockAt() functions within the Prison Location or SpigotWorld @@ -58,34 +35,8 @@ public abstract class Spigot_1_13_Blocks @Override public SpigotBlock getSpigotBlock( Block bukkitBlock ) { return SpigotBlock.getSpigotBlock( bukkitBlock ); -// SpigotBlock sBlock = null; -// -// XMaterial xMat = getXMaterial( bukkitBlock ); -// -// if ( xMat != null ) { -// sBlock = new SpigotBlock( xMat.name(), bukkitBlock ); -// } -// // ignore nulls because errors were logged in getXMaterial() so they only -// // are logged once -// -// return sBlock; } -// @Override -// public BlockType getBlockType(ItemStack spigotStack) { -// BlockType results = getCachedBlockType( spigotStack, NO_DATA_VALUE ); -// -// if ( results == null ) { -// if ( spigotStack != null ) { -// -// results = BlockType.getBlock( spigotStack.getType().name() ); -// -// putCachedBlockType( spigotStack, NO_DATA_VALUE, results ); -// } -// } -// -// return results == BlockType.NULL_BLOCK ? null : results; -// } @Override public XMaterial getXMaterial( Block spigotBlock ) { @@ -95,25 +46,35 @@ public XMaterial getXMaterial( Block spigotBlock ) { results = getCachedXMaterial( spigotBlock, NO_DATA_VALUE ); if ( results == null ) { - results = XMaterial.matchXMaterial( spigotBlock.getType() ); - - if ( results == null ) { - results = XMaterial.matchXMaterial( spigotBlock.getType().name() ).orElse( null ); - } - - if ( results == null ) { + try { + results = XMaterial.matchXMaterial( spigotBlock.getType() ); - Output.get().logWarn( "Spigot113Blocks.getXMaterial() : " + - "Spigot block cannot be mapped to a XMaterial : " + - spigotBlock.getType().name() + - " SpigotBlock = " + ( spigotBlock == null ? "null" : - spigotBlock.getType().name())); - } + if ( results == null ) { + results = XMaterial.matchXMaterial( spigotBlock.getType().name() ).orElse( null ); + } + + if ( results == null ) { + + Output.get().logWarn( "Spigot113Blocks.getXMaterial() : " + + "Spigot block cannot be mapped to a XMaterial : " + + spigotBlock.getType().name() + + " SpigotBlock = " + ( spigotBlock == null ? "null" : + spigotBlock.getType().name())); + } - - if ( results != null ) { - putCachedXMaterial( spigotBlock, NO_DATA_VALUE, results ); + if ( results != null ) { + + putCachedXMaterial( spigotBlock, NO_DATA_VALUE, results ); + } + } + catch ( IllegalArgumentException e) { + // xMaterial does not support this material type. + + // Add this bad spigotBlock to the cache with a NULL_TOKEN + // so it will not try to map it again: + + putCachedXMaterial( spigotBlock, NO_DATA_VALUE, NULL_TOKEN ); } } } @@ -144,60 +105,6 @@ public XMaterial getXMaterial( PrisonBlock prisonBlock ) { } -// /** -// *

    This function tries to use up to three different sources to get a match -// * on the XMaterial. Just because the XMateral may be a match, does not -// * mean it actually is a valid Block for that version of spigot. -// *

    -// * -// * @param blockType -// * @return -// */ -// @Override -// public XMaterial getXMaterial( BlockType blockType ) { -// XMaterial results = getCachedXMaterial( blockType, NO_DATA_VALUE ); -// -// if ( results == null ) { -// if ( blockType != null && blockType != BlockType.IGNORE ) { -// -// results = XMaterial.matchXMaterial( blockType.getXMaterialName() ).orElse( null ); -// -// if ( results == null ) { -// results = XMaterial.matchXMaterial( blockType.getXMaterialNameLegacy() ).orElse( null ); -// -// } -// -// if ( results == null ) { -// -// for ( String altName : blockType.getXMaterialAltNames() ) { -// results = XMaterial.matchXMaterial( altName ).orElse( null ); -// -// if ( results != null ) { -// break; -// } -// } -// } -// -// putCachedXMaterial( blockType, NO_DATA_VALUE, results ); -// } -// -// } -// -// return results == NULL_TOKEN ? null : results; -// } - - -// @Override -// public void updateSpigotBlock( BlockType blockType, Block spigotBlock ) { -// -// if ( blockType != null && blockType != BlockType.IGNORE && spigotBlock != null ) { -// -// XMaterial xMat = getXMaterial( blockType ); -// -// updateSpigotBlock( xMat, spigotBlock ); -// } -// } - @Override public void updateSpigotBlock( PrisonBlock prisonBlock, Block spigotBlock ) { @@ -230,54 +137,6 @@ public void updateSpigotBlock( XMaterial xMat, Block spigotBlock ) { } -// @Override -// public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ) { -// -// if ( blockType != null && blockType != BlockType.IGNORE && spigotBlock != null ) { -// -// XMaterial xMat = getXMaterial( blockType ); -// -// updateSpigotBlockAsync( xMat, spigotBlock ); -// } -// } -// -// -// @Override -// public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ) { -// -// if ( prisonBlock != null && -// !prisonBlock.getBlockName().equalsIgnoreCase( InternalBlockTypes.IGNORE.name() ) && -// spigotBlock != null ) { -// -// XMaterial xMat = getXMaterial( prisonBlock ); -// -// if ( xMat != null ) { -// -// updateSpigotBlockAsync( xMat, spigotBlock ); -// } -// } -// } -// -// -// @Override -// public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ) { -// -// if ( xMat != null ) { -// Material newType = xMat.parseMaterial(); -// if ( newType != null ) { -// -// new BukkitRunnable() { -// @Override -// public void run() { -// -// // No physics update: -// spigotBlock.setType( newType, false ); -// } -// }.runTaskLater( getPlugin(), 0 ); -// -// } -// } -// } /** *

    This function both get's the block and then updates it within @@ -341,23 +200,50 @@ public BlockTestStats testCountAllBlockTypes() { stats.setMaterialSize( Material.values().length ); + StringBuilder sb = new StringBuilder(); + // go through all available materials: for ( Material mat : Material.values() ) { - // Must create an item stack: - ItemStack iStack = new ItemStack( mat, 1 ); - - if ( iStack != null ) { + try { + // Must create an item stack: + ItemStack iStack = new ItemStack( mat, 1 ); - if ( mat.isBlock() ) { - stats.addCountBlocks(); + if ( iStack != null ) { + + if ( mat.isBlock() ) { + stats.addCountBlocks(); + } + else if ( mat.isItem() ) { + stats.addCountItems(); + } } - else if ( mat.isItem() ) { - stats.addCountItems(); + } + catch (Exception e) { + + // NOTE: Wall hangings, water, and potted plants can be placed as blocks, but cannot + // created as ItemStacks: + if ( SpigotUtil.canItemStackMaterial( mat ) ) { + + sb.append( mat.name() ).append( " " ); } + +// Output.get().logInfo( +// "Notice: The org.bukkit.Material %s could not create an ItemStack. This is not an error, just a notice.", +// mat.name() +// ); } } + if ( sb.length() > 0 ) { + + Output.get().logInfo( "### Spigot_1_13_Blocks.testCountAllBlockTypes: " + + "The following XMaterial items could not generate an ItemStack. " + + "This is not an error. " + + "Igoring '*water*', '*wall*', and '*potted*' [%s] ", + sb.toString() ); + } + return stats; } @@ -410,17 +296,6 @@ public boolean setDurability( SpigotItemStack itemInHand, int newDamage ) { return results; } -// public int getDurability( SpigotItemStack itemInHand ) { -// -// Damageable damage = (Damageable) itemInHand.getBukkitStack().getItemMeta(); -// return damage.getDamage(); -// } -// -// public void setDurability( SpigotItemStack itemInHand, int newDamage ) { -// -// Damageable damage = (Damageable) itemInHand.getBukkitStack().getItemMeta(); -// damage.setDamage( newDamage ); -// } /** * This is called setBlockFace, but it is really intended for use with ladders. @@ -477,10 +352,6 @@ public void setBlockFace( Block spigotBlock, BlockFace blockFace ) { @Override public ItemStack getLapisItemStack() { - return XMaterial.LAPIS_LAZULI.parseItem(); -// if (XMaterial.LAPIS_LAZULI.parseItem() != null) { -// return new ItemStack(XMaterial.LAPIS_LAZULI.parseItem()); -// } -// return null; + return XMaterial.LAPIS_LAZULI.parseItem(); } } 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 index 9a76d4372..681e276f7 100644 --- 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 @@ -2,6 +2,7 @@ import java.lang.reflect.Method; +import org.bukkit.block.Block; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -9,7 +10,6 @@ public class Spigot_1_14_Blocks extends Spigot_1_13 - //implements CompatibilityBlocks { private static Method SET_CUSTOM_MODEL_DATA = null; @@ -33,7 +33,7 @@ public class Spigot_1_14_Blocks */ @Override public int getCustomModelData( SpigotItemStack itemStack ) { - return getCustomModelData( itemStack == null ? null : itemStack.getBukkitStack() ); + return getCustomModelData( itemStack == null ? null : itemStack.getBukkitStack() ); } /** * Not compatible with Spigot 1.8 through 1.13 so return a value of 0. @@ -43,30 +43,30 @@ public int getCustomModelData( SpigotItemStack itemStack ) { */ @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(); + 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(); } - } - catch (ReflectiveOperationException ex ) { - ex.printStackTrace(); - } - catch ( ClassCastException ex ) { - ex.printStackTrace(); } - } - itemStack.setItemMeta(meta); - } - - return results; + itemStack.setItemMeta(meta); + } + + return results; } /** @@ -90,20 +90,44 @@ public void setCustomModelData( SpigotItemStack itemStack, int customModelData ) @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(); + 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); - } + itemStack.setItemMeta(meta); + } } + + /** + *

    With spigot 1.14 and newer, there is a function on a block that + * identifies if a block is passable. The description in the api docs are: + *

    + * + *
    +	 * Checks if this block is passable.
    +
    +A block is passable if it has no colliding parts that would prevent 
    +players from moving through it.
    +
    +Examples: Tall grass, flowers, signs, etc. are passable, but open doors, 
    +fence gates, trap doors, etc. are not because they still have parts that 
    +can be collided with.
    +	 * 

    + * + * @param bBlock + * @return + */ + @Override + public boolean isPassable( Block bBlock ) { + return bBlock.isPassable(); + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_18.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_18.java index 2ef9cb96b..20bfef858 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_18.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_18.java @@ -8,12 +8,12 @@ public class Spigot_1_18 @Override public int getMinY() { - return -64; + return -64; } @Override public int getMaxY() { - return 320; + return 320; } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8.java index 67fb01c47..05e370cef 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8.java @@ -29,6 +29,7 @@ import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.SpigotItemStack; +import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; /** @@ -47,7 +48,7 @@ public EquipmentSlot getHand(PlayerInteractEvent e) { @Override public EquipmentSlot getHand(BlockPlaceEvent e) { - return EquipmentSlot.HAND; // Spigot 1.8 only has one hand + return EquipmentSlot.HAND; // Spigot 1.8 only has one hand } @Override @@ -57,26 +58,34 @@ public ItemStack getItemInMainHand(PlayerInteractEvent e) { @Override public ItemStack getItemInMainHand(Player player ) { - return getItemInMainHand( player.getInventory() ); + return getItemInMainHand( player.getInventory() ); } @SuppressWarnings( "deprecation" ) @Override public ItemStack getItemInMainHand(PlayerInventory playerInventory) { - return playerInventory.getItemInHand(); + return playerInventory.getItemInHand(); } public SpigotItemStack getPrisonItemInMainHand(PlayerInteractEvent e) { - return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( e ) ); + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( e ) ); } public SpigotItemStack getPrisonItemInMainHand(Player player) { - return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); + } + + public SpigotItemStack getPrisonItemInMainHand(SpigotPlayer player) { + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player.getWrapper() ) ); } public SpigotItemStack getPrisonItemInOffHand(Player player) { - return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); + } + + public SpigotItemStack getPrisonItemInOffHand(SpigotPlayer player) { + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player.getWrapper() ) ); } @Override @@ -86,22 +95,40 @@ public ItemStack getItemInOffHand(PlayerInteractEvent e) { @Override public ItemStack getItemInOffHand(Player player ) { - return getItemInOffHand( player.getInventory() ); + return getItemInOffHand( player.getInventory() ); } /** * This function does not exist in v1.8 so returns null. */ + @Override public ItemStack getItemInOffHand(PlayerInventory playerInventory) { - return null; + return null; } + /** + * This function does not exist in v1.8 so returns null. + */ + @Override + public ItemStack getItemInOffHandStrict(Player player) { + return null; + } + + /** + * This function does not exist in v1.8 so do nothing. + */ + @Override + public void setItemStackInOffHandStrict(Player player, ItemStack itemStack) { + + } + + @SuppressWarnings( "deprecation" ) @Override public void setItemStackInMainHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ) { - - ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) - .setItemInHand( itemStack.getBukkitStack() ); + + ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) + .setItemInHand( itemStack.getBukkitStack() ); } @SuppressWarnings("deprecation") @@ -109,13 +136,19 @@ public void setItemStackInMainHand( SpigotPlayerInventory inventory, SpigotItemS public void setItemInMainHand(Player p, ItemStack itemStack) { p.getInventory().setItemInHand(itemStack); } + + @SuppressWarnings("deprecation") + @Override + public void setItemInMainHand(SpigotPlayer p, ItemStack itemStack) { + p.getWrapper().getInventory().setItemInHand(itemStack); + } /** * Spigot v1.8 does not have an off hand, so set it to main hand. */ @Override public void setItemStackInOffHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ) { - setItemStackInMainHand( inventory, itemStack ); + setItemStackInMainHand( inventory, itemStack ); } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Blocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Blocks.java index fbb1b65c6..0d7feac45 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Blocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Blocks.java @@ -6,6 +6,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; +import com.cryptomorin.xseries.XBlock; import com.cryptomorin.xseries.XMaterial; import tech.mcprison.prison.internal.block.BlockFace; @@ -19,191 +20,33 @@ public abstract class Spigot_1_8_Blocks extends Spigot_1_8_Player implements CompatibilityBlocks { - -// /** -// *

    This function provides a minecraft v1.8 way of getting -// * the prison BlockType from a bukkit Block. This function -// * should be used for all block types prior to 1.13.x because -// * of the use of magic numbers. The variations of types for a -// * base material cannot be accessed in any other way. -// * For example the item lapis lazuli, which is not a block type, -// * but it is one of the primary problem item. -// *

    -// * -// *

    For versions 1.13.x and higher, a different function would -// * need to be used to get the BlockType. -// *

    -// * -// * @param spigotBlock -// * @return -// */ -// @SuppressWarnings( "deprecation" ) -// @Override -// public BlockType getBlockType(Block spigotBlock) { -// BlockType results = BlockType.NULL_BLOCK; -// -// if ( spigotBlock != null ) { -// -// int id = spigotBlock.getType().getId(); -// short data = spigotBlock.getData(); -// -// results = getCachedBlockType( spigotBlock, (byte) data ); -// if ( results == null ) { -// -// // NOTE: namespace is 1.13+ -//// Output.get().logInfo( "### getBlockType: " + spigotBlock.getType().name() + " " + -//// spigotBlock.getType().getKey().getKey() + " " + -//// spigotBlock.getType().getKey().getNamespace() ); -// -// results = BlockType.getBlock(id, data); -// -// if ( results == null ) { -// -// results = BlockType.getBlock( spigotBlock.getType().name() ); -// -// if ( results == null ) { -// -// Output.get().logWarn( "Spigot18Blocks.getBlockType() : " + -// "Spigot block cannot be mapped to a prison BlockType : " + -// spigotBlock.getType().name() + -// " id = " + id + " data = " + data + -// " BlockType = " + ( results == null ? "null" : results.name())); -// -// } -// } -// -// putCachedBlockType( spigotBlock, (byte) data, results ); -// } -// } -// -// return results == BlockType.NULL_BLOCK ? null : results; -// } @Override public SpigotBlock getSpigotBlock( Block bukkitBlock ) { return SpigotBlock.getSpigotBlock( bukkitBlock ); -// SpigotBlock sBlock = null; -// -// XMaterial xMat = getXMaterial( bukkitBlock ); -// -// if ( xMat != null ) { -// -// sBlock = new SpigotBlock( xMat.name(), bukkitBlock ); -// -//// pBlock = SpigotPrison.getInstance().getPrisonBlockTypes().getBlockTypesByName( xMat.name() ); -//// pBlock = new PrisonBlock( xMat.name() ); -// } -// // ignore nulls because errors were logged in getXMaterial() so they only -// // are logged once -// -// return sBlock; } + -// @SuppressWarnings( "deprecation" ) -// @Override -// public BlockType getBlockType( ItemStack spigotStack ) { -// BlockType results = BlockType.NULL_BLOCK; -// -// if ( spigotStack != null ) { -// -// int id = spigotStack.getType().getId(); -// short data = spigotStack.getData().getData(); -// -// results = getCachedBlockType( spigotStack, (byte) data ); -// if ( results == null ) { -// -// results = BlockType.getBlock(id, data); -// -// if ( results == null ) { -// -// // NOTE: Some items may have invalid data values. Example are with pickaxes -// // should have a value of zero, but could range from +- 256. -// // Try to use XMaterial to map back to a BlockType (old block model). -// XMaterial xMat = xMatMatchXMaterial( spigotStack ); -// -// if ( xMat != null ) { -// results = BlockType.getBlock( xMat.name() ); -// } -// -// if ( results == null ) { -// -// String message = String.format( "Spigot18Blocks: getBlockType(): " + -// "Unable to map to a BlockType. XMaterial = %s :: %s %s " + -// "Material = %s ", -// (xMat == null ? "null" : xMat.name()), -// Integer.toString( id ), Integer.toString( data ), -// spigotStack.getType().name() ); -// -// Output.get().logInfo( message ); -// } -// } -// -// putCachedBlockType( spigotStack, (byte) data, results ); -// } -// } -// -// return results == BlockType.NULL_BLOCK ? null : results; -// } - -// /** -// *

    Something is causing XMaterial to throw an exception that makes no sense -// * since the item listed does not exist in game. -// *

    -// * -// *
    -//	 *  Caused by: java.lang.IllegalArgumentException: Unsupported material from item: BED (14)
    -//	at tech.mcprison.prison.cryptomorin.xseries.XMaterial.lambda$matchXMaterial$1(XMaterial.java:1559) ~[?:?]
    -//	at tech.mcprison.prison.cryptomorin.xseries.XMaterial$$Lambda$197/0x0000000069039ff0.get(Unknown Source) ~[?:?]
    -//	at java.util.Optional.orElseThrow(Optional.java:290) ~[?:1.8.0_272]
    -//	at tech.mcprison.prison.cryptomorin.xseries.XMaterial.matchXMaterial(XMaterial.java:1559) ~[?:?]
    -//	at tech.mcprison.prison.spigot.compat.Spigot18Blocks.getBlockType(Spigot18Blocks.java:116) ~[?:?]
    -//	at tech.mcprison.prison.spigot.block.SpigotItemStack.(SpigotItemStack.java:45) ~[?:?]
    -//	at tech.mcprison.prison.spigot.SpigotUtil.bukkitItemStackToPrison(SpigotUtil.java:583) ~[?:?]
    -//	at tech.mcprison.prison.spigot.SpigotListener.onPlayerInteract(SpigotListener.java:172) ~[?:?]
    -//	at sun.reflect.GeneratedMethodAccessor64.invoke(Unknown Source) ~[?:?]
    -//	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_272]
    -//	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_272]
    -//	at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:302) ~[spigot-1.12.2.jar:git-Spigot-eb3d921-2b93d83]
    -//	... 17 more
    -//	 *  
    -// * -// * -// * NOTE: Some items may have invalid data values. Example are with pickaxes -// * should have a value of zero, but could range from +- 256. -// * Try to use XMaterial to map back to a BlockType (old block model). -// * -// * @param spigotStack -// * @return -// */ -// @SuppressWarnings( "deprecation" ) -// private XMaterial xMatMatchXMaterial( ItemStack spigotStack ) { -// XMaterial xMat = null; -// -// if ( spigotStack != null ) { -// -// try { -// xMat = XMaterial.matchXMaterial( spigotStack ); -// } -// catch ( Exception e ) { -// -// int id = spigotStack.getType().getId(); -// short data = spigotStack.getData().getData(); -// -// // Invalid type from the stack: -// Output.get().logDebug( "Spigot188Blocks: unable to matchXMaterial. " + -// "Type=%s Qty=%s id=%s data=%s Error=[%s]", -// spigotStack.getType().name(), -// Integer.toString( spigotStack.getAmount() ), -// Integer.toString( id ), -// Integer.toString( data ), -// e.getMessage() ); -// } -// } -// -// return xMat; -// } - + /** + *

    This will take a given block and return the XMaterial object for it. + *

    + * + *

    But please keep in mind that just because the block is in a mine, that the + * blocks may not belong in the mine. Matter of fact, this may be the situation + * when creating a new mine in a new world, or moving a mine. I mention this + * fact, because even though the list of blocks for a mine may be very constrained + * ( 'mines block list f') that it may actually contain blocks outside of that + * list. This actually becomes a problem when older versions of XSeries does + * not support that block (ie... updated to new spigot or paper version) and + * therefore XSeries cannot match to one of it's block types. + * This may not be a problem, because the mine may not have been reset yet. + * Resetting the mine will purge those unknown block types. + * Or at least, we can just ignore them since they are not blocks we are + * trying to track. + *

    + * + */ @SuppressWarnings( "deprecation" ) @Override public XMaterial getXMaterial( Block spigotBlock ) { @@ -218,25 +61,40 @@ public XMaterial getXMaterial( Block spigotBlock ) { String blockName = spigotBlock.getType().name() + ":" + data; results = XMaterial.matchXMaterial( blockName ).orElse( null ); -// if ( results == null ) { -// -// Output.get().logInfo( "#### Spigot18Blocks.getXMaterial(Block) : %s => %s ", -// blockName, (results == null ? "null" : results.name() )); -// } - if ( results == null ) { // Last chance: try to match by id: - int id = spigotBlock.getType().getId(); - results = XMaterial.matchXMaterial( id, data ).orElse( null ); + // WARNING: This will not work with "modern material". So if this + // throws an exception when trying to get the ID, then just + // ignore it since results will be null and it will try to + // match by MaterialType and then by name. + try { + int id = spigotBlock.getType().getId(); + + results = matchXMaterial( id, data ); + } + catch (Exception e) { + // Ignore this exception and allow it to find a match by + // other means... + } } if ( results == null ) { - results = XMaterial.matchXMaterial(spigotBlock.getType()); + try { + results = XMaterial.matchXMaterial(spigotBlock.getType()); + } + catch (Exception e) { + // Ignore and let next test try it... + } } if ( results == null ) { - results = XMaterial.matchXMaterial( spigotBlock.getType().name() ).orElse( null ); + try { + results = XMaterial.matchXMaterial( spigotBlock.getType().name() ).orElse( null ); + } + catch (Exception e) { + // Ignore and let the next test try it... + } } if ( results == null ) { @@ -262,6 +120,49 @@ public XMaterial getXMaterial( Block spigotBlock ) { return results == NULL_TOKEN ? null : results; } + + /** + * This function was removed from XMaterial as of XSeries v11.0.0. + * + * This behaves the same, so spigot 1.8 can still be used with + * XSeries v11.1.0+. + * + * Gets the XMaterial based on the material's ID (Magic Value) and data value.
    + * You should avoid using this for performance issues. + * + * Since prison uses a material cache in this function, this will only get the + * XMaterial the first time the item is requested. So performance is bad, but + * it's a one time hit. + * + * Warning: this method loops through all the available materials and matches their + * ID using {@link #getId()} which takes a really long time. + * + * @param id the ID (Magic value) of the material. + * @param data the data value of the material. + * @return a parsed XMaterial with the same ID and data value. + * @see #matchXMaterial(ItemStack) + */ + public static XMaterial matchXMaterial(int id, byte data) { + XMaterial results = null; + + // NOTE: XMaterial.MAX_ID == 2267. + // if (id < 0 || id > 2267 || data < 0) return null; + + if (id >= 0 && id <= 2267 && data >= 0) { + + for (XMaterial materials : XMaterial.VALUES) { + if (materials.getData() == data && materials.getId() == id) { + + results = materials; + break; + } + } + } + + return results; + } + + @Override public XMaterial getXMaterial( PrisonBlock prisonBlock ) { XMaterial results = NULL_TOKEN; @@ -296,101 +197,8 @@ else if ( results == XMaterial.BRICK && return results == NULL_TOKEN ? null : results; } - -// @Override -// public XMaterial getXMaterial( BlockType blockType ) { -// XMaterial results = NULL_TOKEN; -// -// if ( blockType != null && blockType != BlockType.IGNORE ) { -// short data = blockType.getData(); -// -// results = getCachedXMaterial( blockType, (byte) data ); -// if ( results == null ) { -// -// // First match by BlockType name: -// results = XMaterial.matchXMaterial( blockType.getXMaterialName() ).orElse( null ); -// -// // do not use... redundant with blockType.getXMaterialName(): -//// results = XMaterial.matchXMaterial( blockType.name() ).orElse( null ); -// -// if ( results == null ) { -// -// // Try to match on altNames if they exist: -// for ( String altName : blockType.getXMaterialAltNames() ) { -// -// results = XMaterial.matchXMaterial( altName ).orElse( null ); -// -// if ( results != null ) { -// break; -// } -// } -// -// if ( results == null ) { -// -// // Finally, Try to match on legacy name and magic number: -// results = XMaterial.matchXMaterial( blockType.getXMaterialNameLegacy() ).orElse( null ); -// } -// -// putCachedXMaterial( blockType, (byte) data, results ); -// } -// -// } -// -// } -// -// return results == NULL_TOKEN ? null : results; -// } -// public Material getMaterial( BlockType blockType ) { -// Material results = null; -// -// if ( blockType != null && blockType != BlockType.IGNORE ) { -// short data = blockType.getData(); -// -//// Material.bush -//// -//// Material.matchMaterial( name, legacyName ) -//// -//// results = getCachedXMaterial( blockType, (byte) data ); -//// if ( results == null ) { -//// -//// results = XMaterial.matchXMaterial( blockType.getXMaterialNameLegacy() ).orElse( null ); -//// -//// if ( results == null ) { -//// for ( String altName : blockType.getXMaterialAltNames() ) { -//// -//// results = XMaterial.matchXMaterial( altName ).orElse( null ); -//// -//// if ( results != null ) { -//// break; -//// } -//// } -//// } -//// -//// putCachedXMaterial( blockType, (byte) data, results ); -//// } -// -// } -// -// return results == NULL_TOKEN ? null : results; -// } - - -// @Override -// public void updateSpigotBlock( BlockType blockType, Block spigotBlock ) { -// -// if ( blockType != null && blockType != BlockType.IGNORE && spigotBlock != null ) { -// -// XMaterial xMat = getXMaterial( blockType ); -// -// if ( xMat != null ) { -// -// updateSpigotBlock( xMat, spigotBlock ); -// } -// } -// } - @Override public void updateSpigotBlock( PrisonBlock prisonBlock, Block spigotBlock ) { @@ -414,12 +222,6 @@ public void updateSpigotBlock( XMaterial xMat, Block spigotBlock ) { if ( xMat != null ) { -// XBlock.setType( spigotBlock, xMat ); -// -// BlockState bState = spigotBlock.getState(); -// // Force the update but don't apply the physics: -// bState.update( true, false ); - Material newType = xMat.parseMaterial(); if ( newType != null ) { @@ -440,66 +242,6 @@ public void updateSpigotBlock( XMaterial xMat, Block spigotBlock ) { -// @Override -// public void updateSpigotBlockAsync( BlockType blockType, Block spigotBlock ) { -// -// if ( blockType != null && blockType != BlockType.IGNORE && spigotBlock != null ) { -// -// XMaterial xMat = getXMaterial( blockType ); -// -// if ( xMat != null ) { -// -// updateSpigotBlockAsync( xMat, spigotBlock ); -// } -// } -// } -// -// -// @Override -// public void updateSpigotBlockAsync( PrisonBlock prisonBlock, Block spigotBlock ) { -// -// if ( prisonBlock != null && -// !prisonBlock.equals( PrisonBlock.IGNORE ) && -// spigotBlock != null ) { -// -// XMaterial xMat = getXMaterial( prisonBlock ); -// -// if ( xMat != null ) { -// -// updateSpigotBlockAsync( xMat, spigotBlock ); -// } -// } -// } -// -// -// @SuppressWarnings( "deprecation" ) -// @Override -// public void updateSpigotBlockAsync( XMaterial xMat, Block spigotBlock ) { -// -// if ( xMat != null ) { -// Material newType = xMat.parseMaterial(); -// if ( newType != null ) { -// -// new BukkitRunnable() { -// @Override -// public void run() { -// -// BlockState bState = spigotBlock.getState(); -// -// // Set the block state with the new type and rawData: -// bState.setType( newType ); -// bState.setRawData( xMat.getData() ); -// -// // Force the update but don't apply the physics: -// bState.update( true, false ); -// } -// }.runTaskLater( getPlugin(), 0 ); -// -// } -// } -// } - - /** *

    This function both get's the block and then updates it within * the same runnable transaction. This should eliminate the need to @@ -601,8 +343,6 @@ public BlockTestStats testCountAllBlockTypes() { if ( iStack != null ) { -// stats.addMaxData( data ); - if ( mat.isBlock() ) { stats.addCountBlocks(); } @@ -663,16 +403,6 @@ public boolean setDurability( SpigotItemStack itemStack, int damage ) { return results; } -// @SuppressWarnings( "deprecation" ) -// public int getDurability( SpigotItemStack itemInHand ) { -// return itemInHand.getBukkitStack().getDurability(); -// } -// -// @SuppressWarnings( "deprecation" ) -// public void setDurability( SpigotItemStack itemInHand, int newDurability ) { -// itemInHand.getBukkitStack().setDurability( (short) newDurability ); -// } - @Override public void setBlockFace( Block spigotBlock, BlockFace blockFace ) { @@ -730,27 +460,19 @@ public void setBlockFace( Block spigotBlock, BlockFace blockFace ) { @Override public ItemStack getLapisItemStack() { - return XMaterial.LAPIS_LAZULI.parseItem(); - - // This has VERY high runtime overhead: XMaterial.matchXMaterial("INK_SACK").get() - // Should use the following instead: XMaterial.INK_SAC - -// if (XMaterial.matchXMaterial("INK_SACK").isPresent() && XMaterial.matchXMaterial("INK_SACK").get().parseMaterial() != null) { -// return new ItemStack(XMaterial.matchXMaterial("INK_SACK").get().parseMaterial(), 1, (short) 4); -// } -// return null; + return XMaterial.LAPIS_LAZULI.parseItem(); } @Override public int getMinY() { - return 0; + return 0; } @Override public int getMaxY() { - return 255; + return 255; } @@ -762,7 +484,7 @@ public int getMaxY() { */ @Override public int getCustomModelData( SpigotItemStack itemStack ) { - return 0; + return 0; } /** * Not compatible with Spigot 1.8 through 1.13 so return a value of 0. @@ -772,7 +494,7 @@ public int getCustomModelData( SpigotItemStack itemStack ) { */ @Override public int getCustomModelData( ItemStack itemStack ) { - return 0; + return 0; } /** @@ -800,4 +522,79 @@ public void setCustomModelData( ItemStack itemStack, int customModelData ) { + /** + *

    With spigot 1.14 and newer, there is a function on a block that + * identifies if a block is passable. The description in the api docs are: + *

    + * + *
    +	 * Checks if this block is passable.
    +
    +A block is passable if it has no colliding parts that would prevent 
    +players from moving through it.
    +
    +Examples: Tall grass, flowers, signs, etc. are passable, but open doors, 
    +fence gates, trap doors, etc. are not because they still have parts that 
    +can be collided with.
    +	 * 

    + * + *

    For 1.8 through 1.13.x, just check the material type for + * some of the possibilities like what is listed. This does not + * need to be a complete list, but it can also be expanded as + * needed based upon feedback too. Some items really don't matter, + * such as crops or short grass, since it's only about one block + * from the ground, so the item, if thrown, will land near that + * area. + *

    + * + * @param bBlock + * @return + */ + @Override + public boolean isPassable( Block bBlock ) { + boolean results = false; + + if ( bBlock != null ) { + + XMaterial xMat = getXMaterial( bBlock ); + + if ( xMat != null ) { + + boolean isSign = xMat.name().toLowerCase().contains("sign"); + + if ( isSign || XBlock.isCrop(xMat) ) { + results = true; + } + + else { + + + switch ( xMat ) { + case AIR: + + case SHORT_GRASS: + case TALL_GRASS: + case SEAGRASS: + case TALL_SEAGRASS: + + case VINE: + case CAVE_VINES_PLANT: + case TWISTING_VINES_PLANT: + case WEEPING_VINES_PLANT: + + results = true; + break; + + default: + break; + } + } + + + } + } + + return results; + } + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Player.java index 4e35f8fb6..08e5aa7d4 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_8_Player.java @@ -43,7 +43,6 @@ public void setMaxHealth( Player player, double maxHealth ) { */ @Override public void sendTitle( Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut ) { - //player.sendTitle( title, subtitle ); title = title == null ? null : Text.translateAmpColorCodes( title ); subtitle = subtitle == null ? null : Text.translateAmpColorCodes( subtitle ); @@ -66,12 +65,6 @@ public void sendActionBar( Player player, String actionBar ) { String message = Text.translateAmpColorCodes( actionBar ); ActionBar.sendActionBar( player, message ); - // Was using the following until it was replaced with XSeries' ActionBar: -// player.sendTitle( "", actionBar ); - - // The following class does not exist under spigot 1.8.8 -// player.spigot().sendMessage( ChatMessageType.ACTION_BAR, -// new TextComponent( actionBar ) ); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9.java index 7f005893f..bbcb36d42 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9.java @@ -29,6 +29,7 @@ import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.spigot.block.SpigotItemStack; +import tech.mcprison.prison.spigot.game.SpigotPlayer; import tech.mcprison.prison.spigot.inventory.SpigotPlayerInventory; /** @@ -51,11 +52,11 @@ public EquipmentSlot getHand(PlayerInteractEvent e) { @Override public EquipmentSlot getHand(BlockPlaceEvent e) { - if (e.getHand() == null) { - return null; - } else { - return EquipmentSlot.valueOf(e.getHand().name()); - } + if (e.getHand() == null) { + return null; + } else { + return EquipmentSlot.valueOf(e.getHand().name()); + } } @Override @@ -65,28 +66,38 @@ public ItemStack getItemInMainHand(PlayerInteractEvent e) { @Override public ItemStack getItemInMainHand(Player player) { - return getItemInMainHand( player.getInventory() ); + return getItemInMainHand( player.getInventory() ); } @Override public ItemStack getItemInMainHand(PlayerInventory playerInventory) { - return playerInventory.getItemInMainHand(); + return playerInventory.getItemInMainHand(); } @Override public SpigotItemStack getPrisonItemInMainHand(PlayerInteractEvent e) { - return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( e ) ); + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( e ) ); } @Override public SpigotItemStack getPrisonItemInMainHand(Player player) { - return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player ) ); } + @Override + public SpigotItemStack getPrisonItemInMainHand(SpigotPlayer player) { + return SpigotUtil.bukkitItemStackToPrison( getItemInMainHand( player.getWrapper() ) ); + } + @Override public SpigotItemStack getPrisonItemInOffHand(Player player) { return SpigotUtil.bukkitItemStackToPrison( getItemInOffHand( player ) ); } + + @Override + public SpigotItemStack getPrisonItemInOffHand(SpigotPlayer player) { + return SpigotUtil.bukkitItemStackToPrison( getItemInOffHand( player.getWrapper() ) ); + } @Override public ItemStack getItemInOffHand(PlayerInteractEvent e) { @@ -100,28 +111,50 @@ public ItemStack getItemInOffHand(Player player ) { @Override public ItemStack getItemInOffHand(PlayerInventory playerInventory) { - return playerInventory.getItemInOffHand(); + return playerInventory.getItemInOffHand(); } + /** + * 1.9 and higher supports off-hand: + */ + @Override + public ItemStack getItemInOffHandStrict(Player player) { + return getItemInOffHand(player.getInventory()); + } + + /** + * 1.9 and higher supports off-hand: + */ + @Override + public void setItemStackInOffHandStrict(Player player, ItemStack itemStack) { + + player.getInventory().setItemInOffHand(itemStack); + } + @Override public void setItemStackInMainHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ) { - ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) - .setItemInMainHand( itemStack.getBukkitStack() ); + ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) + .setItemInMainHand( itemStack.getBukkitStack() ); } @Override public void setItemInMainHand(Player p, ItemStack itemStack) { p.getInventory().setItemInMainHand(itemStack); } + + @Override + public void setItemInMainHand(SpigotPlayer p, ItemStack itemStack) { + p.getWrapper().getInventory().setItemInMainHand(itemStack); + } @Override public void setItemStackInOffHand( SpigotPlayerInventory inventory, SpigotItemStack itemStack ) { - ItemStack iStack = itemStack == null ? null : itemStack.getBukkitStack(); - - ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) - .setItemInOffHand( iStack ); + ItemStack iStack = itemStack == null ? null : itemStack.getBukkitStack(); + + ((org.bukkit.inventory.PlayerInventory) inventory.getWrapper()) + .setItemInOffHand( iStack ); } @Override public void playIronDoorSound(Location loc) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9_Player.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9_Player.java index ce90aca41..6c9a3837c 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9_Player.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/compat/Spigot_1_9_Player.java @@ -53,10 +53,5 @@ public void sendActionBar( Player player, String actionBar ) { String message = Text.translateAmpColorCodes( actionBar ); ActionBar.sendActionBar( player, message ); - // Was using the following until it was replaced with XSeries' ActionBar: -// player.spigot().sendMessage( ChatMessageType.ACTION_BAR, -// new TextComponent( actionBar ) ); - -// player.sendTitle( "", actionBar ); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/BackpacksConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/BackpacksConfig.java index 0cde03a9f..60bccaae9 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/BackpacksConfig.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/BackpacksConfig.java @@ -25,8 +25,10 @@ public BackpacksConfig(){ public void initialize(){ + String path = "/backpacks/backpacksconfig.yml"; + // Filepath - File file = new File(SpigotPrison.getInstance().getDataFolder() + "/backpacks/backpacksconfig.yml"); + File file = new File(SpigotPrison.getInstance().getDataFolder() + path ); // Check if the config exists fileMaker(file); @@ -48,10 +50,17 @@ public void initialize(){ if (changeCount > 0) { try { conf.save(file); - Output.get().logInfo( "&aThere were &b%d &anew values added for the language files " + "used by the SellAllConfig.yml file located at &b%s", changeCount, file.getAbsoluteFile() ); + Output.get().logInfo( "&aThere were &b%d &anew values added for the language files " + + "used by the '%s' file located at &b%s", + changeCount, + path, file.getAbsoluteFile() ); } catch (IOException e) { - Output.get().logInfo( "&4Failed to save &b%d &4new values for the language files " + "used by the SellAllConfig.yml file located at &b%s&4. " + "&a %s", changeCount, file.getAbsoluteFile(), e.getMessage() ); + Output.get().logInfo( "&4Failed to save &b%d &4new values for the language files " + + "used by the '%s' file located at &b%s&4. " + + "&a %s", + changeCount, + path, file.getAbsoluteFile(), e.getMessage() ); } } 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 bba355b22..8c1f76d94 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 @@ -66,7 +66,7 @@ public void initialize() { } if ( conf.getList( "EditableLore.README-Updated-2022-12-22" ) == null ) { - List lore = new ArrayList<>(); + List lore = new ArrayList<>(); lore.add(" "); lore.add("&8-----------------------"); lore.add("&7 WARNING!! DO NOT EDIT THESE!!"); @@ -130,16 +130,16 @@ public void initialize() { } if (conf.getList("EditableLore.Rank.default.Z") == null){ - List lore = new ArrayList<>(); - lore.add(" "); - lore.add("&8-----------------------"); - lore.add("&3The end of the most amazing adventure."); - lore.add("&3But... if you do '/prestige' you can start"); - lore.add("&3start over and have even more fun!"); - lore.add("&8-----------------------"); - - conf.set("EditableLore.Rank.default.Z", lore); - changeCount++; + List lore = new ArrayList<>(); + lore.add(" "); + lore.add("&8-----------------------"); + lore.add("&3The end of the most amazing adventure."); + lore.add("&3But... if you do '/prestige' you can start"); + lore.add("&3start over and have even more fun!"); + lore.add("&8-----------------------"); + + conf.set("EditableLore.Rank.default.Z", lore); + changeCount++; } if (conf.getList("EditableLore.Rank.prestiges.p1") == null){ @@ -186,182 +186,188 @@ public void initialize() { } if (conf.getList("EditableLore.Mine.Z") == null){ - List lore = new ArrayList<>(); - lore.add(" "); - lore.add("&8-----------------------"); - lore.add("&3Time to get ready to prestige, and restart the fun adventure!"); - lore.add("&8-----------------------"); - - conf.set("EditableLore.Mine.Z", lore); - changeCount++; + List lore = new ArrayList<>(); + lore.add(" "); + lore.add("&8-----------------------"); + lore.add("&3Time to get ready to prestige, and restart the fun adventure!"); + lore.add("&8-----------------------"); + + conf.set("EditableLore.Mine.Z", lore); + changeCount++; } if ( conf.get( "Options.Mines.MaterialType" ) == null ) { - if ( PrisonMines.getInstance() != null ) { - - LinkedHashMap map = new LinkedHashMap<>(); - - map.put("NoMineAccess", XMaterial.REDSTONE_BLOCK.name() ); - - - if ( PrisonMines.getInstance().getMineManager() != null && - PrisonMines.getInstance().getMineManager().getMines() != null && - PrisonMines.getInstance().getMineManager().getMines().size() > 0 ) { - - for ( Mine mine : PrisonMines.getInstance().getMineManager().getMines() ) { - if ( mine.getPrisonBlocks().size() > 0 ) { - map.put( mine.getName(), mine.getPrisonBlocks().get(0).getBlockName() ); - } - } - } - - conf.set("Options.Mines.MaterialType", map); - changeCount++; - } + if ( PrisonMines.getInstance() != null ) { + + LinkedHashMap map = new LinkedHashMap<>(); + + map.put("NoMineAccess", XMaterial.REDSTONE_BLOCK.name() ); + + + if ( PrisonMines.getInstance().getMineManager() != null && + PrisonMines.getInstance().getMineManager().getMines() != null && + PrisonMines.getInstance().getMineManager().getMines().size() > 0 ) { + + for ( Mine mine : PrisonMines.getInstance().getMineManager().getMines() ) { + if ( mine.getPrisonBlocks().size() > 0 ) { + map.put( mine.getName(), mine.getPrisonBlocks().get(0).getBlockName() ); + } + } + } + + conf.set("Options.Mines.MaterialType", map); + changeCount++; + } } else if ( conf.get( "Options.Mines.MaterialType.NoMineAccess" ) == null ) { - String noMineAccess = XMaterial.REDSTONE_BLOCK.name(); - - conf.set("Options.Mines.MaterialType.NoMineAccess", noMineAccess ); - changeCount++; + String noMineAccess = XMaterial.REDSTONE_BLOCK.name(); + + conf.set("Options.Mines.MaterialType.NoMineAccess", noMineAccess ); + changeCount++; } + + + if ( conf.get( "Options.Mines.MaterialType.HasMineAccess" ) == null ) { - String hasMineAccess = XMaterial.COAL_ORE.name(); - - conf.set("Options.Mines.MaterialType.HasMineAccess", hasMineAccess ); - changeCount++; - } + String hasMineAccess = XMaterial.COAL_ORE.name(); + + conf.set("Options.Mines.MaterialType.HasMineAccess", hasMineAccess ); + changeCount++; + } if ( conf.get( "Options.Ranks.MaterialType" ) == null ) { - if ( PrisonRanks.getInstance() != null ) { - - LinkedHashMap map = new LinkedHashMap<>(); - - map.put("NoRankAccess", XMaterial.REDSTONE_BLOCK.name() ); - - if ( PrisonRanks.getInstance().getRankManager() != null && - PrisonRanks.getInstance().getRankManager().getRanks() != null && - PrisonRanks.getInstance().getRankManager().getRanks().size() > 0 ) { - - // 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++; - } + if ( PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { + + LinkedHashMap map = new LinkedHashMap<>(); + + map.put("NoRankAccess", XMaterial.REDSTONE_BLOCK.name() ); + + if ( PrisonRanks.getInstance().getRankManager() != null && + PrisonRanks.getInstance().getRankManager().getRanks() != null && + PrisonRanks.getInstance().getRankManager().getRanks().size() > 0 ) { + + // 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.NoRankAccess" ) == null ) { - - String noRankAccess = XMaterial.REDSTONE_BLOCK.name(); - - conf.set("Options.Ranks.MaterialType.NoRankAccess", noRankAccess ); - changeCount++; + + String noRankAccess = XMaterial.REDSTONE_BLOCK.name(); + + conf.set("Options.Ranks.MaterialType.NoRankAccess", noRankAccess ); + changeCount++; } + + if ( conf.get( "Options.Ranks.MaterialType.HasRankAccess" ) == null ) { - String hasRankAccess = XMaterial.TRIPWIRE_HOOK.name(); - - conf.set("Options.Ranks.MaterialType.HasRankAccess", hasRankAccess ); - changeCount++; + String hasRankAccess = XMaterial.TRIPWIRE_HOOK.name(); + + conf.set("Options.Ranks.MaterialType.HasRankAccess", hasRankAccess ); + changeCount++; } // The following is an error and should be removed if it is found: if ( conf.get( "Options.Ranks.MaterialType.NoMineAccess" ) == null ) { - - conf.set("Options.Ranks.MaterialType.NoMineAccess", null ); - changeCount++; + + conf.set("Options.Ranks.MaterialType.NoMineAccess", null ); + changeCount++; } if ( conf.get( "Options.Ranks.Item_gotten_rank" ) == null ) { - conf.set("Options.Ranks.Item_gotten_rank", null ); - changeCount++; + conf.set("Options.Ranks.Item_gotten_rank", null ); + changeCount++; } if ( conf.get( "Options.Ranks.Item_not_gotten_rank" ) == null ) { - - conf.set("Options.Ranks.Item_not_gotten_rank", null ); - changeCount++; + + conf.set("Options.Ranks.Item_not_gotten_rank", null ); + changeCount++; } if ( conf.get( "Options.Mines.GuiItemNameDefault" ) == null ) { - String defaultName = "{mineTag}"; - - conf.set("Options.Mines.GuiItemNameDefault", defaultName ); - changeCount++; + String defaultName = "{mineTag}"; + + conf.set("Options.Mines.GuiItemNameDefault", defaultName ); + changeCount++; } if ( conf.get( "Options.Mines.GuiItemNames" ) == null ) { - if ( PrisonMines.getInstance() != null && - PrisonMines.getInstance().getMineManager() != null && - PrisonMines.getInstance().getMineManager().getMines() != null && - PrisonMines.getInstance().getMineManager().getMines().size() > 0 ) { - - 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 ( PrisonMines.getInstance() != null && + PrisonMines.getInstance().getMineManager() != null && + PrisonMines.getInstance().getMineManager().getMines() != null && + PrisonMines.getInstance().getMineManager().getMines().size() > 0 ) { + + 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++; + String defaultName = "{rankTag}"; + + conf.set("Options.Ranks.GuiItemNameDefault", defaultName ); + changeCount++; } if ( conf.get( "Options.Ranks.GuiItemNames" ) == null ) { - if ( PrisonRanks.getInstance() != null && - PrisonRanks.getInstance().getRankManager() != null && - PrisonRanks.getInstance().getRankManager().getRanks() != null && - PrisonRanks.getInstance().getRankManager().getRanks().size() > 0 ) { - - 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++; - } + if ( PrisonRanks.getInstance() != null && + PrisonRanks.getInstance().isEnabled() && + PrisonRanks.getInstance().getRankManager() != null && + PrisonRanks.getInstance().getRankManager().getRanks() != null && + PrisonRanks.getInstance().getRankManager().getRanks().size() > 0 ) { + + 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 { + try { conf.save(file); Output.get().logInfo("&aThere were &b%d &anew values added to the GuiConfig.yml file located at &b%s", changeCount, file.getAbsoluteFile()); } @@ -374,10 +380,10 @@ else if ( conf.get( "Options.Ranks.MaterialType.NoRankAccess" ) == null ) { } private void dataConfig(String key, Object value){ - if (conf.getString(key) == null) { - conf.set(key, value); - changeCount++; - } + if (conf.getString(key) == null) { + conf.set(key, value); + changeCount++; + } } // All the strings of the config should be here diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java index 14d29f89d..51de7bcdb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/MessagesConfig.java @@ -81,14 +81,14 @@ private void initConfig(){ String line = br.readLine(); while ( line != null ) { - if ( !line.startsWith( "#" ) && line.contains( "=" ) ) { - - String[] keyValue = line.split( "\\=" ); - String value = (keyValue.length > 1 ? keyValue[1] : ""); // StringEscapeUtils.escapeJava( keyValue[1] ); - temp.put( keyValue[0], value ); - } - - line = br.readLine(); + if ( !line.startsWith( "#" ) && line.contains( "=" ) ) { + + String[] keyValue = line.split( "\\=" ); + String value = (keyValue.length > 1 ? keyValue[1] : ""); // StringEscapeUtils.escapeJava( keyValue[1] ); + temp.put( keyValue[0], value ); + } + + line = br.readLine(); } // WARNING: cannot use the properties.load() function since it is NOT utf-8 capable. @@ -105,13 +105,13 @@ private void initConfig(){ * */ public String getString(StringID message){ - String msg = properties.getProperty(message.toString()); - - if ( msg == null || msg.trim().isEmpty() ) { - msg = message.name(); - } - - return msg; + String msg = properties.getProperty(message.toString()); + + if ( msg == null || msg.trim().isEmpty() ) { + msg = message.name(); + } + + return msg; } @Deprecated diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java index f12eb6823..ce5267b1a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SellAllConfig.java @@ -26,8 +26,10 @@ public SellAllConfig(){ public void initialize(){ + String path = "/SellAllConfig.yml"; + // Filepath - File file = new File(SpigotPrison.getInstance().getDataFolder() + "/SellAllConfig.yml"); + File file = new File(SpigotPrison.getInstance().getDataFolder() + path ); // Check if the config exists fileMaker(file); @@ -50,10 +52,15 @@ public void initialize(){ if (changeCount > 0) { try { conf.save(file); - Output.get().logInfo( "&aThere were &b%d &anew values added for the language files " + "used by the SellAllConfig.yml file located at &b%s", changeCount, file.getAbsoluteFile() ); + Output.get().logInfo( "&aThere were &b%d &anew values added for the language files " + + "used by the '%s' file located at &b%s", + changeCount, path, file.getAbsoluteFile() ); } catch (IOException e) { - Output.get().logInfo( "&4Failed to save &b%d &4new values for the language files " + "used by the SellAllConfig.yml file located at &b%s&4. " + "&a %s", changeCount, file.getAbsoluteFile(), e.getMessage() ); + Output.get().logInfo( "&4Failed to save &b%d &4new values for the language files " + + "used by the '%s' file located at &b%s&4. " + + "&a %s", changeCount, + path, file.getAbsoluteFile(), e.getMessage() ); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SpigotConfigComponents.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SpigotConfigComponents.java index 2d1912b52..32c5d9a9e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SpigotConfigComponents.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/configs/SpigotConfigComponents.java @@ -1,6 +1,6 @@ package tech.mcprison.prison.spigot.configs; -import org.bukkit.configuration.Configuration; +//import org.bukkit.configuration.Configuration; import java.io.File; import java.io.IOException; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java index 63debc9c5..34fd07fcb 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItems.java @@ -15,7 +15,7 @@ import tech.mcprison.prison.spigot.SpigotPrison; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.game.SpigotPlayer; -import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; +import tech.mcprison.prison.util.BluesSemanticVersionComparator; import tech.mcprison.prison.util.Location; /** @@ -35,7 +35,7 @@ public CustomItems() { @Override public void integrate() { - BluesSpigetSemVerComparator semVer = new BluesSpigetSemVerComparator(); + BluesSemanticVersionComparator semVer = new BluesSemanticVersionComparator(); if ( isRegistered()) { try { @@ -147,27 +147,6 @@ public PrisonBlock getCustomBlock( Block block ) { return results; } -// public PrisonBlock getCustomBlock( org.bukkit.block.Block spigotBlock ) { -// PrisonBlock results = null; -// -// String customBlockId = getCustomBlockId( spigotBlock ); -// -// if ( customBlockId != null ) { -// results = SpigotPrison.getInstance().getPrisonBlockTypes() -// .getBlockTypesByName( customBlockId ); -// -// if ( results != null ) { -// Location loc = SpigotUtil.bukkitLocationToPrison( spigotBlock.getLocation() ); -// -// results.setLocation( loc ); -// } -// -// SpigotBlock sBlock = new SpigotBlock(); -// } -// -// return results; -// } - @Override public Block setCustomBlockId( Block block, String customId, boolean doBlockUpdate ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java index 207668d7d..5e66997cf 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/CustomItemsWrapper.java @@ -88,10 +88,8 @@ public void run() { SpigotBlock sBlock = (SpigotBlock) location.getBlockAt(); org.bukkit.block.Block spigotBlock = sBlock.getWrapper(); - //org.bukkit.block.Block spigotBlock = ((SpigotBlock) prisonBlock).getWrapper(); // Request the block change, but we don't need the results so ignore it -// org.bukkit.block.Block resultBlock = CustomItemsAPI.setCustomItemIDAtBlock( spigotBlock, prisonBlock.getBlockName(), true ); } @@ -154,7 +152,6 @@ public List getDrops( PrisonBlock prisonBlock, SpigotPlayer pla catch (Exception e) { Output.get().logError( "Failed: CustomItemsWrapper.getDrops: breakCustomItemBlockWithoutDrops: ", e ); -// e.printStackTrace(); } if ( cuiDropResults != null ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/HeadsCustomBlocks.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/HeadsCustomBlocks.java index 2cec5e494..5b0ae4d39 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/HeadsCustomBlocks.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/HeadsCustomBlocks.java @@ -26,7 +26,6 @@ public HeadsCustomBlocks() { @Override public String getCustomBlockId( Block block ) { - // TODO Auto-generated method stub return null; } @@ -34,7 +33,6 @@ public String getCustomBlockId( Block block ) @Override public PrisonBlock getCustomBlock( Block block ) { - // TODO Auto-generated method stub return null; } @@ -42,7 +40,6 @@ public PrisonBlock getCustomBlock( Block block ) @Override public Block setCustomBlockId( Block block, String customId, boolean doBlockUpdate ) { - // TODO Auto-generated method stub return null; } @@ -50,7 +47,6 @@ public Block setCustomBlockId( Block block, String customId, boolean doBlockUpda @Override public void setCustomBlockIdAsync( PrisonBlock prisonBlock, Location location ) { - // TODO Auto-generated method stub } @@ -63,21 +59,18 @@ public List getCustomBlockList() return results; } - -// @Override -// public List getDrops( PrisonBlock prisonBlock ) -// { -// List results = new ArrayList<>(); -// -// return results; -// } - - @Override public List getDrops(Player player, PrisonBlock prisonBlock, ItemStack tool) { List results = new ArrayList<>(); return results; } + + protected HeadsCustomBlocksWrapper getHeadsCustomBlocksWrapper() { + return headsCustomBlocksWrapper; + } + protected void setHeadsCustomBlocksWrapper(HeadsCustomBlocksWrapper headsCustomBlocksWrapper) { + this.headsCustomBlocksWrapper = headsCustomBlocksWrapper; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/PrisonItemsAdder.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/PrisonItemsAdder.java index 18387d4fd..ce8853492 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/PrisonItemsAdder.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/PrisonItemsAdder.java @@ -26,13 +26,10 @@ public PrisonItemsAdder() { } - @Override public void integrate() { - // BluesSpigetSemVerComparator semVer = new BluesSpigetSemVerComparator(); - if ( isRegistered()) { try { @@ -134,7 +131,6 @@ public PrisonBlock getCustomBlock( org.bukkit.block.Block spigotBlock ) { results.setLocation( loc ); } -// SpigotBlock sBlock = new SpigotBlock(); } return results; diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/PrisonItemsAdderWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/PrisonItemsAdderWrapper.java index 26621859d..b225ce876 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/PrisonItemsAdderWrapper.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/customblock/PrisonItemsAdderWrapper.java @@ -54,7 +54,6 @@ public String getCustomBlockId( Block block ) { org.bukkit.block.Block spigotBlock = ((SpigotBlock) block).getWrapper(); return getCustomBlockId( spigotBlock ); - //return CustomItemsAPI.getCustomItemIDAtBlock( spigotBlock ); } public String getCustomBlockId( org.bukkit.block.Block spigotBlock ) { @@ -62,7 +61,6 @@ public String getCustomBlockId( org.bukkit.block.Block spigotBlock ) { CustomBlock cBlock = CustomBlock.byAlreadyPlaced(spigotBlock); return ( cBlock == null ? null : cBlock.getDisplayName() ); - //return CustomItemsAPI.getCustomItemIDAtBlock( spigotBlock ); } @@ -84,16 +82,6 @@ public Block setCustomBlockId( Block block, String customId, boolean doBlockUpda CustomBlock cBlock = CustomBlock.place( cBlockId, sBlock.getWrapper().getLocation() ); return SpigotBlock.getSpigotBlock( cBlock.getBlock() ); - - -// org.bukkit.block.Block spigotBlock = ((SpigotBlock) block).getWrapper(); - - // So to prevent this from causing lag, we will only get back the block with no updates - // This will allow this function to exit: -// org.bukkit.block.Block resultBlock = -// CustomItemsAPI.setCustomItemIDAtBlock( spigotBlock, customId, doBlockUpdate ); - -// return SpigotBlock.getSpigotBlock( resultBlock ); } @@ -124,17 +112,6 @@ public void run() { CustomBlock cBlock = CustomBlock.place( cBlockId, sBlock.getWrapper().getLocation() ); - // No physics update: - -// SpigotBlock sBlock = (SpigotBlock) location.getBlockAt(); -// -// org.bukkit.block.Block spigotBlock = sBlock.getWrapper(); - //org.bukkit.block.Block spigotBlock = ((SpigotBlock) prisonBlock).getWrapper(); - - // Request the block change, but we don't need the results so ignore it -// org.bukkit.block.Block resultBlock = -// CustomItemsAPI.setCustomItemIDAtBlock( spigotBlock, prisonBlock.getBlockName(), true ); - } }.runTaskLater( getPlugin(), 0 ); @@ -226,9 +203,6 @@ public List getDrops( PrisonBlock prisonBlock, SpigotPlayer pla public List getCustomBlockList() { List customList = new ArrayList<>(); -// List customListx = new ArrayList<>( CustomBlock.getNamespacedIdsInRegistry() ); - - List allItems = ItemsAdder.getAllItems(); for ( CustomStack cStack : allItems ) { 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 index 95de2fc10..ebc1c88db 100644 --- 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 @@ -11,7 +11,7 @@ public class CoinsEngineEconomy private boolean availableAsAnAlternative = false; public CoinsEngineEconomy() { - super( "CoinsEngineEconomy", "CoinsEngineEconomy" ); + super( "CoinsEngine", "CoinsEngine" ); } /** @@ -51,184 +51,172 @@ public boolean supportedCurrency( String currencyName ) { @Override public double getBalance(Player player) { - double amount = 0; - if ( wrapper != null ) { - - synchronized ( wrapper ) { - amount = wrapper.getBalance(player); - } - } - return amount; + double amount = 0; + if ( wrapper != null ) { + + synchronized ( wrapper ) { + amount = wrapper.getBalance(player); + } + } + return amount; } @Override public boolean hasAccount( Player player ) { - return true; + return true; } @Override public double getBalance(Player player, String currencyName) { - double amount = 0; - if ( wrapper != null ) { - - synchronized ( wrapper ) { - amount = wrapper.getBalance(player, currencyName, false); - } - } - return amount; + double amount = 0; + if ( wrapper != null ) { + + synchronized ( wrapper ) { + amount = wrapper.getBalance(player, currencyName, false); + } + } + return amount; } -// @Override -// public double getBalance(Player player, String currencyName, boolean quite) { -// double amount = 0; -// if ( wrapper != null ) { -// -// synchronized ( wrapper ) { -// amount = wrapper.getBalance(player, currencyName, quite); -// } -// } -// 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; + 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; + 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; + 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; - } - } + 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; + 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; + 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; + 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; + boolean results = false; + if ( wrapper != null ) { + results = getBalance(player, currencyName) >= amount; + } + return results; } @Override @@ -238,14 +226,14 @@ public boolean hasIntegrated() { @Override public void disableIntegration() { - wrapper = null; + wrapper = null; } @Override public String getDisplayName() { - return super.getDisplayName() + - ( availableAsAnAlternative ? " (disabled)" : ""); + return super.getDisplayName() + + ( availableAsAnAlternative ? " (disabled)" : ""); } @Override 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 index c3e7fca1c..2744aeef0 100644 --- 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 @@ -43,7 +43,7 @@ public Currency getCurrency( String currencyNamme ) { public double getBalance(Player player) { - Output.get().logWarn( "CoinsEngineEconomy getBalance() - Fail: MUST include a currencyName."); + Output.get().logWarn( "CoinsEngine getBalance() - Fail: MUST include a currencyName."); return getBalance(player, null, false); } @@ -64,7 +64,7 @@ public double getBalance(Player player, String currencyName, boolean quite ) { public void addBalance(Player player, double amount) { - Output.get().logWarn( "CoinsEngineEconomy addBalance() - Fail: MUST include a currencyName."); + Output.get().logWarn( "CoinsEngine addBalance() - Fail: MUST include a currencyName."); addBalance(player, amount, null); } @@ -85,7 +85,7 @@ public void addBalance(Player player, double amount, String currencyName) { public void withdraw(Player player, double amount) { - Output.get().logWarn( "CoinsEngineEconomy withdraw() - Fail: MUST include a currencyName."); + Output.get().logWarn( "CoinsEngine withdraw() - Fail: MUST include a currencyName."); withdraw(player, amount, null); } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EdPrisonEconomy.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EdPrisonEconomy.java index aaad214de..202e6ea17 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EdPrisonEconomy.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EdPrisonEconomy.java @@ -13,7 +13,7 @@ public class EdPrisonEconomy private boolean availableAsAnAlternative = false; public EdPrisonEconomy() { - super( "EdPrison", "EdPrison" ); + super( "EdPrison", "EdPrison" ); } @@ -72,137 +72,126 @@ public boolean supportedCurrency( String currencyName ) { @Override public boolean hasAccount( Player player ) { - return true; + return true; } @Override public double getBalance(Player player) { - double amount = getBalance( player, null ); - - return amount; + double amount = getBalance( player, null ); + + return amount; } @Override public double getBalance(Player player, String currencyName) { - double amount = 0; - if ( wrapper != null ) { - - synchronized ( wrapper ) { - amount = wrapper.getBalance(player, currencyName, false); - } - } - return amount; + double amount = 0; + if ( wrapper != null ) { + + synchronized ( wrapper ) { + amount = wrapper.getBalance(player, currencyName, false); + } + } + return amount; } -// @Override -// public double getBalance(Player player, String currencyName, boolean quite) { -// double amount = 0; -// if ( wrapper != null ) { -// -// synchronized ( wrapper ) { -// amount = wrapper.getBalance(player, currencyName, quite); -// } -// } -// return amount; -// } @Override public boolean setBalance(Player player, double amount) { - boolean results = setBalance( player, amount, null ); - - return results; + boolean results = setBalance( player, amount, null ); + + 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; + 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 = addBalance( player, amount, null ); - - return results; + boolean results = addBalance( player, amount, null ); + + 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; + 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 = removeBalance( player, amount, null ); - - return results; + boolean results = removeBalance( player, amount, null ); + + 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; + 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 = canAfford( player, amount, null ); - - return results; + boolean results = canAfford( player, amount, null ); + + 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; + boolean results = false; + if ( wrapper != null ) { + results = getBalance(player, currencyName) >= amount; + } + return results; } @Override @@ -212,14 +201,14 @@ public boolean hasIntegrated() { @Override public void disableIntegration() { - wrapper = null; + wrapper = null; } @Override public String getDisplayName() { - return super.getDisplayName() + - ( availableAsAnAlternative ? " (disabled)" : ""); + return super.getDisplayName() + + ( availableAsAnAlternative ? " (disabled)" : ""); } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EdPrisonEconomyWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EdPrisonEconomyWrapper.java index 33181f97b..87f92e9ca 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EdPrisonEconomyWrapper.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EdPrisonEconomyWrapper.java @@ -57,11 +57,6 @@ public boolean supportedCurrency( String currencyName ) { } - -// public double getBalance(Player player) { -// return getBalance(player, null); -// } - public double getBalance(Player player, String currencyName, boolean quite) { double results = 0; if ( isEnabled() && currencyName != null ) { diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EssEconomyWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EssEconomyWrapper.java index 595461b22..542f697db 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EssEconomyWrapper.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EssEconomyWrapper.java @@ -39,17 +39,17 @@ class EssEconomyWrapper { public boolean hasAccount( Player player ) { - return Economy.playerExists( player.getName() ); + return Economy.playerExists( player.getName() ); } - double getBalance(Player player) { + public double getBalance(Player player) { try { - if ( hasAccount( player ) ) { - return Economy.getMoneyExact(player.getName()).doubleValue(); - } - - player.sendMessage( "You don't exist in the economy plugin." ); - return 0; + if ( hasAccount( player ) ) { + return Economy.getMoneyExact(player.getName()).doubleValue(); + } + + player.sendMessage( "You don't exist in the economy plugin." ); + return 0; } catch (UserDoesNotExistException e) { player.sendMessage("You don't exist in the economy plugin."); @@ -57,11 +57,11 @@ public boolean hasAccount( Player player ) { } } - void setBalance(Player player, double amount) { + public void setBalance(Player player, double amount) { try { if ( hasAccount( player ) ) { Economy.setMoney(player.getName(), new BigDecimal(amount)); - } + } else { player.sendMessage( "You don't exist in the economy plugin." ); diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EssentialsEconomy.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EssentialsEconomy.java index 2109b5841..37f3be37d 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EssentialsEconomy.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/EssentialsEconomy.java @@ -40,7 +40,7 @@ public class EssentialsEconomy private boolean availableAsAnAlternative = false; public EssentialsEconomy() { - super( "EssentialsX", "Essentials" ); + super( "EssentialsX", "Essentials" ); } @@ -102,7 +102,7 @@ public void integrate() { @Override public boolean hasAccount( Player player ) { - return wrapper.hasAccount( player ); + return wrapper.hasAccount( player ); } @Override @@ -138,14 +138,14 @@ public boolean hasIntegrated() { @Override public void disableIntegration() { - wrapper = null; + wrapper = null; } @Override public String getDisplayName() { - return super.getDisplayName() + - ( availableAsAnAlternative ? " (disabled)" : ""); + return super.getDisplayName() + + ( availableAsAnAlternative ? " (disabled)" : ""); } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/GemsEconomy.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/GemsEconomy.java index f53cc40d9..1ee6a20ae 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/GemsEconomy.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/GemsEconomy.java @@ -11,7 +11,7 @@ public class GemsEconomy private boolean availableAsAnAlternative = false; public GemsEconomy() { - super( "GemsEconomy", "GemsEconomy" ); + super( "GemsEconomy", "GemsEconomy" ); } /** @@ -52,184 +52,173 @@ public boolean supportedCurrency( String currencyName ) { @Override public boolean hasAccount( Player player ) { - return wrapper.hasAccount( player ); + return wrapper.hasAccount( player ); } @Override public double getBalance(Player player) { - double amount = 0; - if ( wrapper != null ) { - - synchronized ( wrapper ) { - amount = wrapper.getBalance(player); - } - } - return amount; + 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, false); - } - } - return amount; + double amount = 0; + if ( wrapper != null ) { + + synchronized ( wrapper ) { + amount = wrapper.getBalance(player, currencyName, false); + } + } + return amount; } -// @Override -// public double getBalance(Player player, String currencyName, boolean quite) { -// double amount = 0; -// if ( wrapper != null ) { -// -// synchronized ( wrapper ) { -// amount = wrapper.getBalance(player, currencyName, quite); -// } -// } -// 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; + 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; + 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; + 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; + 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; + 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; + 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; + 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; + boolean results = false; + if ( wrapper != null ) { + results = getBalance(player, currencyName) >= amount; + } + return results; } @Override @@ -239,14 +228,14 @@ public boolean hasIntegrated() { @Override public void disableIntegration() { - wrapper = null; + wrapper = null; } @Override public String getDisplayName() { - return super.getDisplayName() + - ( availableAsAnAlternative ? " (disabled)" : ""); + return super.getDisplayName() + + ( availableAsAnAlternative ? " (disabled)" : ""); } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/GemsEconomyWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/GemsEconomyWrapper.java index 085044645..97bd14a7a 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/GemsEconomyWrapper.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/GemsEconomyWrapper.java @@ -52,14 +52,6 @@ public boolean supportedCurrency( String currencyName ) { return supported; } -// -// public boolean supportedCurrency( String currencyName ) { -// Currency currency = getCurrency( currencyName ); -// -// boolean supported = (currency != null); -// -// return supported; -// } private Object getCurrencyRefection( String currencyName ) { Object results = null; @@ -79,18 +71,9 @@ private Object getCurrencyRefection( String currencyName ) { return results; } -// public Currency getCurrency( String currencyName ) { -// Currency currency = null; -// if (economy != null && -// currencyName != null && currencyName.trim().length() > 0) { -// currency = economy.getCurrency( currencyName ); -// } -// return currency; -// } - public boolean hasAccount( Player player ) { - return true; + return true; } public double getBalance(Player player) { @@ -164,18 +147,6 @@ private double getBalanceReflection( UUID uuid, String currencyName, String play return results; } -// public double getBalance(Player player, String currencyName) { -// double results = 0; -// if (economy != null) { -// Currency currency = getCurrency( currencyName ); -// if ( currency == null ) { -// results = economy.getBalance(player.getUUID()); -// } else { -// results = economy.getBalance(player.getUUID(), currency); -// } -// } -// return results; -// } public void addBalance(Player player, double amount) { @@ -188,8 +159,6 @@ public void addBalance(Player player, double amount, String currencyName) { economy.deposit(player.getUUID(), amount); } else { -// Currency currency = getCurrency( currencyName ); -// economy.deposit(player.getUUID(), amount, currency); addBalanceReflection( player.getUUID(), amount, currencyName ); } } @@ -227,16 +196,6 @@ private void addBalanceReflection(UUID uuid, double amount, String currencyName } -// public void addBalance(Player player, double amount, String currencyName) { -// if (economy != null) { -// Currency currency = getCurrency( currencyName ); -// if ( currency == null ) { -// economy.deposit(player.getUUID(), amount); -// } else { -// economy.deposit(player.getUUID(), amount, currency); -// } -// } -// } public void withdraw(Player player, double amount) { @@ -249,8 +208,6 @@ public void withdraw(Player player, double amount, String currencyName) { economy.withdraw(player.getUUID(), amount); } else { -// Currency currency = getCurrency( currencyName ); -// economy.withdraw(player.getUUID(), amount, currency); withdrawReflection( player.getUUID(), amount, currencyName ); } } @@ -289,15 +246,5 @@ private void withdrawReflection(UUID uuid, double amount, String currencyName ) } } -// public void withdraw(Player player, double amount, String currencyName) { -// if (economy != null) { -// Currency currency = getCurrency( currencyName ); -// if ( currency == null ) { -// economy.withdraw(player.getUUID(), amount); -// } else { -// economy.withdraw(player.getUUID(), amount, currency); -// } -// } -// } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/SaneEconomy.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/SaneEconomy.java index 5a78538bb..840bbdcf7 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/SaneEconomy.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/SaneEconomy.java @@ -16,7 +16,7 @@ public class SaneEconomy private boolean availableAsAnAlternative = false; public SaneEconomy() { - super( "SaneEconomy", "SaneEconomy" ); + super( "SaneEconomy", "SaneEconomy" ); } @Override @@ -39,7 +39,7 @@ public void integrate() { @Override public boolean hasAccount( Player player ) { - return econWrapper.hasAccount( player ); + return econWrapper.hasAccount( player ); } @Override @@ -49,8 +49,8 @@ public double getBalance(Player player) { @Override public boolean setBalance(Player player, double amount) { - econWrapper.setBalance(player, amount); - return true; + econWrapper.setBalance(player, amount); + return true; } @Override @@ -75,14 +75,14 @@ public boolean hasIntegrated() { @Override public void disableIntegration() { - econWrapper = null; + econWrapper = null; } @Override public String getDisplayName() { - return super.getDisplayName() + " (API v0.15.0)"+ - ( availableAsAnAlternative ? " (disabled)" : ""); + return super.getDisplayName() + " (API v0.15.0)"+ + ( availableAsAnAlternative ? " (disabled)" : ""); } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/SaneEconomyWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/SaneEconomyWrapper.java index 5db58dc76..95a74ed45 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/SaneEconomyWrapper.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/SaneEconomyWrapper.java @@ -26,49 +26,49 @@ public SaneEconomyWrapper(String providerName) { public boolean hasAccount( Player player ) { - EconomablePlayer p = toEconomablePlayer(player); - - return p != null && economyManager.accountExists( p ); + EconomablePlayer p = toEconomablePlayer(player); + + return p != null && economyManager.accountExists( p ); } public double getBalance(Player player) { - double result = 0; - - try { - - if ( !hasAccount( player ) ) { - player.sendMessage( "Economy Error: You don't have an account."); - } - else { - - EconomablePlayer p = toEconomablePlayer(player); - result = economyManager.getBalance( p ); - } - } + double result = 0; + + try { + + if ( !hasAccount( player ) ) { + player.sendMessage( "Economy Error: You don't have an account."); + } + else { + + EconomablePlayer p = toEconomablePlayer(player); + result = economyManager.getBalance( p ); + } + } catch ( Exception e ) { - Output.get().logError( "Failed to get SaneEconomy balance. " + - "Using API v0.15.0. You may need to downgrade. ", e ); + Output.get().logError( "Failed to get SaneEconomy balance. " + + "Using API v0.15.0. You may need to downgrade. ", e ); } return result; } public void setBalance(Player player, double amount) { - try { - - if ( !hasAccount( player ) ) { - player.sendMessage( "Economy Error: You don't have an account."); - } - else { - - EconomablePlayer p = toEconomablePlayer(player); - economyManager.setBalance( p, amount); - } - - } + try { + + if ( !hasAccount( player ) ) { + player.sendMessage( "Economy Error: You don't have an account."); + } + else { + + EconomablePlayer p = toEconomablePlayer(player); + economyManager.setBalance( p, amount); + } + + } catch ( Exception e ) { - Output.get().logError( "Failed to set SaneEconomy balance. " + - "Using API v0.15.0. You may need to downgrade. ", e ); + Output.get().logError( "Failed to set SaneEconomy balance. " + + "Using API v0.15.0. You may need to downgrade. ", e ); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/TheNewEconomy.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/TheNewEconomy.java new file mode 100644 index 000000000..24f298b3c --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/TheNewEconomy.java @@ -0,0 +1,150 @@ +package tech.mcprison.prison.spigot.economies; + +import tech.mcprison.prison.PrisonAPI; +import tech.mcprison.prison.integration.EconomyCurrencyIntegration; +import tech.mcprison.prison.integration.IntegrationType; +import tech.mcprison.prison.internal.Player; +import tech.mcprison.prison.output.Output; + +import java.math.BigDecimal; + +public class TheNewEconomy extends EconomyCurrencyIntegration { + + private TheNewEconomyWrapper wrapper = null; + private boolean availableAsAnAlternative = false; + + public TheNewEconomy() { + super("TheNewEconomy", "TheNewEconomy"); + } + + @Override + public String getPluginSourceURL() { + return "https://www.spigotmc.org/resources/the-new-economy.7805/"; + } + + @Override + public void integrate() { + if(isRegistered()) { + + // if an econ is already registered, then don't register this one: + final boolean econAlreadySet = PrisonAPI.getIntegrationManager().getForType(IntegrationType.ECONOMY).isPresent(); + + if(!econAlreadySet) { + this.wrapper = new TheNewEconomyWrapper(); + } else { + Output.get().logInfo("TheNewEconomy is not directly enabled - Available as backup. "); + this.availableAsAnAlternative = true; + } + + } + } + + @Override + public boolean hasIntegrated() { + return wrapper != null; + } + + @Override + public void disableIntegration() { + wrapper = null; + } + + @Override + public String getDisplayName() { + return super.getDisplayName() + + (availableAsAnAlternative ? " (disabled)" : ""); + } + + @Override + public boolean supportedCurrency(final String currency) { + return wrapper != null && wrapper.supportedCurrency(currency); + } + + @Override + public boolean hasAccount(final Player player) { + return wrapper.hasAccount(player); + } + + /** + * Returns the player's current balance. + * + * @param player The {@link Player}. + * + * @return a double. + */ + @Override + public double getBalance(final Player player) { + return getBalance(player, wrapper.defaultCurrency()); + } + + @Override + public double getBalance(final Player player, final String currency) { + return wrapper.getBalance(player, currency).doubleValue(); + } + + /** + * Sets the player's balance. This will overwrite the previous balance, if that was not clear. + * + * @param player The {@link Player}. + * @param amount The amount. + */ + @Override + public boolean setBalance(final Player player, final double amount) { + return setBalance(player, amount, wrapper.defaultCurrency()); + } + + @Override + public boolean setBalance(final Player player, final double amount, final String currency) { + return wrapper.setBalance(player, currency, new BigDecimal(amount)); + } + + /** + * Adds to the player's current balance. + * + * @param player The {@link Player}. + * @param amount The amount. + */ + @Override + public boolean addBalance(final Player player, final double amount) { + return addBalance(player, amount, wrapper.defaultCurrency()); + } + + @Override + public boolean addBalance(final Player player, final double amount, final String currency) { + return wrapper.addBalance(player, new BigDecimal(amount), currency); + } + + /** + * Removes from the player's current balance. + * + * @param player The {@link Player}. + * @param amount The amount. + */ + @Override + public boolean removeBalance(final Player player, final double amount) { + return removeBalance(player, amount, wrapper.defaultCurrency()); + } + + @Override + public boolean removeBalance(final Player player, final double amount, final String currency) { + return wrapper.withdraw(player, new BigDecimal(amount), currency); + } + + /** + * Returns whether the player can afford a transaction. + * + * @param player The {@link Player}. + * @param amount The amount. + * + * @return true if the player can afford it, false otherwise. + */ + @Override + public boolean canAfford(final Player player, final double amount) { + return canAfford(player, amount, wrapper.defaultCurrency()); + } + + @Override + public boolean canAfford(final Player player, final double amount, final String currency) { + return wrapper.hasBalance(player, currency, new BigDecimal(amount)); + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/TheNewEconomyWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/TheNewEconomyWrapper.java new file mode 100644 index 000000000..664adbeea --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/TheNewEconomyWrapper.java @@ -0,0 +1,68 @@ +package tech.mcprison.prison.spigot.economies; + +import net.tnemc.core.TNECore; +import net.tnemc.core.api.TNEAPI; +import tech.mcprison.prison.internal.Player; + +import java.math.BigDecimal; + +public class TheNewEconomyWrapper { + + private TNEAPI economy; + + public TheNewEconomyWrapper() { + + this.economy = new TNEAPI(); + } + + + public boolean isEnabled() { + return economy != null; + } + + public boolean supportedCurrency(final String currency) { + return TNECore.eco().currency().findCurrency(currency).isPresent(); + } + + public boolean hasAccount(final Player player) { + return economy.hasPlayerAccount(player.getUUID()); + } + + public boolean hasBalance(final Player player, final String currency, final BigDecimal amount) { + return economy.hasHoldings(player.getUUID().toString(), + player.getLocation().getWorld().getName(), + currency, amount); + } + + public boolean setBalance(final Player player, final String currency, final BigDecimal amount) { + return economy.setHoldings(player.getUUID().toString(), + player.getLocation().getWorld().getName(), + currency, amount); + } + + public BigDecimal getBalance(final Player player, final String currency) { + return economy.getHoldings(player.getUUID().toString(), + player.getLocation().getWorld().getName(), + currency); + } + + public String defaultCurrency() { + return economy.getDefaultCurrency().getIdentifier(); + } + + public boolean addBalance(final Player player, final BigDecimal amount, final String currency) { + return economy.addHoldings(player.getUUID().toString(), + player.getLocation().getWorld().getName(), + currency, + amount, + "Prison").isSuccessful(); + } + + public boolean withdraw(final Player player, final BigDecimal amount, final String currency) { + return economy.removeHoldings(player.getUUID().toString(), + player.getLocation().getWorld().getName(), + currency, + amount, + "Prison").isSuccessful(); + } +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/VaultEconomy.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/VaultEconomy.java index 42bfef372..b9509b9de 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/VaultEconomy.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/VaultEconomy.java @@ -30,7 +30,7 @@ public class VaultEconomy private VaultEconomyWrapper econWrapper; public VaultEconomy() { - super( "VaultEcon", "Vault" ); + super( "VaultEcon", "Vault" ); } @Override @@ -55,22 +55,22 @@ public void integrate() { @Override public boolean hasAccount( Player player ) { - boolean sendWarning = false; - return econWrapper.hasAccount( player, sendWarning ); + boolean sendWarning = false; + return econWrapper.hasAccount( player, sendWarning ); } @Override public double getBalance(Player player) { if (hasIntegrated()) { - return econWrapper.getBalance( player ); + return econWrapper.getBalance( player ); } else { - return 0; + return 0; } } @Override public boolean setBalance(Player player, double amount) { - boolean results = false; + boolean results = false; if (hasIntegrated()) { results = econWrapper.setBalance( player, amount ); } @@ -88,7 +88,7 @@ public boolean addBalance(Player player, double amount) { @Override public boolean removeBalance(Player player, double amount) { - boolean results = false; + boolean results = false; if (hasIntegrated()) { results = econWrapper.removeBalance( player, amount ); } @@ -103,7 +103,7 @@ public boolean canAfford(Player player, double amount) { @Override public String getDisplayName() { - return ( !hasIntegrated() ? "Vault Economy" : econWrapper.getName()) + " (Vault)"; + return ( !hasIntegrated() ? "Vault Economy" : econWrapper.getName()) + " (Vault)"; } /** @@ -118,7 +118,7 @@ public boolean hasIntegrated() { @Override public void disableIntegration() { - econWrapper = null; + econWrapper = null; } @Override diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/VaultEconomyWrapper.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/VaultEconomyWrapper.java index 540a96036..2014479de 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/VaultEconomyWrapper.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/economies/VaultEconomyWrapper.java @@ -12,7 +12,7 @@ import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.output.Output; import tech.mcprison.prison.spigot.SpigotUtil; -import tech.mcprison.prison.spigot.spiget.BluesSpigetSemVerComparator; +import tech.mcprison.prison.util.BluesSemanticVersionComparator; /** *

    Prison does not support banks since the only way to identify a bank is through @@ -52,7 +52,7 @@ public VaultEconomyWrapper(String providerName ) { Bukkit.getPluginManager().getPlugin( getProviderName() ) .getDescription().getVersion(); - this.preV1dot4 = ( new BluesSpigetSemVerComparator().compareTo( getVaultVersion(), + this.preV1dot4 = ( new BluesSemanticVersionComparator().compareTo( getVaultVersion(), "1.4.0" ) < 0 ); // Output.get().logInfo( "### VaultEconomyWrapper : vaultVersion = " + getVaultVersion() + @@ -92,7 +92,7 @@ public boolean hasAccount( Player player, boolean sendWarning ) { } - return hasAccount; + return hasAccount; } public String getProviderName() { @@ -148,49 +148,27 @@ private OfflinePlayer getOfflinePlayer(Player player) { */ @SuppressWarnings( "deprecation" ) public double getBalance(Player player) { - double results = 0; - - boolean hasAccount = hasAccount(player, true); - - if ( economy != null && !hasAccount ) { - player.sendMessage( "Economy Error: You don't have an account."); - } - else - if (economy != null) { - - if ( isPreV1_4() ) { - results = economy.getBalance(player.getName()); - } - else { - OfflinePlayer oPlayer = getOfflinePlayer( player ); - if ( oPlayer != null ) { - results = economy.getBalance(oPlayer); - } - - -// if ( oPlayer == null ) { -// Output.get().logInfo( "VaultEconomyWrapper.getBalance(): Error: " + -// "Cannot get economy for player %s so returning a value of 0. " + -// "Failed to get an bukkit offline player.", -// player.getName()); -// results = 0; -// } -// else { -// results = economy.getBalance(oPlayer); -// } - - } -// if ( economy.hasBankSupport() ) { -// -// EconomyResponse bnkBal = economy.bankBalance( player.getName() ); -// if ( bnkBal.transactionSuccess() ) { -// results = bnkBal.balance; -// } -// -// -// } else { -// results = economy.getBalance(player.getName()); -// } + double results = 0; + + boolean hasAccount = hasAccount(player, true); + + if ( economy != null && !hasAccount ) { + player.sendMessage( "Economy Error: You don't have an account."); + } + else + if (economy != null) { + + if ( isPreV1_4() ) { + results = economy.getBalance(player.getName()); + } + else { + OfflinePlayer oPlayer = getOfflinePlayer( player ); + if ( oPlayer != null ) { + results = economy.getBalance(oPlayer); + } + + + } } return results; @@ -198,189 +176,142 @@ public double getBalance(Player player) { @SuppressWarnings( "deprecation" ) public boolean setBalance(Player player, double amount) { - boolean results = false; - - boolean hasAccount = hasAccount(player, true); - - if ( economy != null && !hasAccount ) { - player.sendMessage( "Economy Error: You don't have an account."); - } - else - if (economy != null) { - - if ( isPreV1_4() ) { - economy.withdrawPlayer( player.getName(), getBalance( player ) ); - economy.depositPlayer( player.getName(), amount ); - results = true; - } - else { - OfflinePlayer oPlayer = getOfflinePlayer( player ); - if ( oPlayer != null ) { -// Output.get().logInfo( "VaultEconomyWrapper.setBalance(): Error: " + -// "Cannot get economy for player %s so cannot set balance to %s.", -// player.getName(), Double.toString( amount )); -// } -// else { - economy.withdrawPlayer( oPlayer, getBalance( player ) ); - economy.depositPlayer( oPlayer, amount ); - results = true; - } - } + boolean results = false; + + boolean hasAccount = hasAccount(player, true); + + if ( economy != null && !hasAccount ) { + player.sendMessage( "Economy Error: You don't have an account."); + } + else + if (economy != null) { + + if ( isPreV1_4() ) { + economy.withdrawPlayer( player.getName(), getBalance( player ) ); + economy.depositPlayer( player.getName(), amount ); + results = true; + } + else { + OfflinePlayer oPlayer = getOfflinePlayer( player ); + if ( oPlayer != null ) { + economy.withdrawPlayer( oPlayer, getBalance( player ) ); + economy.depositPlayer( oPlayer, amount ); + results = true; + } + } -// if ( economy.hasBankSupport() ) { -// economy.bankWithdraw(player.getName(), getBalance(player)); -// economy.bankDeposit(player.getName(), amount); -// } else { -// economy.withdrawPlayer( player.getName(), getBalance( player ) ); -// economy.depositPlayer( player.getName(), amount ); -// } } return results; } @SuppressWarnings( "deprecation" ) public boolean addBalance(Player player, double amount) { - boolean results = false; - - boolean hasAccount = hasAccount(player, true); - - if ( amount < 0 ) { - results = removeBalance( player, amount ); - } - - - else if ( economy != null && !hasAccount ) { - player.sendMessage( "Economy Error: You don't have an account."); - } - else if (economy != null) { - if ( isPreV1_4() ) { - economy.depositPlayer( player.getName(), amount ); - results = true; - } - else { - OfflinePlayer oPlayer = getOfflinePlayer( player ); - if ( oPlayer != null ) { -// Output.get().logInfo( "VaultEconomyWrapper.addBalance(): Error: " + -// "Cannot get economy for player %s so cannot add a balance of %s.", -// player.getName(), Double.toString( amount )); -// } -// else { - EconomyResponse response = economy.depositPlayer( oPlayer, amount ); - - results = response.transactionSuccess(); - - if ( !results ) { - DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); - String message = String.format( - "VaultEconomy.addBalance failed: %s amount: %s " + - "balance: %s error: %s", - oPlayer.getName(), - dFmt.format(amount), dFmt.format(response.balance), - response.errorMessage ); - Output.get().logError( message ); - } -// results = true; - } - } -// if ( economy.hasBankSupport() ) { -// economy.bankDeposit(player.getName(), amount); -// } else { -// economy.depositPlayer( player.getName(), amount ); -// } + boolean results = false; + + boolean hasAccount = hasAccount(player, true); + + if ( amount < 0 ) { + results = removeBalance( player, amount ); + } + + + else if ( economy != null && !hasAccount ) { + player.sendMessage( "Economy Error: You don't have an account."); + } + else if (economy != null) { + if ( isPreV1_4() ) { + economy.depositPlayer( player.getName(), amount ); + results = true; + } + else { + OfflinePlayer oPlayer = getOfflinePlayer( player ); + if ( oPlayer != null ) { + EconomyResponse response = economy.depositPlayer( oPlayer, amount ); + + results = response.transactionSuccess(); + + if ( !results ) { + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); + String message = String.format( + "VaultEconomy.addBalance failed: %s amount: %s " + + "balance: %s error: %s", + oPlayer.getName(), + dFmt.format(amount), dFmt.format(response.balance), + response.errorMessage ); + Output.get().logError( message ); + } + } + } } return results; } @SuppressWarnings( "deprecation" ) public boolean removeBalance(Player player, double amount) { - boolean results = false; - - // Needs to be a positive amount: - if ( amount < 0 ) { - amount *= -1; - } - - boolean hasAccount = hasAccount(player, true); - - if ( economy != null && !hasAccount ) { - player.sendMessage( "Economy Error: You don't have an account."); - } - else - if (economy != null) { - if ( isPreV1_4() ) { - economy.withdrawPlayer( player.getName(), amount ); - results = true; - } - else { - OfflinePlayer oPlayer = getOfflinePlayer( player ); - if ( oPlayer != null ) { -// Output.get().logInfo( "VaultEconomyWrapper.removeBalance(): Error: " + -// "Cannot get economy for player %s so cannot remove a balance of %s.", -// player.getName(), Double.toString( amount )); -// } -// else { - EconomyResponse response = economy.withdrawPlayer( oPlayer, amount ); - - results = response.transactionSuccess(); - - if ( !results ) { - DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); - String message = String.format( - "VaultEconomy.removeBalance failed: %s amount: %s " + - "balance: %s error: %s", - oPlayer.getName(), - dFmt.format(amount), dFmt.format(response.balance), - response.errorMessage ); - Output.get().logError( message ); - } -// results = true; - } - } - -// if (economy != null) { -// if ( economy.hasBankSupport() ) { -// economy.bankWithdraw(player.getName(), amount); -// } else { -// economy.withdrawPlayer( player.getName(), amount ); -// } -// } - } - return results; + boolean results = false; + + // Needs to be a positive amount: + if ( amount < 0 ) { + amount *= -1; + } + + boolean hasAccount = hasAccount(player, true); + + if ( economy != null && !hasAccount ) { + player.sendMessage( "Economy Error: You don't have an account."); + } + else + if (economy != null) { + if ( isPreV1_4() ) { + economy.withdrawPlayer( player.getName(), amount ); + results = true; + } + else { + OfflinePlayer oPlayer = getOfflinePlayer( player ); + if ( oPlayer != null ) { + EconomyResponse response = economy.withdrawPlayer( oPlayer, amount ); + + results = response.transactionSuccess(); + + if ( !results ) { + DecimalFormat dFmt = Prison.get().getDecimalFormat("#,##0.00"); + String message = String.format( + "VaultEconomy.removeBalance failed: %s amount: %s " + + "balance: %s error: %s", + oPlayer.getName(), + dFmt.format(amount), dFmt.format(response.balance), + response.errorMessage ); + Output.get().logError( message ); + } + } + } + + } + return results; } @SuppressWarnings( "deprecation" ) public boolean canAfford(Player player, double amount) { - boolean results = false; - - boolean hasAccount = hasAccount(player, true); - - if ( economy != null && !hasAccount ) { - player.sendMessage( "Economy Error: You don't have an account."); - } - else - if (economy != null) { - if ( isPreV1_4() ) { - results = economy.has(player.getName(), amount); - } - else { - OfflinePlayer oPlayer = getOfflinePlayer( player ); - if ( oPlayer != null ) { -// Output.get().logInfo( "VaultEconomyWrapper.canAfford(): Error: " + -// "Cannot get economy for player %s so cannot tell if " + -// "player can afford the amount of %s.", -// player.getName(), Double.toString( amount )); -// } -// else { - results = economy.has(oPlayer, amount); - } - } - -// if ( economy.hasBankSupport() ) { -// results = economy.bankHas(player.getName(), amount).transactionSuccess(); -// } else { -// results = economy.has(player.getName(), amount); -// } - } + boolean results = false; + + boolean hasAccount = hasAccount(player, true); + + if ( economy != null && !hasAccount ) { + player.sendMessage( "Economy Error: You don't have an account."); + } + else + if (economy != null) { + if ( isPreV1_4() ) { + results = economy.has(player.getName(), amount); + } + else { + OfflinePlayer oPlayer = getOfflinePlayer( player ); + if ( oPlayer != null ) { + results = economy.has(oPlayer, amount); + } + } + + } return results; } 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 9d5d4c9f4..faca09541 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 @@ -22,6 +22,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.command.ConsoleCommandSender; @@ -44,6 +45,8 @@ */ public class SpigotCommandSender implements CommandSender { + + private transient String miscText; private org.bukkit.command.CommandSender bukkitSender; @@ -51,14 +54,25 @@ public SpigotCommandSender(org.bukkit.command.CommandSender sender) { this.bukkitSender = sender; } -// @Override -// public UUID getUUID() { -// UUID uuid = null; -// if ( isPlayer() ) { -// uuid = ((org.bukkit.entity.Player) bukkitSender).getUniqueId(); -// } -// return uuid; -// } + + /** + * We have both this function, getUniqueId() and getUUID(), because different + * sources (player vs entity) have different requirements and expectations for + * field names. + * + * @return + */ + public UUID getUniqueId() { + return getUUID(); + } + + public UUID getUUID() { + UUID uuid = null; + if ( isPlayer() ) { + uuid = ((org.bukkit.entity.Player) bukkitSender).getUniqueId(); + } + return uuid; + } @Override public String getName() { @@ -75,10 +89,10 @@ public String getName() { @Override public void dispatchCommand(String command) { - command = CommandHandler.remapRootCmdIdentifiers( command ); - - String registeredCmd = Prison.get().getCommandHandler() - .findRegisteredCommand( command ); + command = CommandHandler.remapRootCmdIdentifiers( command ); + + String registeredCmd = Prison.get().getCommandHandler() + .findRegisteredCommand( command ); Bukkit.getServer().dispatchCommand(bukkitSender, registeredCmd); } @@ -90,11 +104,11 @@ public boolean doesSupportColors() { @Override public void sendMessage(String message) { - - String[] msgs = Text.translateAmpColorCodes(message).split( "\\{br\\}" ); - - for ( String msg : msgs ) { - bukkitSender.sendMessage(msg); + + String[] msgs = Text.translateAmpColorCodes(message).split( "\\{br\\}" ); + + for ( String msg : msgs ) { + bukkitSender.sendMessage(msg); } } @@ -102,24 +116,24 @@ public void sendMessage(String message) { public void sendMessage(String[] messages) { for (String message : messages) { - String[] msgs = Text.translateAmpColorCodes(message).split( "\\{br\\}" ); - for ( String msg : msgs ) { - - sendMessage(msg); - } + String[] msgs = Text.translateAmpColorCodes(message).split( "\\{br\\}" ); + for ( String msg : msgs ) { + + sendMessage(msg); + } } } @Override public void sendMessage(List messages) { - for (String message : messages) { - - String[] msgs = Text.translateAmpColorCodes(message).split( "\\{br\\}" ); - for ( String msg : msgs ) { - - sendMessage(msg); - } - } + for (String message : messages) { + + String[] msgs = Text.translateAmpColorCodes(message).split( "\\{br\\}" ); + for ( String msg : msgs ) { + + sendMessage(msg); + } + } } @Override @@ -132,7 +146,7 @@ public void sendRaw(String json) { @Override public boolean isOp() { - return bukkitSender.isOp(); + return bukkitSender.isOp(); } @Override @@ -149,10 +163,10 @@ public boolean hasPermission(String perm) { @Override public List getPermissions() { - List results = new ArrayList<>(); - - Set perms = bukkitSender.getEffectivePermissions(); - for ( PermissionAttachmentInfo perm : perms ) + List results = new ArrayList<>(); + + Set perms = bukkitSender.getEffectivePermissions(); + for ( PermissionAttachmentInfo perm : perms ) { results.add( perm.getPermission() ); } @@ -163,91 +177,109 @@ public List getPermissions() { @Override public List getPermissions( String prefix ) { - List results = new ArrayList<>(); - for ( String perm : getPermissions() ) { - if ( perm.startsWith( prefix ) ) { - results.add( perm ); - } - } - - return results; + return getPermissions( prefix, getPermissions() ); + } + + @Override + public List getPermissions( String prefix, List perms ) { + List results = new ArrayList<>(); + + for ( String perm : perms ) { + if ( perm.startsWith( prefix ) ) { + results.add( perm ); + } + } + + return results; } + @Override public double getSellAllMultiplier() { - double results = 1.0; - - if ( isPlayer() ) { - - SellAllUtil sellall = SpigotPrison.getInstance().getSellAllUtil(); - - if ( sellall != null && getWrapper() != null ) { - results = sellall.getPlayerMultiplier((org.bukkit.entity.Player) getWrapper()); - } - } - - return results; - -// Optional oPlayer = Prison.get().getPlatform().getPlayer( getName() ); -// -// if ( oPlayer.isPresent() ) { -// results = oPlayer.get().getSellAllMultiplier(); -// } -// -// return results; + double results = 1.0; + + if ( isPlayer() ) { + + SellAllUtil sellall = SpigotPrison.getInstance().getSellAllUtil(); + + if ( sellall != null && getWrapper() != null ) { + results = sellall.getPlayerMultiplier((org.bukkit.entity.Player) getWrapper()); + } + } + + return results; + } + + @Override + public double getSellAllMultiplierDebug() { + double results = 1.0; + + if ( isPlayer() ) { + + SellAllUtil sellall = SpigotPrison.getInstance().getSellAllUtil(); + + if ( sellall != null && getWrapper() != null ) { + + Player player = getPlatformPlayer(); + + results = sellall.getPlayerMultiplierDebug( player ); + } + } + + return results; } @Override public List getSellAllMultiplierListings() { - List results = new ArrayList<>(); - - if ( isPlayer() ) { - - SellAllUtil sellall = SpigotPrison.getInstance().getSellAllUtil(); - - if ( sellall != null && getWrapper() != null ) { - results.addAll( sellall.getPlayerMultiplierList((org.bukkit.entity.Player) getWrapper()) ); - } - } - - - return results; + List results = new ArrayList<>(); + + if ( isPlayer() ) { + + SellAllUtil sellall = SpigotPrison.getInstance().getSellAllUtil(); + + if ( sellall != null && getWrapper() != null ) { + results.addAll( sellall.getPlayerMultiplierList((org.bukkit.entity.Player) getWrapper()) ); + } + } + + + return results; } public List getPermissionsIntegrations( boolean detailed ) { - List results = new ArrayList<>(); - - Optional oPlayer = Prison.get().getPlatform().getPlayer( getName() ); - - if ( oPlayer.isPresent() ) { - - PermissionIntegration perms = PrisonAPI.getIntegrationManager() .getPermission(); - if ( perms != null ) { - results = perms.getPermissions( oPlayer.get(), detailed ); - } - } - - return results; + List results = new ArrayList<>(); + + Optional oPlayer = Prison.get().getPlatform().getPlayer( getName() ); + + if ( oPlayer.isPresent() ) { + + PermissionIntegration perms = PrisonAPI.getIntegrationManager() .getPermission(); + if ( perms != null ) { + results = perms.getPermissions( oPlayer.get(), detailed ); + } + } + + return results; } @Override public boolean isPlayer() { - return bukkitSender != null && bukkitSender instanceof org.bukkit.entity.Player; + return bukkitSender != null && bukkitSender instanceof org.bukkit.entity.Player; } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - - sb.append( "SpigotCommandSender: " ).append( getName() ) - .append( " isOp=" ).append( isOp() ) - .append( " isPlayer=" ).append( isPlayer() ); - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + sb.append( "SpigotCommandSender: " ).append( getName() ) + .append( " isOp=" ).append( isOp() ) + .append( " isPlayer=" ).append( isPlayer() ); + + return sb.toString(); } public org.bukkit.command.CommandSender getWrapper() { @@ -273,9 +305,36 @@ public RankPlayer getRankPlayer() { if ( PrisonRanks.getInstance().isEnabled() ) { - rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer( (Player) this ); + if ( isPlayer() ) { + + rankPlayer = PrisonRanks.getInstance().getPlayerManager() + .getPlayer( (Player) this ); + } + else { + rankPlayer = PrisonRanks.getInstance().getPlayerManager() + .getPlayer( null, this.getName() ); + + } + } return rankPlayer; } + + + /** + * This miscText is not used for any specific purpose other than to hold a String + * value. It can be used to return a message from a function, but it should always + * be cleared when done using it. + * + * @return + */ + @Override + public String getMiscText() { + return miscText; + } + @Override + public void setMiscText( String text ) { + miscText = text; + } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotLocation.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotLocation.java index 3768d291b..dce7ea10e 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotLocation.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotLocation.java @@ -1,5 +1,8 @@ package tech.mcprison.prison.spigot.game; +import org.bukkit.Bukkit; + +import tech.mcprison.prison.internal.World; import tech.mcprison.prison.spigot.SpigotUtil; import tech.mcprison.prison.util.Location; @@ -8,6 +11,14 @@ public class SpigotLocation private org.bukkit.Location bukkitLocation; + public SpigotLocation( Location location ) { + super( location ); + } + + public SpigotLocation( World world, double x, double y, double z, float yaw, float pitch ) { + super( new Location( world, x, y, z, yaw, pitch) ); + } + public SpigotLocation( org.bukkit.Location bukkitLocation ) { super( SpigotUtil.bukkitLocationToPrison( bukkitLocation ) ); @@ -15,9 +26,30 @@ public SpigotLocation( org.bukkit.Location bukkitLocation ) { } public org.bukkit.Location getBukkitLocation() { + + if ( bukkitLocation == null ) { + bukkitLocation = getBukkitLocation( this ); + } + return bukkitLocation; } - public void setBukkitLocation(org.bukkit.Location bukkitLocation) { - this.bukkitLocation = bukkitLocation; + + public static org.bukkit.Location getBukkitLocation( Location location ) { + + org.bukkit.World world = Bukkit.getWorld( location.getWorld().getName() ); + + org.bukkit.Location bLocation = new org.bukkit.Location(world, + location.getX(), location.getY(), location.getZ() ); + + bLocation.setYaw( location.getYaw() ); + + bLocation.setPitch( location.getPitch() ); + + return bLocation; + } + + + public org.bukkit.World getBukkitWorld() { + return getBukkitLocation().getWorld(); } } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java index 77bbd4638..b5fbb9121 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotOfflinePlayer.java @@ -1,11 +1,13 @@ package tech.mcprison.prison.spigot.game; +import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.UUID; +import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.permissions.PermissionAttachmentInfo; @@ -33,10 +35,31 @@ public class SpigotOfflinePlayer private OfflinePlayer offlinePlayer; + + private transient File filePlayer; + private transient File fileCache; + + private transient String miscText; + public SpigotOfflinePlayer(OfflinePlayer offlinePlayer) { this.offlinePlayer = offlinePlayer; } + public static SpigotOfflinePlayer getOfflinePlayer( RankPlayer rankPlayer ) { + SpigotOfflinePlayer result = null; + + // Get an offline player: + OfflinePlayer olPlayer = Bukkit.getOfflinePlayer( rankPlayer.getUUID() ); + + if ( olPlayer != null ) { + result = new SpigotOfflinePlayer( olPlayer ); + + result.setRankPlayer( rankPlayer ); + } + + return result; + } + @Override public String getName() { return offlinePlayer.getName(); @@ -59,12 +82,51 @@ public String getName() { */ public String getPlayerFileName() { - return JsonFileIO.getPlayerFileName( this ); + return filenamePlayer(); } + + + public File getFilePlayer() { + if ( filePlayer == null ) { + filePlayer = JsonFileIO.filePlayer( this );; + } + return filePlayer; + } + public void setFilePlayer(File filePlayer) { + this.filePlayer = filePlayer; + } + + public File getFileCache() { + if ( fileCache == null ) { + fileCache = JsonFileIO.fileCache( this ); + } + return fileCache; + } + public void setFileCache(File fileCache) { + this.fileCache = fileCache; + } + + /** + *

    This is a helper function to ensure that the given file name is + * always generated correctly and consistently. + *

    + * + * @return "player_" plus the least significant bits of the UID + */ + public String filenamePlayer() + { + return getFilePlayer().getName(); + } + + public String filenameCache() + { + return getFileCache().getName(); + } + @Override public String toString() { - return getName(); + return getName(); } @@ -86,7 +148,12 @@ public String getDisplayName() { @Override public boolean isOnline() { return offlinePlayer.isOnline(); -// return false; + } + + + @Override + public long getLastSeenDate() { + return offlinePlayer.getLastPlayed(); } /** @@ -97,17 +164,10 @@ public boolean isOnline() { */ @Override public boolean isPlayer() { - return ( offlinePlayer != null && offlinePlayer.getPlayer() != null && - offlinePlayer.getPlayer() instanceof Player ); -// return false; + return ( offlinePlayer != null && offlinePlayer.getPlayer() != null && + offlinePlayer.getPlayer() instanceof Player ); } -// @Override -// public boolean hasPermission( String perm ) { -// Output.get().logError( "SpigotOfflinePlayer.hasPermission: Cannot access permissions for offline players." ); -// return false; -// } - @Override public void setDisplayName( String newDisplayName ) { Output.get().logError( "SpigotOfflinePlayer.setDisplayName: Cannot set display names." ); @@ -145,8 +205,9 @@ public Location getLocation() { } @Override - public void teleport( Location location ) { + public boolean teleport( Location location ) { Output.get().logError( "SpigotOfflinePlayer.teleport: Offline players cannot be teleported." ); + return false; } @Override @@ -179,7 +240,7 @@ public tech.mcprison.prison.internal.block.Block getLineOfSightBlock() { public List getLineOfSightBlocks() { List results = new ArrayList<>(); - return results; + return results; } @@ -197,10 +258,6 @@ public Inventory getInventory() { return null; } -// @Override -// public void printDebugInventoryInformationToConsole() { -// -// } public OfflinePlayer getWrapper() { return offlinePlayer; @@ -219,37 +276,43 @@ public void recalculatePermissions() { @Override public List getPermissions() { - List results = new ArrayList<>(); - - if ( offlinePlayer.getPlayer() != null ) { - - Set perms = offlinePlayer.getPlayer().getEffectivePermissions(); - for ( PermissionAttachmentInfo perm : perms ) - { - results.add( perm.getPermission() ); - } - } - else { - // try to use vault: - - // TODO add permission integrations here!! - } - - - return results; + List results = new ArrayList<>(); + + if ( offlinePlayer.getPlayer() != null ) { + + Set perms = offlinePlayer.getPlayer().getEffectivePermissions(); + for ( PermissionAttachmentInfo perm : perms ) + { + results.add( perm.getPermission() ); + } + } + else { + // try to use vault: + + // TODO add permission integrations here!! + } + + + return results; } @Override public List getPermissions( String prefix ) { - List results = new ArrayList<>(); - - for ( String perm : getPermissions() ) { - if ( perm.startsWith( prefix ) ) { - results.add( perm ); - } - } - return results; + return getPermissions( prefix, getPermissions() ); + } + + @Override + public List getPermissions( String prefix, List perms ) { + List results = new ArrayList<>(); + + for ( String perm : perms ) { + if ( perm.startsWith( prefix ) ) { + results.add( perm ); + } + } + + return results; } @Override @@ -266,30 +329,8 @@ public boolean hasPermission( String perm ) { } return hasPerm; - -// List perms = getPermissions( perm ); -// return perms.contains( perm ); } -// @Override -// public List getPermissions() { -// List results = new ArrayList<>(); -// -// return results; -// } -// -// @Override -// public List getPermissions( String prefix ) { -// List results = new ArrayList<>(); -// -// for ( String perm : getPermissions() ) { -// if ( perm.startsWith( prefix ) ) { -// results.add( perm ); -// } -// } -// -// return results; -// } @Override public List getPermissionsIntegrations( boolean detailed ) { @@ -310,36 +351,50 @@ public List getPermissionsIntegrations( boolean detailed ) { */ @Override public double getSellAllMultiplier() { - double results = 1.0; + double results = 1.0; - SpigotPlayer sPlayer = null; - - if ( getWrapper().getPlayer() != null ) { - sPlayer = new SpigotPlayer( getWrapper().getPlayer() ); - - results = sPlayer.getSellAllMultiplier(); - } - - return results; + SellAllUtil sellall = SpigotPrison.getInstance().getSellAllUtil(); + + if ( sellall != null && getWrapper() != null ) { + + results = sellall.getPlayerMultiplier( this ); + } + + return results; } - - public List getSellAllMultiplierListings() { - List results = new ArrayList<>(); + @Override + public double getSellAllMultiplierDebug() { + double results = 1.0; - if ( isPlayer() ) { + // NOTE: isPlayer() is a check to see if it's tied to the bukkit Player object, of + // which offline player is not. But the sellall multiplier can still be called. SellAllUtil sellall = SpigotPrison.getInstance().getSellAllUtil(); if ( sellall != null && getWrapper() != null ) { - results.addAll( sellall.getPlayerMultiplierList((org.bukkit.entity.Player) getWrapper()) ); + + results = sellall.getPlayerMultiplierDebug( this ); } - } - return results; } + public List getSellAllMultiplierListings() { + List results = new ArrayList<>(); + + if ( isPlayer() ) { + + SellAllUtil sellall = SpigotPrison.getInstance().getSellAllUtil(); + + if ( sellall != null && getWrapper() != null ) { + results.addAll( sellall.getPlayerMultiplierList((org.bukkit.entity.Player) getWrapper()) ); + } + } + + return results; + } + @Override public void setTitle( String title, String subtitle, int fadeIn, int stay, int fadeOut ) { } @@ -349,11 +404,18 @@ public void setActionBar( String actionBar ) { } public RankPlayer getRankPlayer() { - if ( rankPlayer == null ) { + + if ( rankPlayer == null && PrisonRanks.getInstance() != null && + PrisonRanks.getInstance().isEnabled() ) { + rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer( this ); } return rankPlayer; } + private void setRankPlayer( RankPlayer rankPlayer ) { + this.rankPlayer = rankPlayer; + } + @Override public PlayerCache getPlayerCache() { @@ -391,21 +453,31 @@ public void incrementMinecraftStatsDropCount( tech.mcprison.prison.internal.Play @Override public void sendMessage(List messages) { - // TODO Auto-generated method stub } @Override public tech.mcprison.prison.internal.Player getPlatformPlayer() { - tech.mcprison.prison.internal.Player player = null; - Optional oPlayer = Prison.get().getPlatform().getPlayer( getName() ); + SpigotPlayer sPlayer = SpigotPlayer.getSpigotPlayer( getRankPlayer() ); - if ( oPlayer.isPresent() ) { - player = oPlayer.get(); - } - - return player; + return sPlayer; } + + /** + * This miscText is not used for any specific purpose other than to hold a String + * value. It can be used to return a message from a function, but it should always + * be cleared when done using it. + * + * @return + */ + @Override + public String getMiscText() { + return miscText; + } + @Override + public void setMiscText( String text ) { + miscText = text; + } } 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 7b2e70f85..b2e5ecab5 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 @@ -18,17 +18,17 @@ package tech.mcprison.prison.spigot.game; +import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.UUID; +import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.Statistic; import org.bukkit.block.Block; import org.bukkit.entity.ExperienceOrb; -import org.bukkit.event.player.PlayerTeleportEvent; import com.cryptomorin.xseries.XMaterial; @@ -53,29 +53,91 @@ 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.game.entity.SpigotEntity; 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; +import tech.mcprison.prison.util.Vector; /** - * @author Faizaan A. Datoo + *

    This is a wrapper class that stores the bukkit player object and enables it + * to be used with the internal Prison SpigotPlayer object. It also can store the + * RankPlayer object too. + *

    + * + *

    To generate a SpigotPlayer from a RankPlayer there is a new + * static function that will perform the construction of the SpigotPlayer. + *

    + * + *

    This SpigotPlayer object is ONLY for players that are online. This class + * cannot exist for offline players, of which use the SpigotOfflinePlayer object. + *

    + * */ public class SpigotPlayer - extends SpigotCommandSender + extends SpigotEntity +// extends SpigotCommandSender implements Player, Comparable { private RankPlayer rankPlayer; private org.bukkit.entity.Player bukkitPlayer; + + + private transient File filePlayer; + private transient File fileCache; + + private transient String miscText; public SpigotPlayer(org.bukkit.entity.Player bukkitPlayer) { super(bukkitPlayer); + this.bukkitPlayer = bukkitPlayer; } - + + + /** + *

    This function sets up a SpigotPlayer object using a RankPlayer object. + * It basically joins the bukkit player to the existing RankPlayer. + *

    + * + * + *

    This will throw a SpigotPlayerException if the RankPlayer's UUID cannot be + * tied to a bukkit player. This should never happen since UUIDs come from bukkit + * with the exception of the player being removed from bukkit, but not yet from + * prison. + *

    + * + * @param rankPlayer + * @throws SpigotPlayerException + */ + public static SpigotPlayer getSpigotPlayer( RankPlayer rankPlayer ) { + + SpigotPlayer result = null; + + // We have a RankPlayer object, but we need to connect this SpigotPlayer object + // to the bukkit player object. + + // NOTE: We're directly accessing bukkit here because it's more direct instead of + // trying to do that through a few different function within the + // SpigotPlatform. + + // First try to load a bukkit online player: + org.bukkit.entity.Player bPlayer = Bukkit.getPlayer( rankPlayer.getUUID() ); + + if ( bPlayer != null ) { + result = new SpigotPlayer( bPlayer ); + + result.setRankPlayer( rankPlayer ); + } + + return result; + } + + /** *

    This constructs a player file named based upon the UUID followed * by the player's name. This format is used so it's easier to identify @@ -93,112 +155,164 @@ public SpigotPlayer(org.bukkit.entity.Player bukkitPlayer) { */ public String getPlayerFileName() { - return JsonFileIO.getPlayerFileName( this ); + return filenamePlayer(); } - @Override - public UUID getUUID() { - return bukkitPlayer.getUniqueId(); + + public File getFilePlayer() { + if ( filePlayer == null ) { + filePlayer = JsonFileIO.filePlayer( this );; + } + return filePlayer; + } + public void setFilePlayer(File filePlayer) { + this.filePlayer = filePlayer; + } + + public File getFileCache() { + if ( fileCache == null ) { + fileCache = JsonFileIO.fileCache( this ); + } + return fileCache; + } + public void setFileCache(File fileCache) { + this.fileCache = fileCache; + } + + /** + *

    This is a helper function to ensure that the given file name is + * always generated correctly and consistently. + *

    + * + * @return "player_" plus the least significant bits of the UID + */ + public String filenamePlayer() + { + return getFilePlayer().getName(); + } + + public String filenameCache() + { + return getFileCache().getName(); } - @Override public String getDisplayName() { + @Override + public String getDisplayName() { return bukkitPlayer.getDisplayName(); } - @Override public void setDisplayName(String newDisplayName) { + @Override + public String getName() { + + return bukkitPlayer != null ? + bukkitPlayer.getName() : + rankPlayer != null ? + rankPlayer.getName() : ""; + } + + + @Override + public void setDisplayName(String newDisplayName) { bukkitPlayer.setDisplayName(newDisplayName); } - @Override public void give(ItemStack itemStack) { + @Override + public void give(ItemStack itemStack) { bukkitPlayer.getInventory().addItem(SpigotUtil.prisonItemStackToBukkit(itemStack)); } - @Override public Location getLocation() { - return SpigotUtil.bukkitLocationToPrison(bukkitPlayer.getLocation()); - } - - @Override public void teleport(Location location) { - bukkitPlayer.teleport(SpigotUtil.prisonLocationToBukkit(location), - PlayerTeleportEvent.TeleportCause.PLUGIN); - } - @Override public boolean isOnline() { - return bukkitPlayer.isOnline(); + @Override + public boolean isOnline() { + return bukkitPlayer == null ? false : bukkitPlayer.isOnline(); } - @Override public void setScoreboard(Scoreboard scoreboard) { + @Override + public void setScoreboard(Scoreboard scoreboard) { bukkitPlayer.setScoreboard(((SpigotScoreboard) scoreboard).getWrapper()); } - @Override public Gamemode getGamemode() { + @Override + public Gamemode getGamemode() { return Gamemode.valueOf(getWrapper().getGameMode().toString()); } - @Override public void setGamemode(Gamemode gamemode) { + @Override + public void setGamemode(Gamemode gamemode) { getWrapper().setGameMode(GameMode.valueOf(gamemode.toString())); } @Override public Optional getLocale() { - Optional results = Optional.empty(); + Optional results = Optional.empty(); -// if ( SpigotNMSPlayer.getInstance().hasSupport() ) { -// try { -// results = Optional.ofNullable( -// SpigotNMSPlayer.getInstance().getLocale( getWrapper() ) -// ); -// } -// catch ( Exception ex ) { -// Output.get().logInfo( -// "Failed to initialize NMS components -- " + -// "NMS is not functional - " + ex.getMessage() ); -// } -// } return results; } @Override public SpigotBlock getLineOfSightBlock() { - SpigotBlock results = null; - -// org.bukkit.Location eyeLocation = getWrapper().getEyeLocation(); -// org.bukkit.util.Vector lineOfSight = eyeLocation.getDirection().normalize(); -// -// double maxDistance = 256; -// -// for(double i = 0; i < maxDistance; ++i){ -// Block block = eyeLocation.add( lineOfSight.clone().multiply(i) ).getBlock(); -// if( block.getType() != Material.AIR ) { -//// if( block.getType().isSolid() ) { -// -// results = new SpigotBlock( block ); -// break; -// } -// -// } -// -// return results; -// - - - -// List results = new ArrayList<>(); - - List blocks = bukkitPlayer.getLineOfSight( null, 256 ); - for ( Block block : blocks ) { - if ( block != null && block.getType() != Material.AIR ) { - - // return the first non-null and non-AIR block, which will - // be the one the player is looking at: - results = SpigotBlock.getSpigotBlock( block ); - } + SpigotBlock results = null; + + List blocks = bukkitPlayer.getLineOfSight( null, 256 ); + for ( Block block : blocks ) { + if ( block != null && block.getType() != Material.AIR && + !SpigotCompatibility.getInstance().isPassable(block) ) { + + + // return the first non-null and non-AIR block, which will + // be the one the player is looking at: + results = SpigotBlock.getSpigotBlock( block ); + } } - - return results; + + return results; } + /** + *

    This uses the line of sight to get an exact location of where the player + * is clicking. Normally, when selecting a block, only the block's location + * is accessible which is basically integer resolution, although the player maybe + * clicking somewhere in the middle of a block. This gives a way to finely + * select where they were looking, instead of just the block they were + * looking at and clicking on. + *

    + * + *

    Please notice that there may be issues with this code. Review the + * other function in this class 'getLineOfSightBlock()' in that it uses + * bukkit's block.isPassible(). That function does not exist in the + * prison block and may need to be added. Currently it's not possible to + * be added at this time since too many other changes are in effect within + * prison. This is a note and a placeholder for these possible changes. + *

    + * + * @return + */ + public Location getLineOfSightExactLocation() { + + SpigotLocation eyeLoc = new SpigotLocation( getWrapper().getEyeLocation() ); + Vector eyeVec = eyeLoc.getDirection(); + + Location loc = eyeLoc.add(eyeVec); + + int i = 0; + + // Is isPassible also true when isEmpty? If so, then this could be simplified... + // while ( i++ <= 75 && (loc.getBlockAt().isEmpty() || loc.getBlockAt().isPassible()) ) { + + while ( i++ <= 75 && loc.getBlockAt().isEmpty() ) { + + loc = loc.add(eyeVec); + } + + if ( loc.getBlockAt().isEmpty() ) { + loc = null; + } + + return loc; + } + /** *

    This will return a list of blocks that are in the line of sight of the player. * It will initially ignore all air blocks until it hits a non-air block, then it will @@ -209,21 +323,21 @@ public SpigotBlock getLineOfSightBlock() { @Override public List getLineOfSightBlocks() { - List results = new ArrayList<>(); - - List blocks = bukkitPlayer.getLineOfSight( null, 256 ); - for ( Block block : blocks ) { - if ( block != null && - (results.size() == 0 && block.getType() != Material.AIR || - results.size() > 0 && results.size() < 20 )) { - - // return the first non-null and non-AIR block, which will - // be the one the player is looking at: - results.add( SpigotBlock.getSpigotBlock( block ) ); - } + List results = new ArrayList<>(); + + List blocks = bukkitPlayer.getLineOfSight( null, 256 ); + for ( Block block : blocks ) { + if ( block != null && + (results.size() == 0 && block.getType() != Material.AIR || + results.size() > 0 && results.size() < 20 )) { + + // return the first non-null and non-AIR block, which will + // be the one the player is looking at: + results.add( SpigotBlock.getSpigotBlock( block ) ); + } } - return results; + return results; } @@ -235,290 +349,56 @@ public org.bukkit.entity.Player getWrapper() { public Inventory getInventory() { return getSpigotPlayerInventory(); } + public SpigotPlayerInventory getSpigotPlayerInventory() { - return new SpigotPlayerInventory(getWrapper().getInventory()); + return new SpigotPlayerInventory(getWrapper().getInventory()); } - @Override public void updateInventory() { + @Override + public void updateInventory() { bukkitPlayer.updateInventory(); } -// @Override -// public void recalculatePermissions() { -// bukkitPlayer.recalculatePermissions(); -// } + @Override + public void recalculatePermissions() { + bukkitPlayer.recalculatePermissions(); + } + @Override + public boolean isPlayer() { + return true; + } + -// @Override -// public boolean isOp() { -// return bukkitPlayer.isOp(); -// } - -// @Override -// public boolean hasPermission( String perm ) { -// List perms = getPermissions( perm ); -// return perms.contains( perm ); -// } + @Override + public long getLastSeenDate() { + return bukkitPlayer.getLastPlayed(); + } -// @Override -// public List getPermissions() { -// List results = new ArrayList<>(); -// -// Set perms = bukkitPlayer.getEffectivePermissions(); -// for ( PermissionAttachmentInfo perm : perms ) -// { -// results.add( perm.getPermission() ); -// } -// -// return results; -// } - - -// @Override -// public List getPermissions( String prefix ) { -// List results = new ArrayList<>(); -// -// for ( String perm : getPermissions() ) { -// if ( perm.startsWith( prefix ) ) { -// results.add( perm ); -// } -// } -// -// return results; -// } - - -// /** -// *

    This uses the sellall configs for the permission name to use to get the list of -// * multipliers. It then adds all of the multipliers together to ... -// * -// *

    -// * -// */ -// @Override -// public double getSellAllMultiplier() { -// double results = 1.0; -// -// SellAllPrisonCommands sellall = SellAllPrisonCommands.get(); -// -// if ( sellall != null ) { -// results = sellall.getMultiplier( this ); -// } -// -// return results; -// } - @Override public int compareTo( SpigotPlayer sPlayer) { - return getName().compareTo( sPlayer.getName() ); + return getUUID().compareTo( sPlayer.getUUID() ); } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - - sb.append( "SpigotPlayer: " ).append( getName() ) - .append( " isOp=" ).append( isOp() ) - .append( " isOnline=" ).append( isOnline() ) - .append( " isPlayer=" ).append( isPlayer() ); - - return sb.toString(); + StringBuilder sb = new StringBuilder(); + + sb.append( "SpigotPlayer: " ).append( getName() ) + .append( " isOp=" ).append( isOp() ) + .append( " isOnline=" ).append( isOnline() ) + .append( " isPlayer=" ).append( isPlayer() ) + + .append( " hasBukkitPlayer=" ).append( bukkitPlayer != null ) + .append( " hasRankPlayer=" ).append( rankPlayer != null ) + ; + + return sb.toString(); } - - -// /** -// * This class is an adaptation of the NmsHelper class in the Rosetta library by Max Roncace. The -// * library is licensed under the New BSD License. See the {@link tech.mcprison.prison.localization} -// * package for the full license. -// * -// * @author Max Roncacé -// */ -// private static class NmsHelper { -// -// private static final boolean SUPPORT; -// -// private static final String PACKAGE_VERSION; -// -// private static final Method PLAYER_SPIGOT; -// private static final Method PLAYER$SPIGOT_GETLOCALE; -// private static final Method CRAFTPLAYER_GETHANDLE; -// -// private static final Field ENTITY_PLAYER_LOCALE; -// private static final Field LOCALE_LANGUAGE_WRAPPED_STRING; -// -// static { -// String[] array = Bukkit.getServer().getClass().getPackage().getName().split("\\."); -// PACKAGE_VERSION = array.length == 4 ? array[3] + "." : ""; -// -// Method player_spigot = null; -// Method player$spigot_getLocale = null; -// Method craftPlayer_getHandle = null; -// Field entityPlayer_locale = null; -// Field localeLanguage_wrappedString = null; -// try { -// -// Class craftPlayer = getCraftClass("entity.CraftPlayer"); -// -// // for reasons not known to me Paper decided to make EntityPlayer#locale null by default and have the -// // fallback defined in CraftPlayer$Spigot#getLocale. Rosetta will use that method if possible and fall -// // back to accessing the field directly. -// try { -// player_spigot = org.bukkit.entity.Player.class.getMethod("spigot"); -// Class player$spigot = Class.forName("org.bukkit.entity.Player$Spigot"); -// player$spigot_getLocale = player$spigot.getMethod("getLocale"); -// } catch (NoSuchMethodException ignored) { // we're non-Spigot or old -// } -// -// if (player$spigot_getLocale == null) { // fallback for non-Spigot software -// craftPlayer_getHandle = craftPlayer.getMethod("getHandle"); -// -// entityPlayer_locale = getNmsClass("EntityPlayer").getDeclaredField("locale"); -// entityPlayer_locale.setAccessible(true); -// if (entityPlayer_locale.getType().getSimpleName().equals("LocaleLanguage")) { -// // On versions prior to 1.6, the locale is stored as a LocaleLanguage object. -// // The actual locale string is wrapped within it. -// // On 1.5, it's stored in field "e". -// // On 1.3 and 1.4, it's stored in field "d". -// try { // try for 1.5 -// localeLanguage_wrappedString = -// entityPlayer_locale.getType().getDeclaredField("e"); -// } catch (NoSuchFieldException ex) { // we're pre-1.5 -// localeLanguage_wrappedString = -// entityPlayer_locale.getType().getDeclaredField("d"); -// } -// } -// } -// } -// catch ( ClassNotFoundException ex ) { -// Output.get().logInfo( -// "Cannot initialize NMS components - ClassNotFoundException - " + -// "NMS is not functional - " + ex.getMessage() ); -// -// } -// catch (NoSuchFieldException | NoSuchMethodException ex) { -// Output.get().logInfo( -// "Cannot initialize NMS components - per-player localization disabled. - " + ex.getMessage()); -// } -// PLAYER_SPIGOT = player_spigot; -// PLAYER$SPIGOT_GETLOCALE = player$spigot_getLocale; -// CRAFTPLAYER_GETHANDLE = craftPlayer_getHandle; -// ENTITY_PLAYER_LOCALE = entityPlayer_locale; -// LOCALE_LANGUAGE_WRAPPED_STRING = localeLanguage_wrappedString; -// SUPPORT = CRAFTPLAYER_GETHANDLE != null; -// } -// -// private static boolean hasSupport() { -// return SUPPORT; -// } -// -// private static String getLocale(org.bukkit.entity.Player player) -// throws IllegalAccessException, InvocationTargetException, ClassNotFoundException { -// if (PLAYER$SPIGOT_GETLOCALE != null) { -// return (String) PLAYER$SPIGOT_GETLOCALE.invoke(PLAYER_SPIGOT.invoke(player)); -// } -// -// Object entityPlayer = CRAFTPLAYER_GETHANDLE.invoke(player); -// Object locale = ENTITY_PLAYER_LOCALE.get(entityPlayer); -// if (LOCALE_LANGUAGE_WRAPPED_STRING != null) { -// return (String) LOCALE_LANGUAGE_WRAPPED_STRING.get(locale); -// } else { -// return (String) locale; -// } -// } -// -// private static Class getCraftClass(String className) throws ClassNotFoundException { -// return Class.forName("org.bukkit.craftbukkit." + PACKAGE_VERSION + className); -// } -// -// private static Class getNmsClass(String className) throws ClassNotFoundException { -// return Class.forName("net.minecraft.server." + PACKAGE_VERSION + className); -// } -// -// } - -// @SuppressWarnings( "deprecation" ) -// public void printDebugInventoryInformationToConsole() { -// -// try { -// printDebugInfo( bukkitPlayer.getInventory().getContents(), "Inventory Contents"); -// } -// catch ( java.lang.NoSuchMethodError | Exception e ) { -// // Ignore: Not supported with that version of spigot: -// } -// -// try { -// printDebugInfo( bukkitPlayer.getInventory().getExtraContents(), "Inventory Extra Contents"); -// } -// catch ( java.lang.NoSuchMethodError | Exception e ) { -// // Ignore: Not supported with that version of spigot: -// } -// -// try { -// printDebugInfo( bukkitPlayer.getInventory().getArmorContents(), "Inventory Armor Contents"); -// } -// catch ( java.lang.NoSuchMethodError | Exception e ) { -// // Ignore: Not supported with that version of spigot: -// } -// try { -// printDebugInfo( bukkitPlayer.getInventory().getStorageContents(), "Inventory Storage Contents"); -// } -// catch ( java.lang.NoSuchMethodError | Exception e ) { -// // Ignore: Not supported with that version of spigot: -// } -// -// try { -// printDebugInfo( bukkitPlayer.getInventory().getItemInHand(), "Inventory Item In Hand (pre 1.13)"); -// } -// catch ( java.lang.NoSuchMethodError | Exception e ) { -// // Ignore: Not supported with that version of spigot: -// } -// -// try { -// printDebugInfo( bukkitPlayer.getInventory().getItemInMainHand(), "Inventory Item in Main Hand"); -// } -// catch ( java.lang.NoSuchMethodError | Exception e ) { -// // Ignore: Not supported with that version of spigot: -// } -// -// try { -// printDebugInfo( bukkitPlayer.getInventory().getItemInOffHand(), "Inventory Item in Off Hand"); -// } -// catch ( java.lang.NoSuchMethodError | Exception e ) { -// // Ignore: Not supported with that version of spigot: -// } -// } -// private void printDebugInfo( org.bukkit.inventory.ItemStack[] iStacks, String title ) { -// -// Output.get().logInfo( "&7%s:", title ); -// for ( int i = 0; i < iStacks.length; i++ ) { -// org.bukkit.inventory.ItemStack iStack = iStacks[i]; -// -// if ( iStack != null ) { -// -// ItemStack pItemStack = SpigotUtil.bukkitItemStackToPrison(iStack); -// -// Output.get().logInfo( " i=%d &3%s &3%d &a[&3%s&a]", -// i, iStack.getType().name(), iStack.getAmount(), -// (pItemStack == null ? "" : -// (pItemStack.getDisplayName() == null ? "" : -// pItemStack.getDisplayName())) ); -// } -// } -// } - -// private void printDebugInfo( org.bukkit.inventory.ItemStack iStack, String title ) { -// -// Output.get().logInfo( "&7%s:", title ); -// if ( iStack != null ) { -// -// Output.get().logInfo( " &3%s &3%d", -// iStack.getType().name(), iStack.getAmount() ); -// } -// } - + public void giveExp( int xp ) { if ( getWrapper() != null ) { @@ -663,14 +543,12 @@ public void setActionBar( String actionBar ) { if ( getWrapper() != null) { PlayerMessagingTask.submitTask( getWrapper(), MessageType.actionBar, actionBar ); -// SpigotCompatibility.getInstance() -// .sendActionBar( getWrapper(), actionBar ); } } @Override public RankPlayer getRankPlayer() { - if ( rankPlayer == null && + if ( rankPlayer == null && PrisonRanks.getInstance() != null && PrisonRanks.getInstance().isEnabled() ) { rankPlayer = PrisonRanks.getInstance().getPlayerManager().getPlayer( this ); @@ -678,6 +556,11 @@ public RankPlayer getRankPlayer() { return rankPlayer; } + private void setRankPlayer( RankPlayer rankPlayer ) { + this.rankPlayer = rankPlayer; + } + + @Override public PlayerCache getPlayerCache() { return PlayerCache.getInstance(); @@ -718,7 +601,6 @@ public boolean addBalance( String currency, double amount ) { if ( currencyEcon != null ) { results = currencyEcon.addBalance( this, amount, currency ); -// addCachedRankPlayerBalance( currency, amount ); } } return results; @@ -745,20 +627,6 @@ public boolean enableFlying( Mine mine, float flightSpeed ) { return enabled; } -// public Mine getEffectsMine() { -// Mine effectsMine = null; -// -// if ( lastEffectsMine != null ) { -// -// if ( !lastEffectsMine.isInMineExact( getLocation() ) ) { -// lastEffectsMine = null; -// -// // cancel all effects for player -// } -// effectsMine = lastEffectsMine; -// } -// return effectsMine; -// } public boolean isFlying() { boolean flying = false; @@ -792,13 +660,7 @@ public boolean isMinecraftStatisticsEnabled() { @Override public void incrementMinecraftStatsMineBlock( Player player, String blockName, int quantity) { -// Statistic.BREAK_ITEM; -// Statistic.DROP_COUNT; -// Statistic.MINE_BLOCK; -// Statistic.PICKUP; - XMaterial xMat = XMaterial.matchXMaterial( blockName ).orElse( null ); -// XMaterial xMat = SpigotCompatibility.getInstance().getXMaterial( block ); if ( xMat != null ) { Material mat = xMat.parseMaterial(); @@ -810,12 +672,6 @@ public void incrementMinecraftStatsMineBlock( Player player, String blockName, i } } -// Statistic.MINE_BLOCK; -// player.setStatistic(null, count); -// player.incrementStatistic(null, null); -// player.incrementStatistic(null, null, count); -// player.statistic - } @Override @@ -874,28 +730,24 @@ public boolean isInventoryFull() { * * @return */ -// public boolean isAutoSellEnabled() { -// return isAutoSellEnabled( null ); -// } public boolean isAutoSellEnabled( StringBuilder debugInfo ) { boolean results = false; if ( SpigotPrison.getInstance().isSellAllEnabled() && - SellAllUtil.get().isAutoSellEnabled ) { + SellAllUtil.isAutoSellEnabled() ) { if ( SellAllUtil.get().isAutoSellPerUserToggleable ) { - debugInfo.append( "(sellallEnabled:userToggleable)" ); - -// boolean isAutoSellPerUserToggleable = SellAllUtil.get().isAutoSellPerUserToggleable; + debugInfo.append( "(&7sellallEnabled:userToggleable&3)" ); boolean isPlayerAutoSellTurnedOn = SellAllUtil.get().isSellallPlayerUserToggleEnabled( getWrapper() ); if ( debugInfo != null ) { - debugInfo.append( "(autosellPlayerToggled: " ) + debugInfo.append( "(&7autosellPlayerToggled&3: " ) .append( Output.get().getColorCodeWarning() ) - .append( isPlayerAutoSellTurnedOn ? "enabled" : "disabled" ) + .append( isPlayerAutoSellTurnedOn ? "enabled" : + Output.get().getColorCodeError() + "disabled:" + Output.get().getColorCodeDebug() ) .append( Output.get().getColorCodeDebug() ) .append( ")"); } @@ -913,7 +765,7 @@ public boolean isAutoSellEnabled( StringBuilder debugInfo ) { } else { - debugInfo.append( "(autosell" ) + debugInfo.append( "(autosell " ) .append( Output.get().getColorCodeWarning() ) .append( "Enabled" ) .append( Output.get().getColorCodeDebug() ) @@ -923,7 +775,7 @@ public boolean isAutoSellEnabled( StringBuilder debugInfo ) { } else { - debugInfo.append( "(autosell" ) + debugInfo.append( "(autosell " ) .append( Output.get().getColorCodeWarning() ) .append( "Disabled" ) .append( Output.get().getColorCodeDebug() ) @@ -933,22 +785,6 @@ public boolean isAutoSellEnabled( StringBuilder debugInfo ) { 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( StringBuilder debugInfo ) { -// return isAutoSellByPermEnabled( isAutoSellEnabled( debugInfo ), debugInfo ); -// } /** *

    This will check to see if the player has the perms enabled @@ -963,6 +799,7 @@ public boolean isAutoSellEnabled( StringBuilder debugInfo ) { * @param isPlayerAutosellEnabled * @return */ + @SuppressWarnings("unused") private boolean isAutoSellByPermEnabledAutoFeatures( StringBuilder debugInfo ) { boolean autoSellByPerm = true; @@ -976,12 +813,14 @@ private boolean isAutoSellByPermEnabledAutoFeatures( StringBuilder debugInfo ) { if ( !"disable".equalsIgnoreCase( perm ) && !"false".equalsIgnoreCase( perm ) ) { - debugInfo.append( "(autosellAutoFeaturesByPerm: " ) - .append( Output.get().getColorCodeWarning() ) - ; + debugInfo.append( "(&7autosellAutoFeaturesByPerm&3: " ) + .append( Output.get().getColorCodeWarning() ) + ; if ( isOp() ) { - debugInfo.append( "Op-Disabled" ); + debugInfo.append( + Output.get().getColorCodeError() + "Op-Disabled" + Output.get().getColorCodeDebug() + ); autoSellByPerm = false; } else { @@ -1035,7 +874,7 @@ public boolean checkAutoSellTogglePerms( StringBuilder debugInfo ) { if ( SellAllUtil.get().isAutoSellPerUserToggleablePermEnabled ) { - debugInfo.append( "(autosellToggleByPerm: " ) + debugInfo.append( "(&7autosellToggleByPerm&3: " ) .append( Output.get().getColorCodeWarning() ) ; @@ -1045,7 +884,9 @@ public boolean checkAutoSellTogglePerms( StringBuilder debugInfo ) { !"false".equalsIgnoreCase( perm ) ) { if ( isOp() ) { - debugInfo.append( "Op-Disabled" ); + debugInfo.append( + Output.get().getColorCodeError() + "Op-Disabled:" + Output.get().getColorCodeDebug() + ); results = false; } @@ -1053,7 +894,8 @@ public boolean checkAutoSellTogglePerms( StringBuilder debugInfo ) { results = hasPermission( perm ); - debugInfo.append( results ? "hasPerm" : "noPerm" ); + debugInfo.append( results ? "hasPerm" : + Output.get().getColorCodeError() + "noPerm" + Output.get().getColorCodeDebug() ); } } @@ -1064,4 +906,21 @@ public boolean checkAutoSellTogglePerms( StringBuilder debugInfo ) { return results; } + + /** + * This miscText is not used for any specific purpose other than to hold a String + * value. It can be used to return a message from a function, but it should always + * be cleared when done using it. + * + * @return + */ + @Override + public String getMiscText() { + return miscText; + } + @Override + public void setMiscText( String text ) { + miscText = text; + } + } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerException.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerException.java new file mode 100644 index 000000000..79d646670 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerException.java @@ -0,0 +1,15 @@ +package tech.mcprison.prison.spigot.game; + +public class SpigotPlayerException extends Exception { + + private static final long serialVersionUID = 1L; + + public SpigotPlayerException() { + super( "Cannot load the bukkit org.bukkit.entity.Player." ); + } + + public SpigotPlayerException( String msg ) { + super( msg ); + } + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java index 5fb7637ad..1fb291529 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotPlayerUtil.java @@ -365,12 +365,6 @@ private int getEnchantment( String enchant ) { } } -// for ( Enchantment e : Enchantment.values() ) { -// if (e.getKey().getKey().equalsIgnoreCase( enchant ) ) { -// enchantment = e; -// break; -// } -// } if ( enchantment != null ) { @@ -425,36 +419,6 @@ public int getItemInHandEnchantmentLuck() { } -// public String getEnchantments() { -// StringBuilder sb = new StringBuilder(); -// -// SpigotItemStack itemStack = getItemInHand(); -// -// if ( itemStack != null && itemStack.getBukkitStack() != null) { -// try { -// -// Set keys = itemStack.getBukkitStack().getEnchantments().keySet(); -// -// for ( Enchantment key : keys ) { -// Integer value = itemStack.getBukkitStack().getEnchantments().get( key ); -// -// if ( value != null ) { -// if ( sb.length() > 0 ) { -// sb.append( ", " ); -// } -// sb.append( key.getName() ).append( ": " ).append( value ); -// key.getItemTarget().toString() -// } -// } -// -// } -// catch ( NullPointerException e ) { -// // Ignore. This happens when a TokeEnchanted tool is used when TE is not installed anymore. -// // It throws this exception: Caused by: java.lang.NullPointerException: null key in entry: null=5 -// } -// } -// } - public String getItemInHandLore() { StringBuilder sb = new StringBuilder(); @@ -482,6 +446,4 @@ public void setSpigotPlayer( SpigotPlayer spigotPlayer ) { this.spigotPlayer = spigotPlayer; } - - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java index fc899a239..2da03d031 100644 --- a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/SpigotWorld.java @@ -18,12 +18,20 @@ package tech.mcprison.prison.spigot.game; +import java.util.ArrayList; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; import org.bukkit.Bukkit; +import com.cryptomorin.xseries.XEntityType; +import com.cryptomorin.xseries.XMaterial; + +import tech.mcprison.prison.bombs.MineBombs.AnimationArmorStandItemLocation; +import tech.mcprison.prison.internal.ArmorStand; +import tech.mcprison.prison.internal.Entity; +import tech.mcprison.prison.internal.EntityType; import tech.mcprison.prison.internal.ItemStack; import tech.mcprison.prison.internal.Player; import tech.mcprison.prison.internal.PrisonStatsElapsedTimeNanos; @@ -38,12 +46,16 @@ import tech.mcprison.prison.spigot.block.SpigotBlockSetSynchronously; import tech.mcprison.prison.spigot.block.SpigotItemStack; import tech.mcprison.prison.spigot.compat.SpigotCompatibility; +import tech.mcprison.prison.spigot.game.entity.SpigotArmorStand; +import tech.mcprison.prison.spigot.game.entity.SpigotEntity; +import tech.mcprison.prison.spigot.game.entity.SpigotEntityType; import tech.mcprison.prison.util.Location; /** * @author Faizaan A. Datoo */ -public class SpigotWorld implements World { +public class SpigotWorld + implements World { private org.bukkit.World bukkitWorld; @@ -67,6 +79,41 @@ public SpigotWorld(org.bukkit.World bukkitWorld) { .map((Function) SpigotPlayer::new) .collect(Collectors.toList()); } + + @Override + public List getEntities() { + List results = new ArrayList<>(); + + for (org.bukkit.entity.Entity bukkitEnitity : getWrapper().getEntities() ) { + + results.add( new SpigotEntity( bukkitEnitity) ); + } + + return results; + } + + /** + * Filters the returned Entities by the selected EntityType. + * + * @param eType + * @return + */ + public List getEntities( EntityType eType ) { + List results = new ArrayList<>(); + + SpigotEntityType seType = eType == null ? null : (SpigotEntityType) eType; + + for (org.bukkit.entity.Entity bukkitEnitity : getWrapper().getEntities() ) { + + if ( seType == null || + seType.getxEType() == XEntityType.of(bukkitEnitity) ) { + + results.add( new SpigotEntity( bukkitEnitity )); + } + } + + return results; + } /** *

    This should be the ONLY usage in the whole Prison plugin that gets the @@ -81,42 +128,37 @@ public SpigotWorld(org.bukkit.World bukkitWorld) { @Override public Block getBlockAt( Location location, boolean containsCustomBlocks ) { - if ( getBlockAtLocation == null ) { - getBlockAtLocation = new SpigotBlockGetAtLocation(); - } - - return getBlockAtLocation.getBlockAt(location, containsCustomBlocks, this); + if ( getBlockAtLocation == null ) { + getBlockAtLocation = new SpigotBlockGetAtLocation(); + } + + return getBlockAtLocation.getBlockAt(location, containsCustomBlocks, this); } public Block getBlockAt( Location location ) { - return getBlockAt( location, false ); + return getBlockAt( location, false ); } -// public SpigotBlock getSpigotBlockAt(Location location) { -// return new SpigotBlock( -// bukkitWorld.getBlockAt(SpigotUtil.prisonLocationToBukkit(location))); -// } - public org.bukkit.Location getBukkitLocation(Location location) { - return SpigotUtil.prisonLocationToBukkit(location); + return SpigotUtil.prisonLocationToBukkit(location); } public org.bukkit.inventory.ItemStack getBukkitItemStack( ItemStack itemStack ) { - SpigotItemStack sItemStack = (SpigotItemStack) itemStack; - - return sItemStack.getBukkitStack(); + SpigotItemStack sItemStack = (SpigotItemStack) itemStack; + + return sItemStack.getBukkitStack(); } @Override public void setBlock( PrisonBlock block, int x, int y, int z ) { - Location loc = new Location( this, x, y, z ); - org.bukkit.block.Block bukkitBlock = - bukkitWorld.getBlockAt(SpigotUtil.prisonLocationToBukkit(loc)); - - SpigotCompatibility.getInstance().updateSpigotBlock( block, bukkitBlock ); + Location loc = new Location( this, x, y, z ); + org.bukkit.block.Block bukkitBlock = + bukkitWorld.getBlockAt(SpigotUtil.prisonLocationToBukkit(loc)); + + SpigotCompatibility.getInstance().updateSpigotBlock( block, bukkitBlock ); } @@ -162,63 +204,161 @@ public void setBlocksSynchronously( List tBlocks, MineRes } -// public String getBlockSignature( Location location ) { -// String results = null; -// -// if ( getWrapper() != null ) { -// -// SpigotBlock block = (SpigotBlock) getBlockAt( location ); -// -// StringBuilder sb = new StringBuilder(); -// sb.append( block.getWrapper().getType().name() ) -// .append( ":" ) -//// .append( location.toWorldCoordinates() ) -//// .append( "::" ) -// .append( block.getWrapper().getBlockData() ); -// -// results = sb.toString(); -// } -// -// return results; -// } -// public void getTestBlock() { -// -// PrisonNBTUtil nbtUtil = new PrisonNBTUtil(); -// -// NBTItem nbtItemStack = nbtUtil.getNBT( bstack ); -// -// nbtItemStack. -// } + public org.bukkit.World getWrapper() { + return bukkitWorld; + } + + @Override + public Entity spawnEntity( Location location, EntityType entityType) { + + return new SpigotEntity( spawnBukkitEntity( location, entityType ) ); + } + + public org.bukkit.entity.Entity spawnBukkitEntity( Location location, EntityType entityType) { + + SpigotLocation sLocation = + ( location instanceof SpigotLocation ? + (SpigotLocation) location : + new SpigotLocation( location )); + + SpigotEntityType sEtityType = SpigotEntityType.getSpigotEntityType( entityType ); + + org.bukkit.entity.Entity bEntity = + ((SpigotWorld) sLocation.getWorld()).getWrapper().spawnEntity( + sLocation.getBukkitLocation(), sEtityType.getbEntityType() ); + + return bEntity; + } + + @Override + public ArmorStand spawnArmorStand(Location location) { + + org.bukkit.entity.ArmorStand armorStand = spawnBukkitArmorStand( location ); + + SpigotArmorStand sArmorStand = new SpigotArmorStand( armorStand ); + + return sArmorStand; + } + + public org.bukkit.entity.ArmorStand spawnBukkitArmorStand( Location location ) { + + int maxHight = location.getWorld().getMaxHeight(); + + Location spawnPoint = new Location( location ); + spawnPoint.setY(maxHight); + + org.bukkit.entity.Entity bEntity = spawnBukkitEntity( spawnPoint, SpigotEntityType.ENTITY_TYPE_ARMOR_STAND ); + + org.bukkit.entity.ArmorStand armorStand = (org.bukkit.entity.ArmorStand) bEntity; + armorStand.setVisible(false); + + armorStand.teleport( new SpigotLocation( location ).getBukkitLocation() ); + + return armorStand; + } + + -// public void setBlockFromString( String blockString, Location location ) { -// -// String[] parts = blockString.split("::"); -// String blockNameFormal = parts[0]; -// String worldCoordinates = parts[1]; -// String blockData = parts[2]; -// -// Location targetLocation = location; -// if ( targetLocation == null ) { -// targetLocation = Location.decodeWorldCoordinates(worldCoordinates); + @Override + public ArmorStand spawnArmorStand( Location location, String itemType, + AnimationArmorStandItemLocation asLocation ) { + + + // NOTE: Once spawned, the armor stand is not being teleported back to the + // intended location. It was being spawned at a different location + // because it was "flashing" as visible. +// int maxHight = location.getWorld().getMaxHeight(); + +// Location spawnPoint = new Location( location ); +// spawnPoint.setY(maxHight); + + + + org.bukkit.inventory.ItemStack bItemStack = null; + +// Location spawnPoint = new Location( location ); +// spawnPoint.setX( spawnPoint.getX() + 2 ); +// spawnPoint.setZ( spawnPoint.getZ() + 2 ); + + + org.bukkit.entity.Entity bEntity = spawnBukkitEntity( location, SpigotEntityType.ENTITY_TYPE_ARMOR_STAND ); + org.bukkit.entity.ArmorStand as = (org.bukkit.entity.ArmorStand) bEntity; + + as.setVisible( false ); + as.setBasePlate( false ); + as.setCanPickupItems( false ); +// as.setInvulnerable( true ); +// as.setGravity( false ); + + +// if ( customName == null ) { +// as.setCustomNameVisible( false ); +// } +// else { +// as.setCustomNameVisible( true ); +// as.setCustomName( customName ); // } -// -// SpigotBlock block = (SpigotBlock) getBlockAt( targetLocation ); -// -// Prison.get().getPlatform().getPrisonBlock(blockNameFormal); -//// block.setType(Material.getMaterial(parts[0])); -// -// BlockData targetBlockData = -// SpigotPrison.getInstance().getServer().createBlockData( blockData ); -// -// block.getWrapper().setBlockData( targetBlockData ); -// -// } + + if ( itemType == null || itemType.trim().length() == 0 ) { + as.setArms( false ); + + } + else { + + XMaterial xMat = XMaterial.matchXMaterial( itemType ).orElse( null ); + bItemStack = xMat == null ? null : xMat.parseItem(); + + if ( bItemStack == null ) { + + bItemStack = XMaterial.COBBLESTONE.parseItem(); + } + + + if ( asLocation == AnimationArmorStandItemLocation.hand ) { + + as.setItemInHand(bItemStack); + as.setArms( true ); + +// as.setItem( EquipmentSlot.HAND, bItemStack); + } + else { + as.setHelmet(bItemStack); + + } + + + } + + as.getHelmet(); + as.setHelmet(bItemStack); + + + // wrap in a SpigotArmorStand: + SpigotArmorStand sas = new SpigotArmorStand( as ); + + return sas; + } - public org.bukkit.World getWrapper() { - return bukkitWorld; + /** + * This creates a new instance of a SpigotWorld object based upon the world's name. + * This uses the 'org.bukkit.World.getWorld( worldName );' to return a bukkit world, + * then wrap it in a SpigotWorld object. + * + * @param worldName + * @return + */ + public static SpigotWorld getWorld(String worldName) { + + org.bukkit.World world = Bukkit.getWorld( worldName ); + + return new SpigotWorld( world ); + } + + + public int getMaxHeight() { + return getWrapper().getMaxHeight(); } - } diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/entity/SpigotArmorStand.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/entity/SpigotArmorStand.java new file mode 100644 index 000000000..a07e090a4 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/entity/SpigotArmorStand.java @@ -0,0 +1,193 @@ +package tech.mcprison.prison.spigot.game.entity; + +import tech.mcprison.prison.internal.Entity; +import tech.mcprison.prison.internal.EulerAngle; +import tech.mcprison.prison.internal.ItemStack; +import tech.mcprison.prison.spigot.block.SpigotItemStack; + +public class SpigotArmorStand + extends SpigotEntity + implements tech.mcprison.prison.internal.ArmorStand +{ + + private org.bukkit.entity.ArmorStand bArmorStand; + + private SpigotItemStack sHandItemStack = null; + private SpigotItemStack sHelmetItemStack = null; + + public SpigotArmorStand( org.bukkit.entity.ArmorStand bArmorStand ) { + super( bArmorStand ); + + // bArmorStand.setVisible( false ); + + this.bArmorStand = bArmorStand; + } + + public SpigotArmorStand(Entity entity) { + this( (org.bukkit.entity.ArmorStand) ((SpigotEntity) entity).getBukkitEntity() ); + + org.bukkit.entity.Entity bEntity = ((SpigotEntity) entity).getBukkitEntity(); + if ( bEntity instanceof org.bukkit.entity.ArmorStand ) { + this.bArmorStand = (org.bukkit.entity.ArmorStand) bEntity; + this.bArmorStand.setVisible( false ); + } + } + + @Override + public boolean isVisible() { + return bArmorStand.isVisible(); + } + + @Override + public void setVisible( boolean visible ) { + bArmorStand.setVisible( visible ); + } + + @Override + public void setCustomNameVisible( boolean visible ) { + bArmorStand.setCustomNameVisible( visible ); + } + + @Override + public void setCustomName( String customName ) { + + bArmorStand.setCustomName( customName ); + } + + @Override + public boolean getRemoveWhenFarAway() { + return bArmorStand.getRemoveWhenFarAway(); + } + + @Override + public void setRemoveWhenFarAway(boolean removeWhenFarAway) { + bArmorStand.setRemoveWhenFarAway( removeWhenFarAway ); + } + + @Override + public ItemStack getItemInHand() { + return sHandItemStack; + } + + @Override + public void setItemInHand(ItemStack item) { + if ( item == null ) { + bArmorStand.setItemInHand( null ); + bArmorStand.setArms( false ); + this.sHandItemStack = null; + } + else { + SpigotItemStack sItemStack = + ( item instanceof SpigotItemStack ? + (SpigotItemStack) item : + new SpigotItemStack( item ) ); + + this.sHandItemStack = sItemStack; + + org.bukkit.inventory.ItemStack bas = sItemStack.getBukkitStack(); + + bArmorStand.setArms( true ); + bArmorStand.setItemInHand( bas ); + } + } + + + @Override + public ItemStack getHelmet() { + return sHelmetItemStack; + } + + @Override + public void setHelmet(ItemStack item) { + if ( item == null ) { + bArmorStand.setHelmet( null ); + this.sHelmetItemStack = null; + } + else { + SpigotItemStack sItemStack = + ( item instanceof SpigotItemStack ? + (SpigotItemStack) item : + new SpigotItemStack( item ) ); + + this.sHelmetItemStack = sItemStack; + + org.bukkit.inventory.ItemStack bas = sItemStack.getBukkitStack(); + + bArmorStand.setItemInHand( bas ); + } + } + + + + @Override + public void setRightArmPose(EulerAngle arm) { + + org.bukkit.util.EulerAngle eAngle = new org.bukkit.util.EulerAngle( + arm.getX(), arm.getY(), arm.getZ() ); + + bArmorStand.setRightArmPose(eAngle); + } + + @Override + public boolean isGlowing() { + return bArmorStand.isGlowing(); + } + + @Override + public void setGlowing(boolean glowing) { + bArmorStand.setGlowing(glowing); + } + + @Override + public boolean hasGravity() { + return bArmorStand.hasGravity(); + } + + @Override + public void setGravity(boolean gravity) { + bArmorStand.setGravity(gravity); + } + + + @Override + public boolean hasArms() { + return bArmorStand.hasArms(); + } + @Override + public void setArms( boolean arms ) { + bArmorStand.setArms( arms ); + } + + @Override + public boolean hasBasePlate() { + return bArmorStand.hasBasePlate(); + } + @Override + public void setBasePlate( boolean basePlate ) { + bArmorStand.setBasePlate( basePlate ); + } + + @Override + public boolean getCanPickupItems() { + return bArmorStand.getCanPickupItems(); + } + @Override + public void setCanPickupItems( boolean canPickupItems ) { + bArmorStand.setCanPickupItems( canPickupItems ); + } + + @Override + public boolean isSmall() { + return bArmorStand.isSmall(); + } + @Override + public void setSmall(boolean small) { + bArmorStand.setSmall(small); + } + + @Override + public void setInvulnerable(boolean invulnerable) { + bArmorStand.setInvulnerable(invulnerable); + } + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/entity/SpigotEntity.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/entity/SpigotEntity.java new file mode 100644 index 000000000..3f3b931f8 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/entity/SpigotEntity.java @@ -0,0 +1,289 @@ +package tech.mcprison.prison.spigot.game.entity; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import com.cryptomorin.xseries.XEntityType; + +import tech.mcprison.prison.internal.Entity; +import tech.mcprison.prison.internal.EntityType; +import tech.mcprison.prison.internal.World; +import tech.mcprison.prison.spigot.game.SpigotCommandSender; +import tech.mcprison.prison.spigot.game.SpigotLocation; +import tech.mcprison.prison.spigot.game.SpigotWorld; +import tech.mcprison.prison.spigot.nbt.PrisonNBTUtil; +import tech.mcprison.prison.util.Location; +import tech.mcprison.prison.util.Vector; + +public class SpigotEntity + extends SpigotCommandSender + implements Entity { + + private org.bukkit.entity.Entity bukkitEntity; + + public SpigotEntity(org.bukkit.entity.Entity entity ) { + super( entity ); + + this.bukkitEntity = entity; + } + + + @Override + public String getNbtString( String key ) { + String results = ""; + + if ( bukkitEntity != null ) { + results = PrisonNBTUtil.getNBTString(bukkitEntity, key); + } + + return results; + } + @Override + public void setNbtString( String key, String value ) { + if ( bukkitEntity != null ) { + PrisonNBTUtil.setNBTString(bukkitEntity, key, value); + } + } + + + @Override + public UUID getUniqueId() { + return getBukkitEntity().getUniqueId(); + } + + @Override + public String getCustomName() { + return getBukkitEntity().getCustomName(); + } + + @Override + public int getEntityId() { + return getBukkitEntity().getEntityId(); + } + + @Override + public boolean eject() { + return getBukkitEntity().eject(); + } + + @Override + public Location getLocation() { + return new SpigotLocation( getBukkitEntity().getLocation() ); + } + + @Override + public Location getLocation(Location loc) { + return + new SpigotLocation( + getBukkitEntity().getLocation( ((SpigotLocation) loc).getBukkitLocation() )); + } + + @Override + public float getFallDistance() { + return getBukkitEntity().getFallDistance(); + } + + @Override + public int getFireTicks() { + return getBukkitEntity().getFireTicks(); + } + + @Override + public int getMaxFireTicks() { + return getBukkitEntity().getMaxFireTicks(); + } + + /** + * The parameter of radius is actually a cubic-radius, + * where the r is added to the location to produce a cube around the + * Entity or Player. + * + * @param r Radius around the Entity or Player + * @param eType + * @return + */ + public List getNearbyEntities( int r, EntityType eType ) { + + List bEntities = getBukkitEntity() + .getNearbyEntities( r * 2, r * 2, r * 2 ); + + return convertEntities( bEntities, (SpigotEntityType) eType ); + } + + @Override + public List getNearbyEntities(double x, double y, double z) { + List bEntities = getBukkitEntity().getNearbyEntities(x, y, z); + return convertEntities( bEntities, null ); + } + + /** + * Converts all of the bukkit entities in to the SpigotEntityType, and if + * a SpigotEntityType is provided, it will also filter the results. + * + * @param bEntities + * @param seType + * @return + */ + private List convertEntities( + List bEntities, + SpigotEntityType seType ) { + List sEntities = new ArrayList<>(); + for (org.bukkit.entity.Entity entity : bEntities) { + + if ( seType == null || + seType.getxEType() == XEntityType.of(entity) ) { + + sEntities.add( new SpigotEntity( entity )); + } + } + return sEntities; + } + + + + @SuppressWarnings("deprecation") + @Override + public Entity getPassenger() { + return new SpigotEntity( getBukkitEntity().getPassenger() ); + } + + @Override + public int getTicksLived() { + return getBukkitEntity().getTicksLived(); + } + + @Override + public EntityType getType() { + + EntityType eType = new SpigotEntityType( getBukkitEntity().getType() ); + return eType; + } + + @Override + public Entity getVehicle() { + return new SpigotEntity( getBukkitEntity().getVehicle() ); + } + + @Override + public Vector getVelocity() { + + org.bukkit.util.Vector bVel = getBukkitEntity().getVelocity(); + Vector vec = new Vector( bVel.getX(), bVel.getY(), bVel.getZ() ); + + return vec; + } + + @Override + public World getWorld() { + return new SpigotWorld( getBukkitEntity().getWorld() ); + } + + @Override + public boolean isCustomNameVisible() { + return getBukkitEntity().isCustomNameVisible(); + } + + @Override + public void setCustomName(String name) { + getBukkitEntity().setCustomName(name); + } + + @Override + public void setCustomNameVisible(boolean flag) { + getBukkitEntity().setCustomNameVisible(flag); + } + + @Override + public boolean isDead() { + return getBukkitEntity().isDead(); + } + + @Override + public boolean isEmpty() { + return getBukkitEntity().isEmpty(); + } + + @Override + public boolean isInsideVehicle() { + return getBukkitEntity().isInsideVehicle(); + } + + @Override + public boolean isOnGround() { + return getBukkitEntity().isOnGround(); + } + + @Override + public boolean isValid() { + return getBukkitEntity().isValid(); + } + + @Override + public boolean leaveVehicle() { + return getBukkitEntity().leaveVehicle(); + } + + @Override + public void remove() { + getBukkitEntity().remove(); + } + + @Override + public void setFallDistance(float distance) { + getBukkitEntity().setFallDistance(distance); + } + + @Override + public void setFireTicks(int ticks) { + getBukkitEntity().setFireTicks(ticks); + } + + @SuppressWarnings("deprecation") + @Override + public boolean setPassenger(Entity passenger) { + return getBukkitEntity().setPassenger( ((SpigotEntity) passenger).getBukkitEntity() ); + } + + @Override + public void setTicksLived(int value) { + getBukkitEntity().setTicksLived(value); + } + + @Override + public void setVelocity(Vector velocity) { + + org.bukkit.util.Vector bVec = + new org.bukkit.util.Vector( + velocity.getX(), velocity.getY(), velocity.getZ() ); + + getBukkitEntity().setVelocity( bVec ); + } + + @Override + public boolean teleport(Entity destination) { + return getBukkitEntity().teleport( ((SpigotEntity) destination).getBukkitEntity() ); + } + + @Override + public boolean teleport(Location location) { + + org.bukkit.World world = ((SpigotWorld) location.getWorld()).getWrapper(); + org.bukkit.Location loc = new org.bukkit.Location( world, + location.getX(), location.getY(), location.getZ(), + location.getYaw(), location.getPitch()); + return getBukkitEntity().teleport( loc ); + } + + public org.bukkit.entity.Entity getBukkitEntity() { + return bukkitEntity; + } + + + @Override + public boolean isPlayer() { + return false; + } + + +} diff --git a/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/entity/SpigotEntityType.java b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/entity/SpigotEntityType.java new file mode 100644 index 000000000..28beb7821 --- /dev/null +++ b/prison-spigot/src/main/java/tech/mcprison/prison/spigot/game/entity/SpigotEntityType.java @@ -0,0 +1,61 @@ +package tech.mcprison.prison.spigot.game.entity; + +import com.cryptomorin.xseries.XEntityType; + +import tech.mcprison.prison.internal.EntityType; + +public class SpigotEntityType + extends EntityType { + + private org.bukkit.entity.EntityType bEntityType; + private XEntityType xEType; + + public SpigotEntityType( String entityType ) { + super( entityType ); + + } + public SpigotEntityType( org.bukkit.entity.EntityType bEntityType ) { + super( "" ); + + this.bEntityType = bEntityType; + + XEntityType xEType = XEntityType.of( bEntityType ); + this.xEType = xEType; + + setEntityType( xEType.name() ); + } + public SpigotEntityType( XEntityType xEType ) { + super( xEType.name() ); + + this.xEType = xEType; + + this.bEntityType = xEType.get(); + } + + public static SpigotEntityType getSpigotEntityType( EntityType entityType ) { + SpigotEntityType results = null; + + XEntityType xEType = XEntityType.of( entityType.getEntityType().toUpperCase() ).orElse( null ); + + if ( xEType != null ) { + results = new SpigotEntityType( xEType ); + } + + return results; + } + + public org.bukkit.entity.EntityType getbEntityType() { + return bEntityType; + } + public void setbEntityType(org.bukkit.entity.EntityType bEntityType) { + this.bEntityType = bEntityType; + } + + public XEntityType getxEType() { + return xEType; + } + public void setxEType(XEntityType xEType) { + this.xEType = xEType; + } + +} 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 5497f41af..cc8440ef9 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 @@ -92,7 +92,6 @@ public class ListenersPrisonManager private final MessagesConfig messages = SpigotPrison.getInstance().getMessagesConfig(); boolean guiNotEnabled = !getBoolean(config.getString("prison-gui-enabled")); -// private Optional ladder; // makes no sense... not thread safe. public ChatMode mode; @@ -238,7 +237,6 @@ public void onPlayerInteractEvent(PlayerInteractEvent e){ // signs, so check if the material name contains "sign": String matName = clickedBlock.name().toLowerCase(); if ( matName.contains("sign")) { -// if (clickedBlock == Material.SIGN || clickedBlock == Material.WALL_SIGN) { // Get the player Player p = e.getPlayer(); @@ -265,7 +263,6 @@ public void onPlayerInteractEvent(PlayerInteractEvent e){ if (sellAllUtil.isSellAllSignPermissionToUseEnabled && !p.hasPermission(permissionUseSign)) { Output.get().sendWarn(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_missing_permission) -// + " [&3" + permissionUseSign + "&7]" ); return; } @@ -426,7 +423,7 @@ public void onClick(InventoryClickEvent e){ // If a GUI Tools Page action, then process the request and just exit: else if ( SpigotGUIMenuTools.getInstance().processGUIPage( p, title, e ) ) { - return; + return; } @@ -570,41 +567,7 @@ else if ( SpigotGUIMenuTools.getInstance().processGUIPage( p, title, e ) ) { break; } -// // Check the inventory title and do the actions. -// case "PrisonManager -> AutoFeatures": { -// -// // Call the method -// autoFeaturesGUI(e, p, parts); -// -// break; -// } - -// // Check the title and do the actions. -// case "AutoFeatures -> AutoPickup": { -// -// // Call the method -// autoPickupGUI(e, p, parts); -// -// break; -// } - -// // Check the title and do the actions. -// case "AutoFeatures -> AutoSmelt": { -// -// // Call the method -// autoSmeltGUI(e, p, parts); -// -// break; -// } - -// // Check the title and do the actions. -// case "AutoFeatures -> AutoBlock": { -// -// // Call the method -// autoBlockGUI(e, p, parts); -// -// break; -// } + // Check the title and do the actions. case "SellAll -> Blocks": { @@ -744,60 +707,8 @@ else if ( SpigotGUIMenuTools.getInstance().processGUIPage( p, title, e ) ) { } - - -// private boolean processGUIPage( Player p, String title, InventoryClickEvent e ) { -// boolean isPageAction = false; -// -// ItemStack currentItem = e.getCurrentItem(); -// if ( currentItem != null && currentItem.hasItemMeta() ) { -// -// ItemMeta meta = currentItem.getItemMeta(); -// -// if ( meta.hasLore() ) { -// -// String command = null; -// -// List lores = meta.getLore(); -// -// for ( String lore : lores ) { -// -// if ( lore.contains( SpigotGUIMenuTools.GUI_MENU_TOOLS_PAGE ) ) { -// isPageAction = true; -// } -// if ( lore.contains( SpigotGUIMenuTools.GUI_MENU_TOOLS_COMMAND ) ) { -// command = Text.stripColor( lore ).replace( SpigotGUIMenuTools.GUI_MENU_TOOLS_COMMAND, "" ).trim(); -// } -// } -// -// if ( isPageAction && command != null ) { -// Bukkit.dispatchCommand(p, -// Prison.get().getCommandHandler().findRegisteredCommand( command )); -// -// } -// } -// -// } -// -// return isPageAction; -// } private void sellAllPlayerGUI(InventoryClickEvent e, Player p, String[] parts) { -// if (parts[0].equalsIgnoreCase("Prior")){ -// -// SellAllPlayerGUI gui = new SellAllPlayerGUI(p, Integer.parseInt(parts[1])); -// gui.open(); -// -// e.setCancelled(true); -// return; -// } else if (parts[0].equalsIgnoreCase("Next")){ -// -// SellAllPlayerGUI gui = new SellAllPlayerGUI(p, Integer.parseInt(parts[1])); -// gui.open(); -// -// e.setCancelled(true); -// return; -// } p.closeInventory(); e.setCancelled(true); @@ -1401,7 +1312,7 @@ private void mineBlockPercentage(InventoryClickEvent e, Player p, String[] parts String positionStr = ( parts.length > 5 ? parts[5] : "0" ); int position = 0; try { - position = Integer.parseInt( positionStr ); + position = Integer.parseInt( positionStr ); } catch(NumberFormatException ignored) {} @@ -1620,22 +1531,6 @@ private void sellAllItemValue(InventoryClickEvent e, Player p, String[] parts) { private void sellAllAdminBlocksGUI(InventoryClickEvent e, Player p, String[] parts) { -// if (parts[0].equalsIgnoreCase("Prior")){ -// -// SellAllAdminBlocksGUI gui = new SellAllAdminBlocksGUI(p, Integer.parseInt(parts[1])); -// gui.open(); -// -// e.setCancelled(true); -// return; -// } else if (parts[0].equalsIgnoreCase("Next")){ -// -// SellAllAdminBlocksGUI gui = new SellAllAdminBlocksGUI(p, Integer.parseInt(parts[1])); -// gui.open(); -// -// e.setCancelled(true); -// return; -// } - if (e.isRightClick()){ String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall delete" ); @@ -1666,19 +1561,6 @@ private void prisonManagerGUI(InventoryClickEvent e, Player p, String buttonName break; } -// // Check the Item display name and do open the right GUI. -// case "AutoManager": { -// -// // Check if the autofeatures config isn't null. -// if(SpigotGUIComponents.afConfig() != null) { -// SpigotAutoFeaturesGUI gui = new SpigotAutoFeaturesGUI(p); -// gui.open(); -// } else { -// Output.get().sendWarn(new SpigotPlayer(p), "Can't find an autofeatures config, maybe they're disabled."); -// } -// break; -// } - // Check the Item display name and do open the right GUI. case "Mines": { SpigotMinesGUI gui = new SpigotMinesGUI(p, 1, "gui admin mines", "gui"); @@ -1706,28 +1588,19 @@ private void prisonManagerGUI(InventoryClickEvent e, Player p, String buttonName private void laddersGUI(InventoryClickEvent e, Player p, String buttonNameMain, Module module ) { // Check if the Ranks module's loaded. - if(!(module instanceof PrisonRanks)){ + if(!(module instanceof PrisonRanks) || !PrisonRanks.getInstance().isEnabled() ){ Output.get().sendWarn(new SpigotPlayer(p), "The GUI can't open because the &3Rank module &cisn't loaded"); p.closeInventory(); e.setCancelled(true); return; } -// if (parts[0].equalsIgnoreCase("Next") || parts[0].equalsIgnoreCase("Prior")){ -// -// // Open a new SpigotLadders GUI page. -// SpigotLaddersGUI gui = new SpigotLaddersGUI(p, Integer.parseInt(parts[1]), 1); -// p.closeInventory(); -// gui.open(); -// return; -// } - // Get the ladder by the name of the button got before. RankLadder rLadder = PrisonRanks.getInstance().getLadderManager().getLadder(buttonNameMain); if ( rLadder == null ) { - // Do nothing since it's not a valid ladder name: - return; + // Do nothing since it's not a valid ladder name: + return; } // ladder = rLadder; @@ -1735,22 +1608,22 @@ private void laddersGUI(InventoryClickEvent e, Player p, String buttonNameMain, // to be sure's a right click. if (e.isShiftClick() && e.isRightClick()) { - if ( rLadder.getRanks().size() > 0 ) { - - SpigotPlayer sPlayer = new SpigotPlayer( p ); - sPlayer.setActionBar( "Cannot delete a non-empty ladder" ); - } - else { - - // Execute the command - 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" ); - gui.open(); - return; - } + if ( rLadder.getRanks().size() > 0 ) { + + SpigotPlayer sPlayer = new SpigotPlayer( p ); + sPlayer.setActionBar( "Cannot delete a non-empty ladder" ); + } + else { + + // Execute the command + 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" ); + gui.open(); + return; + } } @@ -1765,14 +1638,12 @@ private void laddersGUI(InventoryClickEvent e, Player p, String buttonNameMain, private void ranksGUI(InventoryClickEvent e, Player p, String buttonNameMain, String[] parts) { -// if (parts[0].equalsIgnoreCase("Next") || parts[0].equalsIgnoreCase("Prior")){ -// -// // Open a new SpigotLadders GUI page. -// SpigotRanksGUI gui = new SpigotRanksGUI(p, ladder, Integer.parseInt(parts[1])); -// p.closeInventory(); -// gui.open(); -// return; -// } + if ( !PrisonRanks.getInstance().isEnabled() ) { + + Output.get().sendWarn(new SpigotPlayer(p), "&cPrison ranks are not enabled."); + return; + } + // Get the rank. Rank rank = PrisonRanks.getInstance().getRankManager().getRank(buttonNameMain); @@ -1826,53 +1697,32 @@ private void playerPrestigesGUI(InventoryClickEvent e, Player p, String buttonNa private void prestigeConfirmationGUI(InventoryClickEvent e, Player p, String buttonNameMain) { - String playerName = p.getName(); + String playerName = p.getName(); // Check the button name and do the actions. if (buttonNameMain.equalsIgnoreCase("Confirm: Prestige")){ - Output.get().logDebug( DebugTarget.rankup, "rankup: /gui prestigeConfirm: Prestige has been Confirmed. " - + " calling: '/prestige " + playerName + " confirm'" ); - - // Execute the command. - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "prestige" ); - - String command = registeredCmd + " " + playerName + " confirm"; - + Output.get().logDebug( DebugTarget.rankup, "rankup: /gui prestigeConfirm: Prestige has been Confirmed. " + + " calling: '/prestige " + playerName + " confirm'" ); + + // Execute the command. + String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "prestige" ); + + String command = registeredCmd + " " + playerName + " confirm"; + Bukkit.dispatchCommand(p, command ); } else if (buttonNameMain.equalsIgnoreCase("Cancel: Don't Prestige")){ - Output.get().logDebug( DebugTarget.rankup, "rankup: /gui prestigeConfirm: Prestige has been canceled " + - "for " + playerName + "." ); + Output.get().logDebug( DebugTarget.rankup, "rankup: /gui prestigeConfirm: Prestige has been canceled " + + "for " + playerName + "." ); - // Send a message to the player. -// Output.get().sendInfo(new SpigotPlayer(p), "&cCancelled"); } // Close the inventory. p.closeInventory(); -// // Check the button name and do the actions. -// if (buttonNameMain.equalsIgnoreCase("Confirm: Prestige")){ -// Output.get().logDebug( DebugTarget.rankup, "rankup: GUI: 'Confirm: Prestige' calling: '/rankup prestiges'" ); -// -// // Execute the command. -// String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "rankup" ); -// -// Bukkit.dispatchCommand(p, registeredCmd + " prestiges"); -// // Close the inventory. -// p.closeInventory(); -// } else if (buttonNameMain.equalsIgnoreCase("Cancel: Don't Prestige")){ -// Output.get().logDebug( DebugTarget.rankup, "rankup: GUI/: 'Cancel: Don't Prestige' sendInfo: 'cancelled'" ); -// -// // Send a message to the player. -// Output.get().sendInfo(new SpigotPlayer(p), "&cCancelled"); -// // Close the inventory. -// p.closeInventory(); -// } -// // Cancel the event. e.setCancelled(true); } @@ -1883,6 +1733,12 @@ private void rankManagerGUI(InventoryClickEvent e, Player p, String[] parts) { String buttonName = ( parts.length >= 1 ? parts[0] : ""); String rankName = (parts.length >= 2 ? parts[1] : "-rankHasNoName-"); + if ( !PrisonRanks.getInstance().isEnabled() ) { + + Output.get().sendWarn(new SpigotPlayer(p), "&cPrison ranks are not enabled."); + return; + } + // Get the rank. Rank rank = PrisonRanks.getInstance().getRankManager().getRank(rankName); @@ -1944,7 +1800,7 @@ private void rankManagerGUI(InventoryClickEvent e, Player p, String[] parts) { private void playerRanksGUI(InventoryClickEvent e, Player p, String buttonNameMain) { // Check the buttonName and do the actions. - String message = Text.stripColor( messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup) ); + String message = Text.stripColor( messages.getString(MessagesConfig.StringID.spigot_gui_lore_rankup) ); if (buttonNameMain.equals(SpigotPrison.format( message ))){ Bukkit.dispatchCommand(p, Prison.get().getCommandHandler().findRegisteredCommand( @@ -2083,15 +1939,6 @@ private void rankPriceGUI(InventoryClickEvent e, Player p, String[] parts) { private void minesGUI(InventoryClickEvent e, Player p, String buttonNameMain, String[] parts) { -// if (parts[0].equalsIgnoreCase("Next") || parts[0].equalsIgnoreCase("Prior")){ -// -// // Open a new SpigotLadders GUI page. -// SpigotMinesGUI gui = new SpigotMinesGUI(p, Integer.parseInt(parts[1])); -// p.closeInventory(); -// gui.open(); -// return; -// } - // Variables. PrisonMines pMines = PrisonMines.getInstance(); Mine m = pMines.getMine(buttonNameMain); @@ -2642,277 +2489,7 @@ private void radiusGUI(InventoryClickEvent e, Player p, String[] parts) { } } -// private void autoFeaturesGUI(InventoryClickEvent e, Player p, String[] parts) { -// -// // Get the config -// AutoFeaturesFileConfig afConfig = AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig(); -// -// // Output finally the buttonname and the mode explicit out of the array -// String buttonName = parts[0]; -// String mode = parts[1]; -// -// boolean enabled = mode.equalsIgnoreCase("Enabled"); -// -// // Check the clickType and do the actions -// if ( enabled && e.isRightClick() && e.isShiftClick() || -// !enabled && e.isRightClick()){ -// -// if (buttonName.equalsIgnoreCase("Full-Inventory-Sound")){ -// afConfig.setFeature( AutoFeatures.playSoundIfInventoryIsFull, !enabled ); -// saveConfigAutoFeatures(e, p); -// } -// -// if (buttonName.equalsIgnoreCase("Full-Inventory-ActionBar")){ -// afConfig.setFeature(AutoFeatures.actionBarMessageIfInventoryIsFull, !enabled); -// saveConfigAutoFeatures(e,p); -// } -// -// if (buttonName.equalsIgnoreCase("All")){ -// afConfig.setFeature(AutoFeatures.isAutoManagerEnabled, !enabled); -// saveConfigAutoFeatures(e,p); -// } -// -// } -// -// // Check the clickType and do the actions -// if (enabled && e.isRightClick() && e.isShiftClick() || !enabled && e.isRightClick() || enabled && e.isLeftClick()){ -// if (buttonName.equalsIgnoreCase("AutoPickup")){ -// if (e.isLeftClick()){ -// SpigotAutoPickupGUI gui = new SpigotAutoPickupGUI(p); -// gui.open(); -// return; -// } -// afConfig.setFeature(AutoFeatures.autoPickupEnabled, !enabled); -// saveConfigAutoFeatures(e,p); -// } -// -// if (buttonName.equalsIgnoreCase("AutoSmelt")){ -// if (e.isLeftClick()){ -// SpigotAutoSmeltGUI gui = new SpigotAutoSmeltGUI(p); -// gui.open(); -// return; -// } -// afConfig.setFeature(AutoFeatures.autoSmeltEnabled, !enabled); -// saveConfigAutoFeatures(e,p); -// } -// -// if (buttonName.equalsIgnoreCase("AutoBlock")){ -// if (e.isLeftClick()){ -// SpigotAutoBlockGUI gui = new SpigotAutoBlockGUI(p); -// gui.open(); -// return; -// } -// afConfig.setFeature(AutoFeatures.autoBlockEnabled, !enabled); -// saveConfigAutoFeatures(e,p); -// } -// } -// } - -// private void autoPickupGUI(InventoryClickEvent e, Player p, String[] parts) { -// -// // Get the config -// AutoFeaturesFileConfig afConfig = AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig(); -// -// // Output finally the buttonname and the mode explicit out of the array -// String buttonname = parts[0]; -// String mode = parts[1]; -// -// boolean enabled = mode.equalsIgnoreCase("Enabled"); -// -// // Check the click and do the actions, also the buttonName -// if ( enabled && e.isRightClick() && e.isShiftClick() || -// !enabled && e.isRightClick() ){ -// -// switch (buttonname){ -// case "All_Blocks":{ -// afConfig.setFeature( AutoFeatures.pickupAllBlocks, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// case "Cobblestone":{ -// afConfig.setFeature(AutoFeatures.pickupCobbleStone, !enabled); -// saveConfigPickup(e,p); -// break; -// } -// case "Gold_Ore":{ -// afConfig.setFeature( AutoFeatures.pickupGoldOre, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// case "Iron_Ore":{ -// afConfig.setFeature( AutoFeatures.pickupIronOre, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// case "Coal_Ore":{ -// afConfig.setFeature( AutoFeatures.pickupCoalOre, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// case "Diamond_Ore":{ -// afConfig.setFeature( AutoFeatures.pickupDiamondOre, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// case "Redstone_Ore":{ -// afConfig.setFeature( AutoFeatures.pickupRedStoneOre, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// case "Emerald_Ore":{ -// afConfig.setFeature( AutoFeatures.pickupEmeraldOre, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// case "Quartz_Ore":{ -// afConfig.setFeature( AutoFeatures.pickupQuartzOre, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// case "Lapis_Ore":{ -// afConfig.setFeature( AutoFeatures.pickupLapisOre, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// case "Snow_Ball":{ -// afConfig.setFeature( AutoFeatures.pickupSnowBall, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// case "Glowstone_Dust":{ -// afConfig.setFeature( AutoFeatures.pickupGlowstoneDust, !enabled ); -// saveConfigPickup(e, p); -// break; -// } -// default:{ -// break; -// } -// -// } -// } -// } -// -// private void autoSmeltGUI(InventoryClickEvent e, Player p, String[] parts) { -// -// // Get the config -// AutoFeaturesFileConfig afConfig = AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig(); -// -// // Output finally the buttonname and the mode explicit out of the array -// String buttonname = parts[0]; -// String mode = parts[1]; -// -// boolean enabled = mode.equalsIgnoreCase("Enabled"); -// -// // Check the clickType and do the actions -// if ( enabled && e.isRightClick() && e.isShiftClick() || -// !enabled && e.isRightClick()){ -// -// switch (buttonname){ -// case "Gold_Ore":{ -// afConfig.setFeature( AutoFeatures.smeltGoldOre, !enabled ); -// saveConfigSmelt(e, p); -// break; -// } -// case "Iron_Ore":{ -// afConfig.setFeature( AutoFeatures.smeltIronOre, !enabled ); -// saveConfigSmelt(e, p); -// break; -// } -// case "All_Ores":{ -// afConfig.setFeature( AutoFeatures.smeltAllBlocks, !enabled ); -// saveConfigSmelt(e, p); -// break; -// } -// default:{ -// break; -// } -// } -// } -// } -// -// private void autoBlockGUI(InventoryClickEvent e, Player p, String[] parts) { -// -// // Get the config -// AutoFeaturesFileConfig afConfig = AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig(); -// -// // Output finally the buttonname and the mode explicit out of the array -// String buttonname = parts[0]; -// String mode = parts[1]; -// -// boolean enabled = mode.equalsIgnoreCase("Enabled"); -// -// // Check the clickType and do the actions -// if ( enabled && e.isRightClick() && e.isShiftClick() || -// !enabled && e.isRightClick()){ -// -// switch (buttonname){ -// case "Gold_Block":{ -// afConfig.setFeature( AutoFeatures.blockGoldBlock, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "Iron_Block":{ -// afConfig.setFeature( AutoFeatures.blockIronBlock, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "Coal_Block":{ -// afConfig.setFeature( AutoFeatures.blockCoalBlock, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "Diamond_Block":{ -// afConfig.setFeature( AutoFeatures.blockDiamondBlock, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "Redstone_Block":{ -// afConfig.setFeature( AutoFeatures.blockRedstoneBlock, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "Emerald_Block":{ -// afConfig.setFeature( AutoFeatures.blockEmeraldBlock, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "Quartz_Block":{ -// afConfig.setFeature( AutoFeatures.blockQuartzBlock, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "Prismarine_Block":{ -// afConfig.setFeature( AutoFeatures.blockPrismarineBlock, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "Lapis_Block":{ -// afConfig.setFeature( AutoFeatures.blockLapisBlock, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "Snow_Block":{ -// afConfig.setFeature( AutoFeatures.blockSnowBlock, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "Glowstone_Block":{ -// afConfig.setFeature( AutoFeatures.blockGlowstone, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// case "All_Blocks":{ -// afConfig.setFeature( AutoFeatures.blockAllBlocks, !enabled ); -// saveConfigBlock(e, p); -// break; -// } -// default:{ -// break; -// } -// } -// } -// -// } + private void modeAction(AsyncPlayerChatEvent e, Player p, String message) { @@ -2942,7 +2519,7 @@ private void modeAction(AsyncPlayerChatEvent e, Player p, String message) { private void sellAllCurrencyChat(AsyncPlayerChatEvent e, Player p, String message) { // Check message and do the action - String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall set currency" ); + String registeredCmd = Prison.get().getCommandHandler().findRegisteredCommand( "sellall set currency" ); if (message.equalsIgnoreCase("cancel")){ Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_event_cancelled)); } else if (message.equalsIgnoreCase("default")){ @@ -2957,21 +2534,6 @@ private void sellAllCurrencyChat(AsyncPlayerChatEvent e, Player p, String messag isChatEventActive = false; } -// private void prestigeAction(AsyncPlayerChatEvent e, Player p, String message) { -// -// // Check the chat message and do the actions -// if (message.equalsIgnoreCase("cancel")) { -// Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_prestiges_cancelled)); -// } else if (message.equalsIgnoreCase("confirm")) { -// Bukkit.getScheduler().runTask(SpigotPrison.getInstance(), () -> Bukkit.getServer().dispatchCommand(p, "rankup prestiges")); -// } else { -// Output.get().sendInfo(new SpigotPlayer(p), messages.getString(MessagesConfig.StringID.spigot_message_prestiges_cancelled_wrong_keyword)); -// } -// // Cancel the event -// e.setCancelled(true); -// // Set the event to false, because it got deactivated -// isChatEventActive = false; -// } private void mineAction(AsyncPlayerChatEvent e, Player p, String message) { @@ -2998,45 +2560,4 @@ private void rankAction(AsyncPlayerChatEvent e, Player p, String message) { isChatEventActive = false; } -// /** -// * Save the auto features, and then cancel the event and close the inventory. -// * -// * @param e -// * @param player -// */ -// private boolean saveAutoFeatures( InventoryClickEvent e, Player player ) { -// boolean success = AutoFeaturesWrapper.getInstance().getAutoFeaturesConfig().saveConf(); -// e.setCancelled(true); -// player.closeInventory(); -// return success; -// } -// -// -// private boolean saveConfigBlock(InventoryClickEvent e, Player p) { -// boolean success = saveAutoFeatures( e, p ); -// SpigotAutoBlockGUI gui = new SpigotAutoBlockGUI(p); -// gui.open(); -// return success; -// } -// -// private boolean saveConfigSmelt(InventoryClickEvent e, Player p) { -// boolean success = saveAutoFeatures( e, p ); -// SpigotAutoSmeltGUI gui = new SpigotAutoSmeltGUI(p); -// gui.open(); -// return success; -// } -// -// private boolean saveConfigPickup(InventoryClickEvent e, Player p) { -// boolean success = saveAutoFeatures( e, p ); -// SpigotAutoPickupGUI gui = new SpigotAutoPickupGUI(p); -// gui.open(); -// return success; -// } -// -// private boolean saveConfigAutoFeatures(InventoryClickEvent e, Player p) { -// boolean success = saveAutoFeatures( e, p ); -// SpigotAutoFeaturesGUI gui = new SpigotAutoFeaturesGUI(p); -// gui.open(); -// return success; -// } } 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 4ddb6322c..a9f7eb41c 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 @@ -49,8 +49,6 @@ public class SpigotGUIMenuTools private boolean useDisabledButtons; -// private String loreCommand; - private SpigotGUIMenuTools() { super(); @@ -66,8 +64,6 @@ private SpigotGUIMenuTools() { this.menuGoBack = XMaterial.BARRIER; -// this.menuStateOff1 = XMaterial.BLACK_STAINED_GLASS_PANE; -// this.menuStateOff2 = XMaterial.GRAY_STAINED_GLASS_PANE; } @@ -155,7 +151,6 @@ public GUIMenuPageData( int totalArraySize, int currentPage, String commandToRun posStart = (page - 1) * pageSize; posEnd = posStart + pageSize; -// posEnd = posStart + pageSize - 1; if ( posEnd > totalArraySize ) { posEnd = totalArraySize; @@ -305,29 +300,6 @@ public void setButtons( List