Compare commits

...
Author SHA1 Message Date
NotAlexNoyle 5d85028e81 Fix CoreProtect skull logging to use legacy-safe block API 2026-03-09 10:19:09 -04:00
NotAlexNoyle f40afbd4a4 Update GUI 2026-03-09 10:05:43 -04:00
NotAlexNoyle 5ae4b03d30 Formatting 2026-03-09 09:55:36 -04:00
NotAlexNoyle 543912b8a1 Merge pull request #12 from true-og/codex/fix-multiple-issues-in-bounty-plugin
Fix bounty GUI regressions and /bounty no-args behavior
2026-03-09 09:54:18 -04:00
NotAlexNoyle b1ca462de9 Fix bounty GUI regressions and command fallback behavior 2026-03-09 09:53:48 -04:00
NotAlexNoyle 1a47411f3b CoreProtect-OG rollback integration 2026-03-09 09:31:00 -04:00
NotAlexNoyle 7e193edd13 Merge pull request #11 from true-og/codex/use-coreprotect-api-for-head-metadata
Integrate CoreProtect logging for bounty head metadata
2026-03-09 09:13:46 -04:00
NotAlexNoyle c214807fdd Integrate CoreProtect logging for bounty head metadata 2026-03-09 09:13:34 -04:00
NotAlexNoyle c3e63a7475 Formatting 2026-03-09 09:07:15 -04:00
NotAlexNoyle bac11ea028 Merge pull request #10 from true-og/codex/implement-advanced-player-display-features
Use UUID-based heads, LuckPerms-formatted names, right-click actionbar, and explicit "Diamonds" labels
2026-03-09 09:04:55 -04:00
NotAlexNoyle c37165e2c5 Update bounty displays, LuckPerms formatting, and UUID head metadata 2026-03-09 09:04:05 -04:00
NotAlexNoyle ddc4f21868 Update formatting 2026-03-09 08:37:33 -04:00
NotAlexNoyle 7070e2cf38 Merge pull request #9 from true-og/codex/fix-chat-message-boldness-and-add-lore
Fix chat formatting bleed, 1.19.4 firework particle, and persistent bounty-head metadata
2026-03-09 08:14:12 -04:00
NotAlexNoyle 0560fdfd5d Fix chat formatting, fireworks particle fallback, and bounty head metadata 2026-03-09 08:13:49 -04:00
NotAlexNoyle 5726b86bd5 Fix string formatting 2026-03-09 08:03:29 -04:00
NotAlexNoyle aca097a8b1 Update formatting 2026-03-09 07:48:19 -04:00
NotAlexNoyle 193c614cc6 Merge pull request #8 from true-og/codex/implement-bounty-gui-enhancements
Use LuckPerms ranks in bounty GUI and add global celebration on claim
2026-03-09 07:43:03 -04:00
NotAlexNoyle 7dd394e5be Enhance bounty GUI ranks and claim celebrations 2026-03-09 07:42:48 -04:00
NotAlexNoyle 5525065d62 Merge pull request #7 from true-og/codex/update-bounty-handling-and-messaging
Support decimal bounties, use DiamondBank-OG shard conversions, and add behead broadcast
2026-03-09 07:35:58 -04:00
NotAlexNoyle 86b595a196 Support decimal bounty inputs and DiamondBank shard-based bounty messaging 2026-03-09 07:35:28 -04:00
NotAlexNoyle 8030220ffb Update GxUI-OG 2026-03-09 05:20:10 -04:00
NotAlexNoyle 2a7645effc Protect inventory items from player exploitation 2026-03-09 05:09:17 -04:00
NotAlexNoyle ff7e8156ff Update README.md 2026-03-09 04:59:32 -04:00
NotAlexNoyle 37e88c913c Merge pull request #6 from true-og/codex/add-configurable-player-head-drop-chance
Add configurable player head drop chance for bounty claims
2026-03-09 04:58:44 -04:00
NotAlexNoyle babfe91ef1 Add configurable bounty player head drop chance 2026-03-09 04:58:32 -04:00
NotAlexNoyle 2d10ab8eb6 Update formatting 2026-03-09 04:54:50 -04:00
NotAlexNoyle efa90b8101 Merge pull request #5 from true-og/codex/fix-item-extraction-bug-in-gui
Prevent taking placeholder items from bounty GUI
2026-03-09 04:52:52 -04:00
NotAlexNoyle eb41781b3c Suppress default death message during bounty claim 2026-03-09 04:52:33 -04:00
NotAlexNoyle 7cfda08d39 Prevent item extraction from bounty GUI 2026-03-09 04:52:10 -04:00
NotAlexNoyle a84b72071a Update GUI formatting 2026-03-09 04:47:59 -04:00
NotAlexNoyle 7cb97e7c1d Merge pull request #4 from true-og/codex/fix-stack-overflow-errors-in-plugin
Avoid recursive language defaults in LangUtil to prevent StackOverflow
2026-03-09 04:25:18 -04:00
NotAlexNoyle 6ca88c3265 Fix recursive language defaults causing StackOverflow 2026-03-09 04:25:04 -04:00
NotAlexNoyle b6fccfef5d Switch to Utilities-OG for messages 2026-03-09 04:19:47 -04:00
NotAlexNoyle ca7cf827d1 Merge pull request #3 from true-og/codex/fix-economy-integration-to-use-diamondbank-og
Initialize DiamondBank-OG hook and guard against null economy hook
2026-03-04 07:28:09 -05:00
NotAlexNoyle c6b059d4ec Fix economy hook initialization for DiamondBank integration 2026-03-04 07:27:32 -05:00
NotAlexNoyle f57245ccc3 Remove unused clans plugins 2026-03-04 07:20:21 -05:00
NotAlexNoyle a2dd3a03af Make DiamondBankAPI Not static 2026-03-02 06:08:40 -05:00
NotAlexNoyle e11c692ef0 Update DiamondBank-OG API 2026-03-02 05:51:21 -05:00
NotAlexNoyle 18a743ecf2 Vault -> DiamondBank Hard Fork 2026-02-25 05:04:33 -05:00
NotAlexNoyle a66a1123f2 Formatting 2026-02-11 13:34:21 -05:00
NotAlexNoyle b9887b5476 Merge pull request #2 from true-og/codex/complete-bounty-management-updates
Fix bounty set flow to charge contributors after bounty event validation
2026-02-11 03:57:25 +00:00
NotAlexNoyle 76ab7b9272 Fix bounty charge flow to occur after set event 2026-02-11 03:56:09 +00:00
NotAlexNoyle 0b1018a02c Pre codex milestone 2026-02-10 22:48:12 -05:00
NotAlexNoyle 8caaa7422e Merge pull request #1 from true-og/codex/fix-server-hang-in-bountydatamanager.java
Fix async bounty save locking
2026-02-09 12:46:55 +00:00
NotAlexNoyle aa51a7e174 Fix async bounty save locking 2026-02-09 12:46:24 +00:00
NotAlexNoyle e85f9f0289 Add breakpoint for ChatGPT 2026-02-09 07:37:19 -05:00
NotAlexNoyle 7e4b1c1d84 DiamondBank-OG API 2026-01-24 11:12:26 -05:00
NotAlexNoyle 5ae17b8437 Drop BetterTeams and Parties, Maven -> Gradle 2025-09-25 04:23:09 -04:00
TechnicallyCoded 6665796181 Add ClansPlus team hook (#25)
* Remove bundled ClansPlus jar

* Fix dep

* Fix java version syntax

* Fix shade
2025-09-14 18:43:45 +02:00
NotAlexNoyle 430e49f79e Use LGPLv3 license (#22) 2025-08-13 08:43:09 -04:00
65 changed files with 4976 additions and 1601 deletions

No files matched your search

+10
View File
@@ -8,6 +8,15 @@
# IntelliJ
out/
# Eclipse
.classpath
.project
.settings/
# Gradle
.gradle/
build/
# Compiled class file
*.class
@@ -29,6 +38,7 @@ out/
hs_err_pid*
*~
bin/
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
+9
View File
@@ -0,0 +1,9 @@
[submodule "libs/DiamondBank-OG"]
path = libs/DiamondBank-OG
url = https://github.com/true-og/DiamondBank-OG
[submodule "libs/Utilities-OG"]
path = libs/Utilities-OG
url = https://github.com/true-og/Utilities-OG
[submodule "libs/GxUI-OG"]
path = libs/GxUI-OG
url = https://github.com/true-og/GxUI-OG/
+165
View File
@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
+17 -14
View File
@@ -1,14 +1,17 @@
# PlayerBountiesPlus
# PlayerBounties-OG
## Overview
PlayerBountiesPlus lets players set and claim bounties while blocking teammates from claiming rewards. Hooks into Vault for economy handling and supports many team plugins.
PlayerBounties-OG is a hard fork of [PlayerBountiesPlus](https://github.com/TechnicallyCoded/PlayerBountiesPlus) that lets players set and claim bounties while blocking teammates from claiming rewards. Hooks into [DiamondBank-OG](https://github.com/true-og/DiamondBank-OG) for economy handling and supports [SimpleClans](https://github.com/true-og/SimpleClans). Built for Purpur 1.19.4.
## Features
- Clan-aware bounty system that prevents teammates from claiming each other's bounties
- Integrates with Vault and supports ClansLite, Parties, BetterTeams, SimpleClans and Towny for team detection
- Inventory GUI for viewing bounties
- PlaceholderAPI support for custom placeholders
- Localized messages in multiple languages
- Clan-aware bounty system that prevents teammates from claiming each other's bounties.
- Inventory GUI for viewing bounties.
- Customizable odds for receiving player head from bounty victim.
- Localized messages in multiple languages.
- Integrates [CoreProtect-OG](https://github.com/true-og/CoreProtect-OG) for player head rollback injection.
- Integrates [DiamondBank-OG](https://github.com/true-og/DiamondBank-OG) for currency.
- Integrates [LuckPerms](https://github.com/true-og/LuckPerms) for player name and rank formatting.
- Integrates [SimpleClans](https://github.com/true-og/SimpleClans) for team detection.
## Commands
- `/bounty set <player> <amount>` – set a bounty on a player
@@ -17,8 +20,8 @@ PlayerBountiesPlus lets players set and claim bounties while blocking teammates
- `/pbp reload` – reload configuration and messages
- `/pbp version` – display plugin version
- `/pbp bounty set <player> <amount>` – admin set a bounty
- `/pbp bounty add <player> <amount>` – add to a bounty
- `/pbp bounty remove <player> <amount>` – remove from a bounty
- `/pbp bounty add <player> <amount>` – add diamonds to a bounty
- `/pbp bounty remove <player> <amount>` – remove diamonds from a bounty
- `/pbp bounty delete <player>` – delete a bounty
- `/pbp bounty get <player>` – view a bounty
@@ -38,9 +41,9 @@ PlayerBountiesPlus lets players set and claim bounties while blocking teammates
| `playerbountiesplus.command.admin.bounty.get` | op |
## Developer Notes
- Commands reside in `com.tcoded.playerbountiesplus.command` with subpackages for bounty and admin actions
- Event listeners like `DeathListener` handle bounty claim logic
- Hooks under `com.tcoded.playerbountiesplus.hook` integrate with Vault, PlaceholderAPI and team plugins
- Inventory GUIs in `com.tcoded.playerbountiesplus.gui` present bounty data
- `BountyDataManager` manages persistence of bounties
- Commands reside in `com.tcoded.playerbountiesplus.command` with subpackages for bounty and admin actions.
- Event listeners like `DeathListener` handle bounty claim logic.
- Hooks under `com.tcoded.playerbountiesplus.hook` integrate with DiamondBank-OG and SimpleClans.
- Inventory GUIs in `com.tcoded.playerbountiesplus.gui` present bounty data.
- `BountyDataManager` manages persistence of bounties.
Executable
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/bash
# Fetch all submodule content.
git submodule update --force --recursive --init
+150
View File
@@ -0,0 +1,150 @@
/* This is free and unencumbered software released into the public domain */
/* ------------------------------ Plugins ------------------------------ */
plugins {
id("java") // Import Java plugin.
id("java-library") // Import Java Library plugin.
id("com.diffplug.spotless") version "8.1.0" // Import Spotless plugin.
id("com.gradleup.shadow") version "8.3.9" // Import Shadow plugin.
id("checkstyle") // Import Checkstyle plugin.
eclipse // Import Eclipse plugin.
kotlin("jvm") version "2.1.21" // Import Kotlin JVM plugin.
}
extra["kotlinAttribute"] = Attribute.of("kotlin-tag", Boolean::class.javaObjectType)
val kotlinAttribute: Attribute<Boolean> by rootProject.extra
/* --------------------------- JDK / Kotlin ---------------------------- */
java {
sourceCompatibility = JavaVersion.VERSION_17 // Compile with JDK 17 compatibility.
toolchain { // Select Java toolchain.
languageVersion.set(JavaLanguageVersion.of(17)) // Use JDK 17.
vendor.set(JvmVendorSpec.GRAAL_VM) // Use GraalVM CE.
}
}
kotlin { jvmToolchain(17) }
/* ----------------------------- Metadata ------------------------------ */
group = "com.tcoded" // Declare bundle identifier.
version = "1.0" // Declare plugin version (will be in .jar).
val apiVersion = "1.19" // Declare minecraft server target version.
/* ----------------------------- Resources ----------------------------- */
tasks.named<ProcessResources>("processResources") {
val props = mapOf("version" to version, "apiVersion" to apiVersion)
inputs.properties(props) // Indicates to rerun if version changes.
filesMatching("plugin.yml") { expand(props) }
from("LICENSE") { into("/") } // Bundle licenses into jarfiles.
}
/* ---------------------------- Repos ---------------------------------- */
repositories {
mavenCentral() // Import the Maven Central Maven Repository.
gradlePluginPortal() // Import the Gradle Plugin Portal Maven Repository.
maven { url = uri("https://repo.purpurmc.org/snapshots") } // Import the PurpurMC Maven Repository.
maven { url = uri("https://repo.codemc.io/repository/maven-releases/") }
maven { url = uri("https://repo.codemc.io/repository/maven-snapshots/") }
maven { url = uri("file://${System.getProperty("user.home")}/.m2/repository") }
System.getProperty("SELF_MAVEN_LOCAL_REPO")?.let { // TrueOG Bootstrap mavenLocal().
val dir = file(it)
if (dir.isDirectory) {
println("Using SELF_MAVEN_LOCAL_REPO at: $it")
maven { url = uri("file://${dir.absolutePath}") }
} else {
logger.error("TrueOG Bootstrap not found, defaulting to ~/.m2 for mavenLocal()")
mavenLocal()
}
} ?: logger.error("TrueOG Bootstrap not found, defaulting to ~/.m2 for mavenLocal()")
maven { url = uri("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") }
maven { url = uri("https://oss.sonatype.org/content/groups/public/") }
maven { url = uri("https://jitpack.io") }
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
maven { url = uri("https://repo.glaremasters.me/repository/towny/") }
maven { url = uri("https://repo.extendedclip.com/releases/") }
maven { url = uri("https://repo.tcoded.com/public/") }
maven { url = uri("https://maven.playpro.com") }
}
/* ---------------------- Java project deps ---------------------------- */
dependencies {
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT") // Declare Purpur API version to be packaged.
compileOnly("net.sacredlabyrinth.phaed.simpleclans:SimpleClans:2.15.2")
compileOnly("net.luckperms:api:5.5") // Import LuckPerms API.
compileOnly("net.coreprotect:coreprotect:23.1")
compileOnlyApi(project(":libs:Utilities-OG")) // Import TrueOG Network Utilities-OG Java API (from source).
compileOnlyApi(project(":libs:GxUI-OG")) // Import TrueOG Network GxUI-OG Java API (from source).
compileOnlyApi(project(":libs:DiamondBank-OG")) {
attributes { attribute(kotlinAttribute, true) }
} // Import TrueOG network DiamondBank-OG Kotlin API (from source).
}
apply(from = "eclipse.gradle.kts") // Import eclipse classpath support script.
/* ---------------------- Reproducible jars ---------------------------- */
tasks.withType<AbstractArchiveTask>().configureEach { // Ensure reproducible .jars
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
/* ----------------------------- Shadow -------------------------------- */
tasks.shadowJar {
exclude("io.github.miniplaceholders.*") // Exclude the MiniPlaceholders package from being shadowed.
isEnableRelocation = true
relocationPrefix = "${project.group}.shadow"
archiveClassifier.set("") // Use empty string instead of null.
minimize()
}
tasks.jar { archiveClassifier.set("part") } // Applies to root jarfile only.
tasks.build { dependsOn(tasks.spotlessApply, tasks.shadowJar) } // Build depends on spotless and shadow.
/* --------------------------- Javac opts ------------------------------- */
tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-parameters") // Enable reflection for java code.
options.isFork = true // Run javac in its own process.
options.compilerArgs.add("-Xlint:deprecation") // Trigger deprecation warning messages.
options.encoding = "UTF-8" // Use UTF-8 file encoding.
}
/* ----------------------------- Auto Formatting ------------------------ */
spotless {
java {
eclipse().configFile("config/formatter/eclipse-java-formatter.xml") // Eclipse java formatting.
leadingTabsToSpaces() // Convert leftover leading tabs to spaces.
removeUnusedImports() // Remove imports that aren't being called.
}
kotlinGradle {
ktfmt().kotlinlangStyle().configure { it.setMaxWidth(120) } // JetBrains Kotlin formatting.
target("build.gradle.kts", "settings.gradle.kts") // Gradle files to format.
}
}
checkstyle {
toolVersion = "10.18.1" // Declare checkstyle version to use.
configFile = file("config/checkstyle/checkstyle.xml") // Point checkstyle to config file.
isIgnoreFailures = true // Don't fail the build if checkstyle does not pass.
isShowViolations = true // Show the violations in any IDE with the checkstyle plugin.
}
tasks.named("compileJava") {
dependsOn("spotlessApply") // Run spotless before compiling with the JDK.
}
tasks.named("spotlessCheck") {
dependsOn("spotlessApply") // Run spotless before checking if spotless ran.
}
/* ------------------------------ Eclipse SHIM ------------------------- */
// This can't be put in eclipse.gradle.kts because Gradle is weird.
subprojects {
apply(plugin = "java-library")
apply(plugin = "eclipse")
eclipse.project.name = "${project.name}-${rootProject.name}"
tasks.withType<Jar>().configureEach { archiveBaseName.set("${project.name}-${rootProject.name}") }
}
+34
View File
@@ -0,0 +1,34 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
<property name="severity" value="error"/>
</module>
<module name="TreeWalker">
<module name="FinalLocalVariable"/>
<module name="AvoidStarImport"/>
<module name="Indentation">
<property name="severity" value="ignore"/>
</module>
</module>
<module name="RegexpSingleline">
<property name="format" value="\borg\.junit\.jupiter\.api\.Assertions\.fail\s*\(\s*&quot;Not yet implemented&quot;\s*\)\s*;"/>
<property name="message" value="Remove placeholder fail() and implement the test."/>
<property name="ignoreCase" value="true"/>
<property name="severity" value="warning"/>
</module>
<module name="RegexpSingleline">
<property name="format" value="(?&lt;!\w)fail\s*\(\s*&quot;Not yet implemented&quot;\s*\)\s*;"/>
<property name="message" value="Remove placeholder fail() and implement the test."/>
<property name="severity" value="warning"/>
</module>
</module>
+404
View File
@@ -0,0 +1,404 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="23">
<profile kind="CodeFormatterProfile" name="TrueOG Network Formatting" version="23">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.javadoc_do_not_separate_block_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case_after_arrow" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.align_arrows_in_switch_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow" value="20"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>
+151
View File
@@ -0,0 +1,151 @@
/* This is free and unencumbered software released into the public domain */
import org.gradle.plugins.ide.eclipse.model.EclipseModel
import java.nio.file.Files
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.OutputKeys
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
val kotlinAttribute: Attribute<Boolean> by rootProject.extra
val kotlinPluginProjects = configurations
.getByName("compileClasspath")
.allDependencies
.filterIsInstance<ProjectDependency>()
.filter { it -> it.attributes.getAttribute(kotlinAttribute) != null }
.map { it.path }
kotlinPluginProjects.forEach { evaluationDependsOn(it) }
val ideLibs: Configuration by
configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
}
configure<EclipseModel> {
project {
name = "PlayerBounties-OG-Plugin"
}
classpath {
plusConfigurations.add(ideLibs)
}
}
val ideLibDir = layout.buildDirectory.dir("ide-libs")
val hashRegex = Regex("-[0-9a-fA-F]{10}(?=\\.jar$)") // Black magic.
val copyTasks = mutableListOf<TaskProvider<Copy>>()
kotlinPluginProjects.forEach { path ->
val sub = project(path)
val shadowJarProv = sub.tasks.named("shadowJar")
val copyTask =
tasks.register<Copy>("ideCopy${sub.name.replaceFirstChar(Char::titlecase)}") {
dependsOn(shadowJarProv)
from(shadowJarProv)
into(ideLibDir)
rename { it.replace(hashRegex, "") } // Remove git commit hash from jarfile.
}
copyTasks += copyTask
}
/* Ensure the jars exist before .classpath is generated */
tasks.named("eclipseClasspath").configure { dependsOn(copyTasks) }
/* Supply those jars to the ideLibs configuration (after evaluation) */
afterEvaluate { dependencies { add("ideLibs", fileTree(ideLibDir) { include("*.jar") }) } }
val injectIdeLibs =
tasks.register("injectIdeLibs") {
dependsOn("eclipse") // run after all eclipse files are generated
doLast {
val cpFile = file(".classpath")
if (!cpFile.exists()) return@doLast
val jars = fileTree(ideLibDir.get()) { include("*.jar") }.files.sortedBy { it.name }
if (jars.isEmpty()) return@doLast
// Parse DOM
val dbf = DocumentBuilderFactory.newInstance()
val doc = dbf.newDocumentBuilder().parse(cpFile)
val root = doc.documentElement
// Helper to see if an entry already exists
fun exists(path: String): Boolean =
root.getElementsByTagName("classpathentry").let { list ->
(0 until list.length).any { i ->
val n = list.item(i)
val kind = n.attributes?.getNamedItem("kind")?.nodeValue
val p = n.attributes?.getNamedItem("path")?.nodeValue
kind == "lib" && p == path
}
}
// Remove any entry that points to ide-libs dir (folder or jars) to avoid dupes
val toRemove = mutableListOf<org.w3c.dom.Node>()
val list = root.getElementsByTagName("classpathentry")
val dirPath = ideLibDir.get().asFile.absolutePath
for (i in 0 until list.length) {
val n = list.item(i)
val kind = n.attributes?.getNamedItem("kind")?.nodeValue
val p = n.attributes?.getNamedItem("path")?.nodeValue ?: ""
if (kind == "lib" && (p == dirPath || p.startsWith("$dirPath/"))) {
toRemove += n
}
}
toRemove.forEach { root.removeChild(it) }
// Append our jar entries LAST
jars.forEach { f ->
val abs = f.absolutePath
if (!exists(abs)) {
val entry = doc.createElement("classpathentry")
entry.setAttribute("kind", "lib")
entry.setAttribute("path", abs)
root.appendChild(entry)
}
}
// Write back pretty
val tf =
TransformerFactory.newInstance().newTransformer().apply {
setOutputProperty(OutputKeys.INDENT, "yes")
setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "1")
setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no")
setOutputProperty(OutputKeys.ENCODING, "UTF-8")
}
Files.newBufferedWriter(cpFile.toPath()).use { w -> tf.transform(DOMSource(doc), StreamResult(w)) }
}
}
tasks.named("eclipse").configure { finalizedBy(injectIdeLibs) }
val eclipseModel = extensions.getByType<EclipseModel>()
fun Project.addResolvableEclipseConfigs() {
val jarAttr =
objects.named(org.gradle.api.attributes.LibraryElements::class, org.gradle.api.attributes.LibraryElements.JAR)
val apiAttr = objects.named(org.gradle.api.attributes.Usage::class, org.gradle.api.attributes.Usage.JAVA_API)
val compileOnlyRes =
configurations.create("eclipseCompileOnly") {
extendsFrom(configurations.getByName("compileOnly"))
isCanBeResolved = true
isCanBeConsumed = false
attributes.attribute(org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE, apiAttr)
attributes.attribute(org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, jarAttr)
}
val compileOnlyApiRes =
configurations.create("eclipseCompileOnlyApi") {
extendsFrom(configurations.getByName("compileOnlyApi"))
isCanBeResolved = true
isCanBeConsumed = false
attributes.attribute(org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE, apiAttr)
attributes.attribute(org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, jarAttr)
}
eclipseModel.classpath.plusConfigurations.addAll(listOf(compileOnlyRes, compileOnlyApiRes))
}
addResolvableEclipseConfigs()
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Executable
+251
View File
@@ -0,0 +1,251 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
+94
View File
@@ -0,0 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
-2
View File
@@ -1,2 +0,0 @@
jdk:
- openjdk17
Binary file not shown.
Submodule libs/DiamondBank-OG added at ec4a71782b.
Submodule
+1
Submodule libs/GxUI-OG added at cbcf14f0ab.
+1
Submodule libs/Utilities-OG added at 3705eafbc3.
-183
View File
@@ -1,183 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tcoded</groupId>
<artifactId>PlayerBountiesPlus</artifactId>
<version>1.4.17</version>
<packaging>jar</packaging>
<name>PlayerBountiesPlus</name>
<description>Claim bounties only if you are not on the same clan</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<url>https://tcoded.com</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<relocations>
<relocation>
<pattern>com.tcoded.folialib</pattern>
<shadedPattern>com.tcoded.playerbountiesplus.lib.folialib</shadedPattern>
</relocation>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>com.tcoded.playerbountiesplus.lib.bstats</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<repositories>
<repository>
<id>spigotmc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.org/repository/maven-public</url>
</repository>
<repository>
<id>glaremasters repo</id>
<url>https://repo.glaremasters.me/repository/towny/</url>
</repository>
<repository>
<id>placeholderapi</id>
<url>https://repo.extendedclip.com/releases/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.19.3-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>23.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.CraptiCraft-Development</groupId>
<artifactId>ClansLite-API</artifactId>
<version>1.4.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.TechnicallyCoded</groupId>
<artifactId>FoliaLib</artifactId>
<version>0.4.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.alessiodp.parties</groupId>
<artifactId>parties-api</artifactId>
<version>3.2.9</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/parties-api-3.2.9.jar</systemPath>
</dependency>
<dependency>
<groupId>com.github.lightlibs</groupId>
<artifactId>LegacyColorCodeParser</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.LightLibs</groupId>
<artifactId>SpigotUpdateChecker</artifactId>
<version>1.1.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.booksaw</groupId>
<artifactId>BetterTeams</artifactId>
<version>4.8.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.sacredlabyrinth.phaed.simpleclans</groupId>
<artifactId>SimpleClans</artifactId>
<version>2.15.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.SaberLLC</groupId>
<artifactId>Saber-Factions</artifactId>
<version>4.1.4-STABLE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.palmergames.bukkit.towny</groupId>
<artifactId>towny</artifactId>
<version>0.100.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
+13
View File
@@ -0,0 +1,13 @@
rootProject.name = "PlayerBounties-OG"
ProcessBuilder("sh", "bootstrap.sh").directory(rootDir).inheritIO().start().let {
if (it.waitFor() != 0) throw GradleException("bootstrap.sh failed")
}
file("libs")
.listFiles()
?.filter { it.isDirectory && !it.name.startsWith(".") }
?.forEach { dir ->
include(":libs:${dir.name}")
project(":libs:${dir.name}").projectDir = dir
}
@@ -0,0 +1,321 @@
package com.tcoded.playerbountiesplus;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.event.HandlerList;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.ServicesManager;
import org.bukkit.plugin.java.JavaPlugin;
import com.google.common.collect.ImmutableList;
import com.tcoded.playerbountiesplus.command.BountyCommand;
import com.tcoded.playerbountiesplus.command.PlayerBountiesPlusAdminCmd;
import com.tcoded.playerbountiesplus.hook.currency.DiamondBankOGHook;
import com.tcoded.playerbountiesplus.hook.logging.CoreProtectHook;
import com.tcoded.playerbountiesplus.hook.currency.EconomyHook;
import com.tcoded.playerbountiesplus.hook.team.TeamHook;
import com.tcoded.playerbountiesplus.listener.BountyHeadListener;
import com.tcoded.playerbountiesplus.listener.DeathListener;
import com.tcoded.playerbountiesplus.listener.GuiProtectionListener;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import com.tcoded.playerbountiesplus.util.LangUtil;
import net.luckperms.api.LuckPerms;
import net.trueog.diamondbankog.api.DiamondBankAPIJava;
import net.trueog.utilitiesog.UtilitiesOG;
public final class PlayerBountiesOG extends JavaPlugin {
// Plugin instance declaration.
private static PlayerBountiesOG instance;
public static PlayerBountiesOG getInstance() {
return instance;
}
public static String getPrefix() {
return "&7[&cPlayerBounties&f-&4OG&7] ";
}
// Utilities.
private LangUtil langUtil;
// Managers.
private BountyDataManager bountyDataManager;
// Hooks.
private EconomyHook ecoHook;
private TeamHook teamHook;
// DiamondBank-OG Economy.
private DiamondBankAPIJava diamondBankAPI;
// LuckPerms API hook.
private LuckPerms luckPerms;
// CoreProtect API hook.
private CoreProtectHook coreProtectHook;
public PlayerBountiesOG() {
instance = this;
}
@Override
public void onEnable() {
// Config
saveDefaultConfig();
// Initialize the LuckPerms API.
final RegisteredServiceProvider<LuckPerms> luckPermsProvider = getServer().getServicesManager()
.getRegistration(LuckPerms.class);
if (luckPermsProvider != null) {
this.luckPerms = luckPermsProvider.getProvider();
} else {
getLogger().warning(
"LuckPerms not found – bounty claim announcements will not include rank colors or prefixes.");
}
this.coreProtectHook = new CoreProtectHook(this);
if (!this.coreProtectHook.isEnabled()) {
getLogger().warning(
"CoreProtect API v11+ not found - custom bounty head metadata may not rollback correctly.");
}
// Initialize the DiamondBank-OG API.
final RegisteredServiceProvider<DiamondBankAPIJava> provider = getServer().getServicesManager()
.getRegistration(DiamondBankAPIJava.class);
// If the DiamondBank-OG API failed to initialize, do this...
if (provider == null) {
// Tell Bukkit to disable this plugin, and inform the console.
disableSelf("DiamondBank-OG API is null – disabling " + getPluginMeta().getName() + "!");
return;
}
// Assign the active instance of DiamondBank-OG to the API handler.
this.diamondBankAPI = provider.getProvider();
// Utils.
this.reloadLang();
// Managers.
this.bountyDataManager = new BountyDataManager(this);
this.bountyDataManager.init();
// Economy Hooks.
registerDefaultEcoHooks();
// Team Hooks.
this.teamHook = TeamHook.findTeamHook(this);
if (this.teamHook == null) {
getLogger().warning(
"There is no supported team/clan/party plugin on the server! Feel free to request support for the plugin you use on GitHub or Discord!");
}
// Commands.
final PluginCommand bountyCmd = this.getCommand("bounty");
if (bountyCmd != null) {
final BountyCommand bountyExec = new BountyCommand(this, diamondBankAPI);
bountyCmd.setExecutor(bountyExec);
bountyCmd.setTabCompleter(bountyExec);
}
final PluginCommand adminCmd = this.getCommand("playerbountiesplusadmin");
if (adminCmd != null) {
final PlayerBountiesPlusAdminCmd adminExec = new PlayerBountiesPlusAdminCmd(this);
adminCmd.setExecutor(adminExec);
adminCmd.setTabCompleter(adminExec);
}
// Listeners.
this.getServer().getPluginManager().registerEvents(new DeathListener(this, this.diamondBankAPI, this.luckPerms),
this);
this.getServer().getPluginManager().registerEvents(
new BountyHeadListener(this, this.diamondBankAPI, this.luckPerms, this.coreProtectHook), this);
this.getServer().getPluginManager().registerEvents(new GuiProtectionListener(this), this);
final List<Plugin> plugins = ImmutableList.copyOf(this.getServer().getPluginManager().getPlugins());
findPluginWithQuery(plugins, "team");
findPluginWithQuery(plugins, "teams");
findPluginWithQuery(plugins, "clan");
findPluginWithQuery(plugins, "clans");
findPluginWithQuery(plugins, "party", "voteparty");
findPluginWithQuery(plugins, "parties");
findPluginWithQuery(plugins, "guild");
findPluginWithQuery(plugins, "guilds");
}
public void reloadLang() {
this.langUtil = new LangUtil(this, StringUtils.lowerCase(this.getConfig().getString("lang", "en_us")));
}
@Override
public void onDisable() {
HandlerList.unregisterAll(this);
UtilitiesOG.logToConsole(getPrefix(), "PlayerBounties-OG has been shut down successfully!");
}
public EconomyHook getEcoHook() {
if (this.ecoHook == null) {
throw new IllegalStateException("Economy hook is not initialized. DiamondBank-OG may be unavailable.");
}
return this.ecoHook;
}
public TeamHook getTeamHook() {
return teamHook;
}
public BountyDataManager getBountyDataManager() {
return bountyDataManager;
}
public LangUtil getLang() {
return this.langUtil;
}
public LuckPerms getLuckPerms() {
return this.luckPerms;
}
public CoreProtectHook getCoreProtectHook() {
return this.coreProtectHook;
}
// Utilities.
private static void findPluginWithQuery(List<Plugin> plugins, String pluginNameQuery, String... excludeStrings) {
final String firstPluginFound = plugins.stream().filter(p -> {
final String lowerName = StringUtils.lowerCase(p.getName());
// If the plugin name doesn't contain the query, skip.
if (!StringUtils.contains(lowerName, pluginNameQuery)) {
return false;
}
// If the plugin name contains any of the exclude strings, skip.
for (String excludeString : excludeStrings) {
if (StringUtils.contains(lowerName, excludeString)) {
return false;
}
}
return true;
}).findFirst().map(p -> {
final List<String> authors = p.getPluginMeta().getAuthors();
return p.getName() + " (" + (authors.isEmpty() ? "N/A" : authors.get(0)) + ")";
}).orElse(null);
if (firstPluginFound == null) {
return;
}
}
private void registerDefaultEcoHooks() {
final ServicesManager servicesManager = getServer().getServicesManager();
// De-register old hook.
servicesManager.unregisterAll(this);
// Initialize the DiamondBank-OG hook with the active plugin instance.
final DiamondBankOGHook diamondBankOGHook = new DiamondBankOGHook(getInstance(), diamondBankAPI);
// Set DiamondBank-OG as the active economy implementation used by
// commands/listeners.
this.ecoHook = diamondBankOGHook;
// Register the DiamondBank-OG hook as the active economy hook.
servicesManager.register(EconomyHook.class, diamondBankOGHook, this, ServicePriority.Low);
}
// Helps this plugin kill itself gracefully (in minecraft).
public static void disableSelf(String reason) {
// Run a meta-task on the Bukkit server outside of the context of this plugin.
Bukkit.getScheduler().runTask(Bukkit.getServer().getPluginManager().getPlugin("PlayerBounties-OG"), () -> {
// Attempt to fetch the active instance of this plugin.
final PlayerBountiesOG pluginInstance = getInstance();
// If this plugin is already disabled, do this...
if (!pluginInstance.isEnabled()) {
// Do nothing, task already completed.
return;
}
// Inform console of this plugin being disabled.
UtilitiesOG.logToConsole(getPrefix(), reason);
// Commit sudoku.
Bukkit.getPluginManager().disablePlugin(pluginInstance);
});
}
}
@@ -1,224 +0,0 @@
package com.tcoded.playerbountiesplus;
import com.google.common.collect.ImmutableList;
import com.tcoded.folialib.FoliaLib;
import com.tcoded.lightlibs.updatechecker.SimpleUpdateChecker;
import com.tcoded.playerbountiesplus.command.BountyCommand;
import com.tcoded.playerbountiesplus.command.PlayerBountiesPlusAdminCmd;
import com.tcoded.playerbountiesplus.hook.currency.EconomyHook;
import com.tcoded.playerbountiesplus.hook.currency.DummyEcoHook;
import com.tcoded.playerbountiesplus.hook.currency.VaultHook;
import com.tcoded.playerbountiesplus.hook.placeholder.PlaceholderHook;
import com.tcoded.playerbountiesplus.hook.team.AbstractTeamHook;
import com.tcoded.playerbountiesplus.hook.team.TeamHook;
import com.tcoded.playerbountiesplus.listener.DeathListener;
import com.tcoded.playerbountiesplus.listener.GuiListener;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import com.tcoded.playerbountiesplus.util.LangUtil;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.ChatColor;
import org.bukkit.command.PluginCommand;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.HandlerList;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.ServicesManager;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.List;
public final class PlayerBountiesPlus extends JavaPlugin {
// Instance
private static PlayerBountiesPlus instance;
public static PlayerBountiesPlus getInstance() {
return instance;
}
// Utils
private FoliaLib foliaLib;
private LangUtil langUtil;
// Managers
private BountyDataManager bountyDataManager;
// Hooks
private EconomyHook ecoHook;
private TeamHook teamHook;
private PlaceholderHook placeholderHook;
public PlayerBountiesPlus() {
instance = this;
}
@Override
public void onEnable() {
// Config
saveDefaultConfig();
FileConfiguration config = this.getConfig();
// Utils
this.foliaLib = new FoliaLib(this);
this.reloadLang();
// Managers
this.bountyDataManager = new BountyDataManager(this);
this.bountyDataManager.init();
// Economy Hooks
registerDefaultEcoHooks();
if (!applyEcoHookRegistration()) return;
// Team Hooks
this.teamHook = TeamHook.findTeamHook(this);
if (this.teamHook == null) {
getLogger().warning("There is no supported team/clan/party plugin on the server! Feel free to request support for the plugin you use on GitHub or Discord!");
}
// Placeholder Hooks
this.placeholderHook = PlaceholderHook.findPlaceholderHook(this);
this.placeholderHook.enable();
// Commands
PluginCommand bountyCmd = this.getCommand("bounty");
if (bountyCmd != null) {
BountyCommand bountyExec = new BountyCommand(this);
bountyCmd.setExecutor(bountyExec);
bountyCmd.setTabCompleter(bountyExec);
}
PluginCommand adminCmd = this.getCommand("playerbountiesplusadmin");
if (adminCmd != null) {
PlayerBountiesPlusAdminCmd adminExec = new PlayerBountiesPlusAdminCmd(this);
adminCmd.setExecutor(adminExec);
adminCmd.setTabCompleter(adminExec);
}
// Listeners
this.getServer().getPluginManager().registerEvents(new DeathListener(this), this);
this.getServer().getPluginManager().registerEvents(new GuiListener(), this);
// Update checker
checkUpdate();
// bStats
Metrics metrics = new Metrics(this, 19617);
metrics.addCustomChart(new SimplePie("config_lang", () -> langUtil.getLang()));
metrics.addCustomChart(new SimplePie("datafolder_customlang", () -> Boolean.toString(langUtil.isCustomLang())));
metrics.addCustomChart(new SimplePie("hook_teamhook", () -> teamHook == null ? "None" : teamHook.getPluginName() + " (" + teamHook.getAuthor() + ")"));
metrics.addCustomChart(new SimplePie("server_isfolia", () -> Boolean.toString(foliaLib.isFolia())));
List<Plugin> plugins = ImmutableList.copyOf(this.getServer().getPluginManager().getPlugins());
findPluginWithQuery(plugins, metrics, "team");
findPluginWithQuery(plugins, metrics, "teams");
findPluginWithQuery(plugins, metrics, "clan");
findPluginWithQuery(plugins, metrics, "clans");
findPluginWithQuery(plugins, metrics, "party", "voteparty");
findPluginWithQuery(plugins, metrics, "parties");
findPluginWithQuery(plugins, metrics, "guild");
findPluginWithQuery(plugins, metrics, "guilds");
}
public void reloadLang() {
this.langUtil = new LangUtil(this, this.getConfig().getString("lang", "en_us").toLowerCase());
}
public void checkUpdate() {
SimpleUpdateChecker.checkUpdate(
this,
ChatColor.translateAlternateColorCodes('&', "&f[&bPlayerBountiesPlus&f] "),
108637,
runnable -> this.getFoliaLib().getScheduler().runAsync(wt -> runnable.run())
);
}
@Override
public void onDisable() {
HandlerList.unregisterAll(this);
this.placeholderHook.disable();
}
public EconomyHook getEcoHook() {
return this.ecoHook;
}
public TeamHook getTeamHook() {
return teamHook;
}
public PlaceholderHook getPlaceholderHook() {
return placeholderHook;
}
public BountyDataManager getBountyDataManager() {
return bountyDataManager;
}
public FoliaLib getFoliaLib() {
return this.foliaLib;
}
public LangUtil getLang() {
return this.langUtil;
}
// Utils
private static void findPluginWithQuery(List<Plugin> plugins, Metrics metrics, String pluginNameQuery, String... excludeStrings) {
String firstPluginFound = plugins.stream()
.filter(p -> {
String lowerName = p.getName().toLowerCase();
// If the plugin name doesn't contain the query, skip
if (!lowerName.contains(pluginNameQuery)) return false;
// If the plugin name contains any of the exclude strings, skip
for (String excludeString : excludeStrings) {
if (lowerName.contains(excludeString)) return false;
}
return true;
})
.findFirst()
.map(p -> {
List<String> authors = p.getDescription().getAuthors();
return p.getName() + " (" + (authors.isEmpty() ? "N/A" : authors.get(0)) + ")";
}).orElse(null);
if (firstPluginFound == null) return;
metrics.addCustomChart(new SimplePie("plugins_query_" + pluginNameQuery, () -> firstPluginFound));
}
private void registerDefaultEcoHooks() {
ServicesManager servicesManager = getServer().getServicesManager();
// Unregister old eco hooks
servicesManager.unregisterAll(this);
// Register vault economy hook
VaultHook vaultEcoHook = new VaultHook(this);
boolean ecoPresent = vaultEcoHook.init();
// Register or fallback
if (ecoPresent) servicesManager.register(EconomyHook.class, vaultEcoHook, this, ServicePriority.Low);
else servicesManager.register(EconomyHook.class, new DummyEcoHook(), this, ServicePriority.Lowest);
}
public boolean applyEcoHookRegistration() {
// Get economy hook
ServicesManager servicesManager = getServer().getServicesManager();
RegisteredServiceProvider<EconomyHook> ecoHookProvider = servicesManager.getRegistration(EconomyHook.class);
if (ecoHookProvider == null) {
getLogger().severe("No economy hook is present! Aborting startup!");
return false;
}
String hookName = ecoHookProvider.getProvider().getClass().getSimpleName();
String hookPluginName = ecoHookProvider.getPlugin().getName();
getLogger().info("Using economy hook: " + hookName + " from plugin: " + hookPluginName);
this.ecoHook = ecoHookProvider.getProvider();
return true;
}
}
@@ -1,78 +1,130 @@
package com.tcoded.playerbountiesplus.command;
import com.google.common.collect.Lists;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.command.bounty.BountyCheckCmd;
import com.tcoded.playerbountiesplus.command.bounty.BountySetCmd;
import com.tcoded.playerbountiesplus.command.bounty.BountyTopCmd;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.Lists;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.command.bounty.BountyCheckCmd;
import com.tcoded.playerbountiesplus.command.bounty.BountySetCmd;
import com.tcoded.playerbountiesplus.command.bounty.BountyTopCmd;
import net.trueog.diamondbankog.api.DiamondBankAPIJava;
import net.trueog.utilitiesog.UtilitiesOG;
public class BountyCommand implements CommandExecutor, TabCompleter {
private PlayerBountiesPlus plugin;
private final PlayerBountiesOG plugin;
private final DiamondBankAPIJava diamondBankAPI;
public BountyCommand(PlayerBountiesOG plugin, DiamondBankAPIJava diamondBankAPI) {
public BountyCommand(PlayerBountiesPlus plugin) {
this.plugin = plugin;
this.diamondBankAPI = diamondBankAPI;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String cmdName, String[] args) {
if (args.length < 1) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.no-action"));
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), "&cERROR: Only players can use this command.");
return true;
}
String action = args[0].toLowerCase();
if (args.length < 1) {
if (StringUtils.equalsIgnoreCase(cmdName, "bounties")) {
return BountyTopCmd.handleCmd(plugin, diamondBankAPI, sender, cmd, cmdName, args);
}
final String noAction = plugin.getLang().getColored("command.bounty.no-action");
UtilitiesOG.trueogMessage((Player) sender, noAction);
return true;
}
final String action = StringUtils.lowerCase(args[0]);
switch (action) {
case "set":
case "set" -> {
return BountySetCmd.handleCmd(plugin, sender, cmd, cmdName, args);
case "top":
return BountyTopCmd.handleCmd(plugin, sender, cmd, cmdName, args);
case "check":
}
case "top" -> {
return BountyTopCmd.handleCmd(plugin, diamondBankAPI, sender, cmd, cmdName, args);
}
case "check" -> {
return BountyCheckCmd.handleCmd(plugin, sender, cmd, cmdName, args);
default:
sender.sendMessage(plugin.getLang().getColored("command.bounty.invalid-action"));
}
default -> {
// If "/bounty" is run without a valid subcommand, treat it as "/bounty top".
return BountyTopCmd.handleCmd(plugin, diamondBankAPI, sender, cmd, cmdName, args);
}
}
return true;
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args)
{
if (args.length == 1) {
return Lists.newArrayList("set", "top", "check").stream()
.filter(action -> action.startsWith(args[0].toLowerCase()))
.filter(action -> StringUtils.startsWith(action, StringUtils.lowerCase(args[0])))
.collect(Collectors.toList());
} else if (args.length > 1) {
String subCommand = args[0].toLowerCase();
switch (subCommand) {
case "set":
return BountySetCmd.onTabComplete(sender, args).stream()
.filter(suggestion -> suggestion.toLowerCase().startsWith(args[1].toLowerCase()))
.collect(Collectors.toList());
case "check":
return BountyCheckCmd.onTabComplete(sender, args).stream()
.filter(suggestion -> suggestion.toLowerCase().startsWith(args[1].toLowerCase()))
.collect(Collectors.toList());
case "top":
return Collections.emptyList(); // No additional arguments for top
default:
return Collections.emptyList();
}
final String subCommand = StringUtils.lowerCase(args[0]);
return switch (subCommand) {
case "set" -> BountySetCmd
.onTabComplete(sender, args).stream().filter(suggestion -> StringUtils
.startsWith(StringUtils.lowerCase(suggestion), StringUtils.lowerCase(args[1])))
.collect(Collectors.toList());
case "check" -> BountyCheckCmd
.onTabComplete(sender, args).stream().filter(suggestion -> StringUtils
.startsWith(StringUtils.lowerCase(suggestion), StringUtils.lowerCase(args[1])))
.collect(Collectors.toList());
case "top" -> Collections.emptyList();
default -> Collections.emptyList();
};
}
return Collections.emptyList();
}
}
@@ -1,90 +1,122 @@
package com.tcoded.playerbountiesplus.command;
import com.google.common.collect.Lists;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.command.admin.PlayerBountiesPlusReloadCmd;
import com.tcoded.playerbountiesplus.command.admin.PlayerBountiesPlusVersionCmd;
import com.tcoded.playerbountiesplus.command.admin.bounty.AdminBountyCmd;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.Lists;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.command.admin.PlayerBountiesPlusReloadCmd;
import com.tcoded.playerbountiesplus.command.admin.PlayerBountiesPlusVersionCmd;
import com.tcoded.playerbountiesplus.command.admin.bounty.AdminBountyCmd;
import net.trueog.utilitiesog.UtilitiesOG;
public class PlayerBountiesPlusAdminCmd implements CommandExecutor, TabCompleter {
private static final ArrayList<String> completions = Lists.newArrayList("reload", "version", "bounty", "help");
private final PlayerBountiesPlus plugin;
private final PlayerBountiesOG plugin;
public PlayerBountiesPlusAdminCmd(PlayerBountiesOG plugin) {
public PlayerBountiesPlusAdminCmd(PlayerBountiesPlus plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args)
{
if (args.length < 1) {
sendHelpMsg(sender);
return true;
}
String arg0Lower = args[0].toLowerCase();
final String arg0Lower = StringUtils.lowerCase(args[0]);
return switch (arg0Lower) {
case "reload" -> PlayerBountiesPlusReloadCmd.handleCmd(plugin, sender, command, label, args);
case "version" -> PlayerBountiesPlusVersionCmd.handleCmd(plugin, sender, command, label, args);
case "bounty" -> AdminBountyCmd.handleCmd(plugin, sender, command, label, args);
default -> {
switch (arg0Lower) {
case "reload":
return PlayerBountiesPlusReloadCmd.handleCmd(plugin, sender, command, label, args);
case "version":
return PlayerBountiesPlusVersionCmd.handleCmd(plugin, sender, command, label, args);
case "bounty":
return AdminBountyCmd.handleCmd(plugin, sender, command, label, args);
default:
sendHelpMsg(sender);
return true;
}
yield true;
}
};
}
private void sendHelpMsg(CommandSender sender) {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&',
"&f[&bPlayerBountiesPlus&f] &7PlayerBountiesPlus by TechnicallyCoded\n" +
"&fAdmin Commands:\n" +
"&f/pbp reload &7- Reload the configuration file and the messages.\n" +
"&f/pbp version &7- Check the version of the plugin.\n" +
"&f/pbp bounty set <player> <amount> &7- Set a player's bounty.\n" +
"&f/pbp bounty add <player> <amount> &7- Add to a player's bounty.\n" +
"&f/pbp bounty remove <player> <amount> &7- Remove from a player's bounty.\n" +
"&f/pbp bounty delete <player> &7- Delete a player's bounty.\n" +
"&f/pbp help &7- Get this message."
));
final String help = """
&f[&bPlayerBountiesPlus&f] &7PlayerBountiesPlus by TechnicallyCoded
&fAdmin Commands:
&f/pbp reload &7- Reload the configuration file and the messages.
&f/pbp version &7- Check the version of the plugin.
&f/pbp bounty set <player> <amount> &7- Set a player's bounty.
&f/pbp bounty add <player> <amount> &7- Add to a player's bounty.
&f/pbp bounty remove <player> <amount> &7- Remove from a player's bounty.
&f/pbp bounty delete <player> &7- Delete a player's bounty.
&f/pbp help &7- Get this message.\
""";
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), help);
} else {
UtilitiesOG.trueogMessage((Player) sender, help);
}
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args)
{
if (args.length == 1) {
return completions.stream()
.filter(s -> s.toLowerCase().startsWith(args[0].toLowerCase()))
.filter(s -> StringUtils.startsWith(StringUtils.lowerCase(s), StringUtils.lowerCase(args[0])))
.collect(Collectors.toList());
} else if (args.length > 1) {
String subCommand = args[0].toLowerCase();
switch (subCommand) {
case "bounty":
return AdminBountyCmd.onTabComplete(sender, args);
case "version":
return PlayerBountiesPlusVersionCmd.onTabComplete(sender, args);
case "reload":
case "help":
return Collections.emptyList(); // No additional arguments for reload or help
default:
return Collections.emptyList();
}
final String subCommand = StringUtils.lowerCase(args[0]);
return switch (subCommand) {
case "bounty" -> AdminBountyCmd.onTabComplete(sender, args);
case "version" -> PlayerBountiesPlusVersionCmd.onTabComplete(sender, args);
case "reload", "help" -> Collections.emptyList();
default -> Collections.emptyList();
};
}
return Collections.emptyList();
}
}
}
@@ -1,43 +1,74 @@
package com.tcoded.playerbountiesplus.command.admin;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import net.trueog.utilitiesog.UtilitiesOG;
public class PlayerBountiesPlusReloadCmd implements TabCompleter {
private static final String RELOAD_PERMISSION = "playerbountiesplus.command.playerbountiesplus.reload";
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String cmdName, String[] args) {
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String cmdName,
String[] args)
{
if (!sender.hasPermission(RELOAD_PERMISSION)) {
String noPerm = plugin.getLang().getColored("command.no-permission");
String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm)
.replace("{permission}", RELOAD_PERMISSION);
sender.sendMessage(noPermDetailed);
final String noPerm = plugin.getLang().getColored("command.no-permission");
final String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm).replace("{permission}", RELOAD_PERMISSION);
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noPermDetailed);
} else {
UtilitiesOG.trueogMessage((Player) sender, noPermDetailed);
}
return true;
}
plugin.reloadConfig();
plugin.reloadLang();
plugin.checkUpdate();
sender.sendMessage(plugin.getLang().getColored("command.admin.reload.reloaded"));
final String reloadMessage = plugin.getLang().getColored("command.admin.reload.reloaded");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), reloadMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, reloadMessage);
}
return true;
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
// No additional arguments for reload command
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args)
{
// No additional arguments for reload command.
return Collections.emptyList();
}
}
}
@@ -1,41 +1,58 @@
package com.tcoded.playerbountiesplus.command.admin;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.util.LangUtil;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.util.Collections;
import java.util.List;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.util.LangUtil;
import net.trueog.utilitiesog.UtilitiesOG;
public class PlayerBountiesPlusVersionCmd {
private static final String VERSION_PERMISSION = "playerbountiesplus.command.playerbountiesplus.version";
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String cmdName, String[] args) {
LangUtil lang = plugin.getLang();
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String cmdName,
String[] args)
{
String version;
final LangUtil lang = plugin.getLang();
final String version;
if (sender.hasPermission(VERSION_PERMISSION)) {
version = "v" + plugin.getDescription().getVersion();
version = "v" + plugin.getPluginMeta().getVersion();
} else {
version = "\n" + lang.getColored("command.admin.version.no-permission");
}
if (sender instanceof Player player) {
sender.sendMessage(ChatColor.translateAlternateColorCodes('&',
"&f[&bPlayerBountiesPlus&f] Plugin Information:\n" +
"&fPlugin: &7Running PlayerBountiesPlus " + version + "\n" +
"&fAuthor: &7TechnicallyCoded\n" +
"&fUpdate URL: &9https://www.spigotmc.org/resources/player-bounties-plus.108637/"
));
UtilitiesOG.trueogMessage(player, PlayerBountiesOG.getPrefix()
+ "&6 Authors: &aTechnicallyCoded, NotAlexNoyle &6Version: &e" + version);
} else {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(),
"Authors: TechnicallyCoded, NotAlexNoyle Version: " + version);
}
return true;
}
public static List<String> onTabComplete(CommandSender sender, String[] args) {
// No sub-commands for version, return empty list
// No sub-commands for version, return empty list.
return Collections.emptyList();
}
}
}
@@ -1,77 +1,167 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import net.trueog.utilitiesog.UtilitiesOG;
public class AdminBountyAddCmd {
private static final String PERMISSION = "playerbountiesplus.command.admin.bounty.add";
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String label, String[] args) {
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (!sender.hasPermission(PERMISSION)) {
String noPerm = plugin.getLang().getColored("command.no-permission");
String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm)
.replace("{permission}", PERMISSION);
sender.sendMessage(noPermDetailed);
final String noPerm = plugin.getLang().getColored("command.no-permission");
final String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm).replace("{permission}", PERMISSION);
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noPermDetailed);
} else {
UtilitiesOG.trueogMessage((Player) sender, noPermDetailed);
}
return true;
}
if (args.length < 4) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.add.missing-args"));
final String missingArguments = plugin.getLang().getColored("command.admin.bounty.add.missing-args");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), missingArguments);
} else {
UtilitiesOG.trueogMessage((Player) sender, missingArguments);
}
return true;
}
String playerName = args[2];
int amount;
final String playerName = args[2];
final double amount;
try {
amount = Integer.parseInt(args[3]);
} catch (NumberFormatException ex) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.add.amount-nan"));
amount = parseAmount(args[3]);
} catch (NumberFormatException numberFormatException) {
final String notNumber = plugin.getLang().getColored("command.admin.bounty.add.amount-nan");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), notNumber);
} else {
UtilitiesOG.trueogMessage((Player) sender, notNumber);
}
return true;
}
OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
final OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.add.player-not-found"));
final String playerNotFound = plugin.getLang().getColored("command.admin.bounty.add.player-not-found");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), playerNotFound);
} else {
UtilitiesOG.trueogMessage((Player) sender, playerNotFound);
}
return true;
}
UUID uuid = target.getUniqueId();
BountyDataManager m = plugin.getBountyDataManager();
int current = m.getBounty(uuid);
int total = current + amount;
final UUID uuid = target.getUniqueId();
final BountyDataManager m = plugin.getBountyDataManager();
final double current = m.getBounty(uuid);
final double total = current + amount;
m.setBounty(uuid, total);
m.saveBountiesAsync();
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.add.success")
.replace("{target}", target.getName())
.replace("{amount}", String.valueOf(amount))
.replace("{total}", String.valueOf(total)));
final String bountyAdded = plugin.getLang().getColored("command.admin.bounty.add.success")
.replace("{target}", target.getName()).replace("{amount}", String.valueOf(amount))
.replace("{total}", String.valueOf(total));
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), bountyAdded);
} else {
UtilitiesOG.trueogMessage((Player) sender, bountyAdded);
}
return true;
}
private static double parseAmount(String amountInput) {
if (!amountInput.matches("^\\d+(?:\\.\\d)?$")) {
throw new NumberFormatException("Invalid amount format");
}
return Double.parseDouble(amountInput);
}
@Nullable
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
@NotNull String label, @NotNull String[] args)
{
if (args.length == 3) {
// Suggest all online player names for the username
return sender.getServer().getOnlinePlayers().stream()
.map(player -> player.getName())
.collect(Collectors.toList());
// Suggest all online player names for the username.
return sender.getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
} else if (args.length == 4) {
// Suggest a placeholder for the amount
// Suggest a placeholder for the amount.
return Collections.singletonList("<amount>");
}
return Collections.emptyList();
}
}
}
@@ -1,69 +1,98 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import net.trueog.utilitiesog.UtilitiesOG;
public class AdminBountyCmd {
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String label, String[] args) {
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (args.length < 2) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.no-action"));
final String noAction = plugin.getLang().getColored("command.bounty.no-action");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noAction);
} else {
UtilitiesOG.trueogMessage((Player) sender, noAction);
}
return true;
}
String action = args[1].toLowerCase();
switch (action) {
case "set":
return AdminBountySetCmd.handleCmd(plugin, sender, cmd, label, args);
case "add":
return AdminBountyAddCmd.handleCmd(plugin, sender, cmd, label, args);
case "remove":
return AdminBountyRemoveCmd.handleCmd(plugin, sender, cmd, label, args);
case "delete":
return AdminBountyDeleteCmd.handleCmd(plugin, sender, cmd, label, args);
case "get":
return AdminBountyGetCmd.handleCmd(plugin, sender, cmd, label, args);
default:
sender.sendMessage(plugin.getLang().getColored("command.bounty.invalid-action"));
return true;
}
final String action = StringUtils.lowerCase(args[1]);
return switch (action) {
case "set" -> AdminBountySetCmd.handleCmd(plugin, sender, cmd, label, args);
case "add" -> AdminBountyAddCmd.handleCmd(plugin, sender, cmd, label, args);
case "remove" -> AdminBountyRemoveCmd.handleCmd(plugin, sender, cmd, label, args);
case "delete" -> AdminBountyDeleteCmd.handleCmd(plugin, sender, cmd, label, args);
case "get" -> AdminBountyGetCmd.handleCmd(plugin, sender, cmd, label, args);
default -> {
final String invalidAction = plugin.getLang().getColored("command.bounty.invalid-action");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), invalidAction);
} else {
UtilitiesOG.trueogMessage((Player) sender, invalidAction);
}
yield true;
}
};
}
public static List<String> onTabComplete(CommandSender sender, String[] args) {
List<String> suggestions = Collections.emptyList();
if (args.length == 2) {
suggestions = Arrays.asList("set", "add", "remove", "delete", "get");
} else if (args.length > 2) {
String sub = args[1].toLowerCase();
final String sub = StringUtils.lowerCase(args[1]);
switch (sub) {
case "add":
suggestions = AdminBountyAddCmd.onTabComplete(sender, null, null, args);
break;
case "remove":
suggestions = AdminBountyRemoveCmd.onTabComplete(sender, null, null, args);
break;
case "delete":
suggestions = AdminBountyDeleteCmd.onTabComplete(sender, null, null, args);
break;
case "get":
suggestions = AdminBountyGetCmd.onTabComplete(sender, null, null, args);
break;
case "set":
suggestions = AdminBountySetCmd.onTabComplete(sender, null, null, args);
break;
case "add" -> suggestions = AdminBountyAddCmd.onTabComplete(sender, null, null, args);
case "remove" -> suggestions = AdminBountyRemoveCmd.onTabComplete(sender, null, null, args);
case "delete" -> suggestions = AdminBountyDeleteCmd.onTabComplete(sender, null, null, args);
case "get" -> suggestions = AdminBountyGetCmd.onTabComplete(sender, null, null, args);
case "set" -> suggestions = AdminBountySetCmd.onTabComplete(sender, null, null, args);
}
}
String input = args[args.length - 1].toLowerCase();
return suggestions.stream()
.filter(opt -> opt.toLowerCase().startsWith(input))
final String input = StringUtils.lowerCase(args[args.length - 1]);
return suggestions.stream().filter(opt -> StringUtils.startsWith(StringUtils.lowerCase(opt), input))
.collect(Collectors.toList());
}
}
}
@@ -1,7 +1,10 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@@ -9,55 +12,110 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import net.trueog.utilitiesog.UtilitiesOG;
public class AdminBountyDeleteCmd {
private static final String PERMISSION = "playerbountiesplus.command.admin.bounty.delete";
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String label, String[] args) {
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (!sender.hasPermission(PERMISSION)) {
String noPerm = plugin.getLang().getColored("command.no-permission");
String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm)
.replace("{permission}", PERMISSION);
sender.sendMessage(noPermDetailed);
final String noPerm = plugin.getLang().getColored("command.no-permission");
final String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm).replace("{permission}", PERMISSION);
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noPermDetailed);
} else {
UtilitiesOG.trueogMessage((Player) sender, noPermDetailed);
}
return true;
}
if (args.length < 3) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.delete.missing-args"));
final String missingArguments = plugin.getLang().getColored("command.admin.bounty.delete.missing-args");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), missingArguments);
} else {
UtilitiesOG.trueogMessage((Player) sender, missingArguments);
}
return true;
}
String playerName = args[2];
OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
final String playerName = args[2];
final OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.delete.player-not-found"));
final String playerNotFound = plugin.getLang().getColored("command.admin.bounty.delete.player-not-found");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), playerNotFound);
} else {
UtilitiesOG.trueogMessage((Player) sender, playerNotFound);
}
return true;
}
UUID uuid = target.getUniqueId();
BountyDataManager m = plugin.getBountyDataManager();
m.removeBounty(uuid);
m.saveBountiesAsync();
final UUID uuid = target.getUniqueId();
final BountyDataManager bountyData = plugin.getBountyDataManager();
bountyData.removeBounty(uuid);
bountyData.saveBountiesAsync();
final String bountyDeletedMessage = plugin.getLang().getColored("command.admin.bounty.delete.success")
.replace("{target}", target.getName());
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), bountyDeletedMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, bountyDeletedMessage);
}
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.delete.success")
.replace("{target}", target.getName()));
return true;
}
@Nullable
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
@NotNull String label, @NotNull String[] args)
{
if (args.length == 3) {
// Suggest all online player names for the username
return sender.getServer().getOnlinePlayers().stream()
.map(Player::getName)
.collect(Collectors.toList());
// Suggest all online player names for the username.
return sender.getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
}
return Collections.emptyList();
}
}
}
@@ -1,63 +1,120 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import net.trueog.utilitiesog.UtilitiesOG;
public class AdminBountyGetCmd {
private static final String PERMISSION = "playerbountiesplus.command.admin.bounty.get";
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String label, String[] args) {
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (!sender.hasPermission(PERMISSION)) {
String noPerm = plugin.getLang().getColored("command.no-permission");
String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm)
.replace("{permission}", PERMISSION);
sender.sendMessage(noPermDetailed);
final String noPerm = plugin.getLang().getColored("command.no-permission");
final String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm).replace("{permission}", PERMISSION);
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noPermDetailed);
} else {
UtilitiesOG.trueogMessage((Player) sender, noPermDetailed);
}
return true;
}
if (args.length < 3) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.get.missing-args"));
final String missingArguments = plugin.getLang().getColored("command.admin.bounty.get.missing-args");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), missingArguments);
} else {
UtilitiesOG.trueogMessage((Player) sender, missingArguments);
}
return true;
}
String playerName = args[2];
final String playerName = args[2];
OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
final OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.get.player-not-found"));
final String playerNotFound = plugin.getLang().getColored("command.admin.bounty.get.player-not-found");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), playerNotFound);
} else {
UtilitiesOG.trueogMessage((Player) sender, playerNotFound);
}
return true;
}
UUID uuid = target.getUniqueId();
BountyDataManager m = plugin.getBountyDataManager();
int current = m.getBounty(uuid);
final UUID uuid = target.getUniqueId();
final BountyDataManager m = plugin.getBountyDataManager();
final double current = m.getBounty(uuid);
final String bountyFetch = plugin.getLang().getColored("command.admin.bounty.get.success")
.replace("{target}", target.getName()).replace("{bounty}", String.valueOf(current));
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), bountyFetch);
} else {
UtilitiesOG.trueogMessage((Player) sender, bountyFetch);
}
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.get.success")
.replace("{target}", target.getName())
.replace("{bounty}", String.valueOf(current)));
return true;
}
@Nullable
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
@NotNull String label, @NotNull String[] args)
{
if (args.length == 3) {
// Suggest all online player names for the username
return sender.getServer().getOnlinePlayers().stream()
.map(player -> player.getName())
.collect(Collectors.toList());
// Suggest all online player names for the username.
return sender.getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
}
return Collections.emptyList();
}
}
}
@@ -1,82 +1,175 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import net.trueog.utilitiesog.UtilitiesOG;
public class AdminBountyRemoveCmd {
private static final String PERMISSION = "playerbountiesplus.command.admin.bounty.remove";
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String label, String[] args) {
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (!sender.hasPermission(PERMISSION)) {
String noPerm = plugin.getLang().getColored("command.no-permission");
String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm)
.replace("{permission}", PERMISSION);
sender.sendMessage(noPermDetailed);
final String noPerm = plugin.getLang().getColored("command.no-permission");
final String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm).replace("{permission}", PERMISSION);
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noPermDetailed);
} else {
UtilitiesOG.trueogMessage((Player) sender, noPermDetailed);
}
return true;
}
if (args.length < 4) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.remove.missing-args"));
final String missingArguments = plugin.getLang().getColored("command.admin.bounty.remove.missing-args");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), missingArguments);
} else {
UtilitiesOG.trueogMessage((Player) sender, missingArguments);
}
return true;
}
String playerName = args[2];
int amount;
final String playerName = args[2];
final double amount;
try {
amount = Integer.parseInt(args[3]);
} catch (NumberFormatException ex) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.remove.amount-nan"));
amount = parseAmount(args[3]);
} catch (NumberFormatException numberFormatException) {
final String notNumberMessage = plugin.getLang().getColored("command.admin.bounty.remove.amount-nan");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), notNumberMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, notNumberMessage);
}
return true;
}
OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
final OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.remove.player-not-found"));
final String playerNotFound = plugin.getLang().getColored("command.admin.bounty.remove.player-not-found");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), playerNotFound);
} else {
UtilitiesOG.trueogMessage((Player) sender, playerNotFound);
}
return true;
}
UUID uuid = target.getUniqueId();
BountyDataManager m = plugin.getBountyDataManager();
int current = m.getBounty(uuid);
int total = current - amount;
final UUID uuid = target.getUniqueId();
final BountyDataManager m = plugin.getBountyDataManager();
final double current = m.getBounty(uuid);
double total = current - amount;
if (total <= 0) {
m.removeBounty(uuid);
total = 0;
} else {
m.setBounty(uuid, total);
}
m.saveBountiesAsync();
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.remove.success")
.replace("{target}", target.getName())
.replace("{amount}", String.valueOf(amount))
.replace("{total}", String.valueOf(total)));
final String bountyRemovedMessage = plugin.getLang().getColored("command.admin.bounty.remove.success")
.replace("{target}", target.getName()).replace("{amount}", String.valueOf(amount))
.replace("{total}", String.valueOf(total));
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), bountyRemovedMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, bountyRemovedMessage);
}
return true;
}
private static double parseAmount(String amountInput) {
if (!amountInput.matches("^\\d+(?:\\.\\d)?$")) {
throw new NumberFormatException("Invalid amount format");
}
return Double.parseDouble(amountInput);
}
@Nullable
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
@NotNull String label, @NotNull String[] args)
{
if (args.length == 3) {
// Suggest all online player names for the username
return sender.getServer().getOnlinePlayers().stream()
.map(player -> player.getName())
.collect(Collectors.toList());
// Suggest all online player names for the username.
return sender.getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
} else if (args.length == 4) {
// Suggest a placeholder for the amount
// Suggest a placeholder for the amount.
return Collections.singletonList("<amount>");
}
return Collections.emptyList();
}
}
}
@@ -1,74 +1,161 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import net.trueog.utilitiesog.UtilitiesOG;
public class AdminBountySetCmd {
private static final String PERMISSION = "playerbountiesplus.command.admin.bounty.set";
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String label, String[] args) {
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (!sender.hasPermission(PERMISSION)) {
String noPerm = plugin.getLang().getColored("command.no-permission");
String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm)
.replace("{permission}", PERMISSION);
sender.sendMessage(noPermDetailed);
final String noPerm = plugin.getLang().getColored("command.no-permission");
final String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm).replace("{permission}", PERMISSION);
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noPermDetailed);
} else {
UtilitiesOG.trueogMessage((Player) sender, noPermDetailed);
}
return true;
}
if (args.length < 4) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.set.missing-args"));
final String missingArguments = plugin.getLang().getColored("command.admin.bounty.set.missing-args");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), missingArguments);
} else {
UtilitiesOG.trueogMessage((Player) sender, missingArguments);
}
return true;
}
String playerName = args[2];
int amount;
final String playerName = args[2];
final double amount;
try {
amount = Integer.parseInt(args[3]);
} catch (NumberFormatException ex) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.set.amount-nan"));
amount = parseAmount(args[3]);
} catch (NumberFormatException numberFormatException) {
final String notNumberMessage = plugin.getLang().getColored("command.admin.bounty.set.amount-nan");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), notNumberMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, notNumberMessage);
}
return true;
}
OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
final OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.set.player-not-found"));
final String playerNotFound = plugin.getLang().getColored("command.admin.bounty.set.player-not-found");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), playerNotFound);
} else {
UtilitiesOG.trueogMessage((Player) sender, playerNotFound);
}
return true;
}
UUID uuid = target.getUniqueId();
BountyDataManager m = plugin.getBountyDataManager();
m.setBounty(uuid, amount);
m.saveBountiesAsync();
final UUID uuid = target.getUniqueId();
final BountyDataManager dataManager = plugin.getBountyDataManager();
dataManager.setBounty(uuid, amount);
dataManager.saveBountiesAsync();
final String bountySetMessage = plugin.getLang().getColored("command.admin.bounty.set.success")
.replace("{target}", target.getName()).replace("{bounty}", String.valueOf(amount));
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), bountySetMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, bountySetMessage);
}
sender.sendMessage(plugin.getLang().getColored("command.admin.bounty.set.success")
.replace("{target}", target.getName())
.replace("{bounty}", String.valueOf(amount)));
return true;
}
private static double parseAmount(String amountInput) {
if (!amountInput.matches("^\\d+(?:\\.\\d)?$")) {
throw new NumberFormatException("Invalid amount format");
}
return Double.parseDouble(amountInput);
}
@Nullable
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
@NotNull String label, @NotNull String[] args)
{
if (args.length == 3) {
// Suggest all online player names for the username
return sender.getServer().getOnlinePlayers().stream()
.map(player -> player.getName())
.collect(Collectors.toList());
// Suggest all online player names for the username.
return sender.getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
} else if (args.length == 4) {
// Suggest a placeholder for the amount
// Suggest a placeholder for the amount.
return Collections.singletonList("<amount>");
}
return Collections.emptyList();
}
}
}
@@ -1,68 +1,122 @@
package com.tcoded.playerbountiesplus.command.bounty;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import net.trueog.utilitiesog.UtilitiesOG;
public class BountyCheckCmd {
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String cmdName, String[] args) {
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String cmdName,
String[] args)
{
if (args.length < 2) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.check.no-player-specified"));
final String noPlayerSpecifiedMessage = plugin.getLang()
.getColored("command.bounty.check.no-player-specified");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noPlayerSpecifiedMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, noPlayerSpecifiedMessage);
}
return true;
}
String playerNameArg = args[1];
final String playerNameArg = args[1];
Player target = plugin.getServer().getPlayerExact(playerNameArg);
final Player target = plugin.getServer().getPlayerExact(playerNameArg);
if (target == null) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.check.player-not-found"));
final String playerNotFoundMessage = plugin.getLang().getColored("command.bounty.check.player-not-found");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), playerNotFoundMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, playerNotFoundMessage);
}
return true;
}
UUID playerUUID = target.getUniqueId();
final UUID playerUUID = target.getUniqueId();
BountyDataManager bountyDataManager = plugin.getBountyDataManager();
boolean hasBounty = bountyDataManager.hasBounty(playerUUID);
final BountyDataManager bountyDataManager = plugin.getBountyDataManager();
final boolean hasBounty = bountyDataManager.hasBounty(playerUUID);
if (hasBounty) {
// Confirmation
int bounty = bountyDataManager.getBounty(playerUUID);
sender.sendMessage(
plugin.getLang().getColored("command.bounty.check.bounty-found")
.replace("{target}", target.getName())
.replace("{bounty}", Integer.toString(bounty))
);
// Confirmation.
final double bounty = bountyDataManager.getBounty(playerUUID);
final String bountyFoundMessage = plugin.getLang().getColored("command.bounty.check.bounty-found")
.replace("{target}", target.getName()).replace("{bounty}", Double.toString(bounty));
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), bountyFoundMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, bountyFoundMessage);
}
} else {
sender.sendMessage(
plugin.getLang().getColored("command.bounty.check.no-bounty")
.replace("{target}", target.getName())
);
final String noBountyFoundMessage = plugin.getLang().getColored("command.bounty.check.no-bounty")
.replace("{target}", target.getName());
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noBountyFoundMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, noBountyFoundMessage);
}
}
return true;
}
@Nullable
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull String[] args) {
if (args.length == 2) {
// Suggest online player names for the username
return sender.getServer().getOnlinePlayers().stream()
.map(Player::getName)
.filter(name -> name.toLowerCase().startsWith(args[1].toLowerCase()))
// Suggest online player names for the username.
return sender.getServer().getOnlinePlayers().stream().map(Player::getName)
.filter(name -> StringUtils.startsWith(StringUtils.lowerCase(name), StringUtils.lowerCase(args[1])))
.collect(Collectors.toList());
}
return Collections.emptyList();
}
}
}
@@ -1,152 +1,431 @@
package com.tcoded.playerbountiesplus.command.bounty;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.event.BountySetEvent;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.event.BountySetEvent;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.cacheddata.CachedMetaData;
import net.luckperms.api.model.user.User;
import net.trueog.diamondbankog.api.DiamondBankAPIJava;
import net.trueog.utilitiesog.UtilitiesOG;
public class BountySetCmd {
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String cmdName, String[] args) {
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String cmdName,
String[] args)
{
if (args.length < 3) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.missing-args"));
final String missingArgumentsMessage = plugin.getLang().getColored("command.bounty.set.missing-args");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), missingArgumentsMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, missingArgumentsMessage);
}
return true;
}
if (sender instanceof Player && !sender.hasPermission("playerbountiesplus.command.bounty.set")) {
String noPerm = plugin.getLang().getColored("command.no-permission");
String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
final String noPerm = plugin.getLang().getColored("command.no-permission");
final String noPermDetailed = plugin.getLang().getColored("command.no-permission-detailed")
.replace("{no-permission-msg}", noPerm)
.replace("{permission}", "playerbountiesplus.command.bounty.set");
sender.sendMessage(noPermDetailed);
return true;
}
if (!(sender instanceof Player)) {
String playerNameArg = args[1];
float amount;
try {
amount = Integer.parseInt(args[2]);
} catch (NumberFormatException ex) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.amount-nan"));
return true;
}
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noPermDetailed);
Player target = plugin.getServer().getPlayerExact(playerNameArg);
} else {
if (target == null) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.player-not-found"));
return true;
}
UtilitiesOG.trueogMessage((Player) sender, noPermDetailed);
// Check limits
double minimum = plugin.getConfig().getDouble("bounty-minimum", 1.0);
if (amount < minimum) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.under-minimum")
.replace("{minimum}", String.valueOf(minimum))
);
return true;
}
double maximum = plugin.getConfig().getDouble("bounty-maximum", 1000000.0);
if (amount > maximum) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.over-maximum")
.replace("{maximum}", String.valueOf(minimum))
);
return true;
}
// Check money
if (sender instanceof Player) {
Player player = (Player) sender;
boolean allowed = plugin.getEcoHook().takeEco(player, amount);
if (!allowed) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.not-enough-money"));
return true;
}
return true;
}
// Apply bounty multiplier
amount *= (float) plugin.getConfig().getDouble("bounty-multiplier", 1.0);
final String playerNameArg = args[1];
final double parsedAmount;
try {
// Trigger bounty set event
BountySetEvent event = new BountySetEvent(sender instanceof Player ? (Player) sender : null, target, amount);
parsedAmount = parseAmount(args[2]);
} catch (NumberFormatException numberFormatException) {
final String notNumberMessage = plugin.getLang().getColored("command.bounty.set.amount-nan");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), notNumberMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, notNumberMessage);
}
return true;
}
final Player target = plugin.getServer().getPlayerExact(playerNameArg);
if (target == null) {
final String playerNotFoundMessage = plugin.getLang().getColored("command.bounty.set.player-not-found");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), playerNotFoundMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, playerNotFoundMessage);
}
return true;
}
// Check limits.
final double minimum = plugin.getConfig().getDouble("bounty-minimum", 1.0);
if (parsedAmount < minimum) {
final String underMinimumMessage = plugin.getLang().getColored("command.bounty.set.under-minimum")
.replace("{minimum}", String.valueOf(minimum));
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), underMinimumMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, underMinimumMessage);
}
return true;
}
final double maximum = plugin.getConfig().getDouble("bounty-maximum", 1000000.0);
if (parsedAmount > maximum) {
final String overMaximumMessage = plugin.getLang().getColored("command.bounty.set.over-maximum")
.replace("{maximum}", String.valueOf(maximum));
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), overMaximumMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, overMaximumMessage);
}
return true;
}
// Apply bounty multiplier.
double amount = parsedAmount * plugin.getConfig().getDouble("bounty-multiplier", 1.0);
// Trigger bounty set event.
final BountySetEvent event = new BountySetEvent(sender instanceof Player ? (Player) sender : null, target,
(float) amount);
plugin.getServer().getPluginManager().callEvent(event);
amount = event.getAmount();
// Check if event was cancelled
// Check if event was cancelled.
if (event.isCancelled()) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.cancelled"));
final String cancelledBounty = plugin.getLang().getColored("command.bounty.set.cancelled");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), cancelledBounty);
} else {
UtilitiesOG.trueogMessage((Player) sender, cancelledBounty);
}
return true;
}
// Sanity check final amount
// Sanity check final amount.
if (amount <= 0) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.internal-invalid-value"));
final String invalidValueMessage = plugin.getLang().getColored("command.bounty.set.internal-invalid-value");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), invalidValueMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, invalidValueMessage);
}
return true;
}
UUID playerUUID = target.getUniqueId();
// Check economy. Only charge if sender is a player.
if (sender instanceof Player player) {
// Calculate total bounty including previous bounties
BountyDataManager bountyDataManager = plugin.getBountyDataManager();
int bountyAlreadyPresent = bountyDataManager.getBounty(playerUUID);
int totalBounty = ((int) amount) + bountyAlreadyPresent;
final boolean allowed = plugin.getEcoHook().takeEco(player, target, amount);
if (!allowed) {
final String notEnoughDiamondsMessage = plugin.getLang()
.getColored("command.bounty.set.not-enough-money");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), notEnoughDiamondsMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, notEnoughDiamondsMessage);
}
return true;
}
}
final UUID playerUUID = target.getUniqueId();
// Calculate total bounty including previous bounties.
final BountyDataManager bountyDataManager = plugin.getBountyDataManager();
final DiamondBankAPIJava diamondBankAPI = resolveDiamondBankApi(plugin);
final long newBountyShards = diamondBankAPI.diamondsToShards(amount);
final long existingBountyShards = diamondBankAPI
.diamondsToShards((float) bountyDataManager.getBounty(playerUUID));
final long totalBountyShards = newBountyShards + existingBountyShards;
final double totalBounty = Double.parseDouble(diamondBankAPI.shardsToDiamonds(totalBountyShards));
bountyDataManager.setBounty(playerUUID, totalBounty);
// Confirmation
sender.sendMessage(
plugin.getLang().getColored("command.bounty.set.success")
.replace("{bounty}", String.valueOf(amount))
.replace("{total}", String.valueOf(totalBounty))
.replace("{target}", target.getName())
.replace("{player}", sender.getName())
);
// Announcement.
final String extra;
if (existingBountyShards == 0L) {
extra = "";
} else {
extra = plugin.getLang().getColored("command.bounty.set.announce-extra").replace("{total}",
diamondBankAPI.shardsToDiamonds(totalBountyShards));
// Announce
String extra;
if (bountyAlreadyPresent == 0) extra = "";
else {
extra = plugin.getLang().getColored("command.bounty.set.announce-extra")
.replace("{total}", String.valueOf(totalBounty));
}
if (plugin.getConfig().getBoolean("bounty-placed-announce", true)) {
plugin.getServer().broadcastMessage(
plugin.getLang().getColored("command.bounty.set.announce")
.replace("{bounty}", String.valueOf(amount))
.replace("{target}", target.getName())
.replace("{player}", sender.getName())
.replace("{extra}", extra)
);
final LuckPerms luckPerms = resolveLuckPerms(plugin);
final String setterDisplay = sender instanceof Player player ? formatLuckPermsDisplay(luckPerms, player)
: sender.getName();
final String targetDisplay = formatLuckPermsDisplay(luckPerms, target);
final String bountyDisplay = diamondBankAPI.shardsToDiamonds(newBountyShards);
Bukkit.getOnlinePlayers()
.forEach((Player player) -> UtilitiesOG.trueogMessage(player,
PlayerBountiesOG.getPrefix() + "&a"
+ plugin.getLang().getColored("command.bounty.set.announce")
.replace("{bounty}", bountyDisplay).replace("{target}", targetDisplay)
.replace("{player}", setterDisplay).replace("{extra}", extra)));
}
bountyDataManager.saveBountiesAsync();
return true;
}
private static double parseAmount(String amountInput) {
if (!amountInput.matches("^\\d+(?:\\.\\d)?$")) {
throw new NumberFormatException("Invalid amount format");
}
return Double.parseDouble(amountInput);
}
private static DiamondBankAPIJava resolveDiamondBankApi(PlayerBountiesOG plugin) {
final RegisteredServiceProvider<DiamondBankAPIJava> provider = plugin.getServer().getServicesManager()
.getRegistration(DiamondBankAPIJava.class);
if (provider == null) {
throw new IllegalStateException("DiamondBank-OG API is null");
}
return provider.getProvider();
}
private static LuckPerms resolveLuckPerms(PlayerBountiesOG plugin) {
final RegisteredServiceProvider<LuckPerms> provider = plugin.getServer().getServicesManager()
.getRegistration(LuckPerms.class);
if (provider == null) {
return null;
}
return provider.getProvider();
}
private static String formatLuckPermsDisplay(LuckPerms luckPerms, Player player) {
final String prefix = stripLeadingReset(stripTrailingReset(getLuckPermsPrefixLegacy(luckPerms, player)));
final String leadingColorCodes = extractLeadingColorCodes(prefix);
if (prefix.isBlank()) {
return player.getName();
}
if (leadingColorCodes.isBlank()) {
return prefix + " " + player.getName();
}
return prefix + " " + leadingColorCodes + player.getName();
}
private static String getLuckPermsPrefixLegacy(LuckPerms luckPerms, Player player) {
if (luckPerms == null) {
return "";
}
final User user = luckPerms.getUserManager().getUser(player.getUniqueId());
if (user == null) {
return "";
}
final CachedMetaData meta = user.getCachedData().getMetaData();
final String prefix = meta.getPrefix();
if (prefix == null || prefix.isBlank()) {
return "";
}
return StringUtils.trim(prefix).replace('§', '&');
}
private static String stripTrailingReset(String input) {
if (input == null || input.isBlank()) {
return "";
}
return StringUtils.trim(input.replaceAll("(?i)(?:\\s*(?:<reset>|[&§]r))+$", ""));
}
private static String stripLeadingReset(String input) {
if (input == null || input.isBlank()) {
return "";
}
return StringUtils.trim(input.replaceFirst("(?i)^(?:\\s*(?:<reset>|[&§]r))+", ""));
}
private static String extractLeadingColorCodes(String input) {
if (input == null || input.length() < 2) {
return "";
}
final StringBuilder out = new StringBuilder();
for (int i = 0; i < input.length() - 1; i++) {
final char current = input.charAt(i);
if (current != '&' && current != '§') {
break;
}
out.append(current).append(input.charAt(i + 1));
i++;
}
return out.toString();
}
@Nullable
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull String[] args) {
if (args.length == 2) {
// Suggest online player names for the username
return sender.getServer().getOnlinePlayers().stream()
.map(Player::getName)
.filter(name -> name.toLowerCase().startsWith(args[1].toLowerCase()))
// Suggest online player names for the username.
return sender.getServer().getOnlinePlayers().stream().map(Player::getName)
.filter(name -> StringUtils.startsWith(StringUtils.lowerCase(name), StringUtils.lowerCase(args[1])))
.collect(Collectors.toList());
} else if (args.length == 3) {
// Suggest a placeholder for the amount
// Suggest a placeholder for the amount.
return Collections.singletonList("<amount>");
}
return Collections.emptyList();
}
}
}
@@ -1,47 +1,231 @@
package com.tcoded.playerbountiesplus.command.bounty;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.ChatColor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.*;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.gui.MainBountyGui;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.cacheddata.CachedMetaData;
import net.luckperms.api.model.user.User;
import net.trueog.diamondbankog.api.DiamondBankAPIJava;
import net.trueog.utilitiesog.UtilitiesOG;
public class BountyTopCmd {
public static boolean handleCmd(PlayerBountiesPlus plugin, CommandSender sender, Command cmd, String cmdName, String[] args) {
public static boolean handleCmd(PlayerBountiesOG plugin, DiamondBankAPIJava diamondBankAPI, CommandSender sender,
Command cmd, String cmdName, String[] args)
{
Set<Map.Entry<UUID, Integer>> bountiesSet = plugin.getBountyDataManager().getBounties().entrySet();
List<Map.Entry<UUID, Integer>> bounties = new ArrayList<>(bountiesSet);
bounties.sort((a, b) -> b.getValue() - a.getValue());
if (sender instanceof Player player) {
StringBuilder strb = new StringBuilder();
strb.append(plugin.getLang().getColored("command.bounty.top.top-10") + "\n");
final List<MainBountyGui.BountyGuiEntry> entries = buildGuiEntries(plugin);
new MainBountyGui(plugin, player, () -> entries, diamondBankAPI).open();
int bountiesSize = bounties.size();
int maxInList = Math.min(10, bountiesSize);
return true;
if (bountiesSize > 0) {
for (int i = 0; i < maxInList; i++) {
strb.append(ChatColor.GRAY);
strb.append(" - ");
Map.Entry<UUID, Integer> entry = bounties.get(i);
strb.append(plugin.getServer().getOfflinePlayer(entry.getKey()).getName());
strb.append(": ");
strb.append(entry.getValue());
strb.append('\n');
}
}
else {
strb.append(plugin.getLang().getColored("command.bounty.top.no-bounties") + "\n");
sendTextTopList(plugin, diamondBankAPI, sender);
return true;
}
private static List<MainBountyGui.BountyGuiEntry> buildGuiEntries(PlayerBountiesOG plugin) {
final Set<Map.Entry<UUID, Double>> bountiesSet = plugin.getBountyDataManager().getBounties().entrySet();
final List<Map.Entry<UUID, Double>> bounties = new ArrayList<>(bountiesSet);
bounties.sort((a, b) -> Double.compare(b.getValue(), a.getValue()));
final List<MainBountyGui.BountyGuiEntry> entries = new ArrayList<>();
for (Map.Entry<UUID, Double> entry : bounties) {
if (entry.getValue() == null || entry.getValue() <= 0D) {
continue;
}
final OfflinePlayer offlinePlayer = plugin.getServer().getOfflinePlayer(entry.getKey());
String targetName = offlinePlayer.getName();
if (targetName == null || targetName.isBlank()) {
targetName = "Unknown Player";
}
final String displayName = resolveLuckPermsDisplayName(plugin.getLuckPerms(), entry.getKey(), targetName);
entries.add(new MainBountyGui.BountyGuiEntry(entry.getKey(), targetName, displayName, entry.getValue()));
}
return entries;
}
private static String resolveLuckPermsDisplayName(LuckPerms luckPerms, UUID playerId, String playerName) {
final String safeName = StringUtils.defaultIfBlank(playerName, "Unknown Player");
if (luckPerms == null) {
return "&f" + safeName;
}
final User user = luckPerms.getUserManager().getUser(playerId);
if (user == null) {
return "&f" + safeName;
}
final CachedMetaData meta = user.getCachedData().getMetaData();
final String prefix = StringUtils.trim(StringUtils.defaultString(meta.getPrefix()).replace('§', '&'));
final String suffix = StringUtils.trim(StringUtils.defaultString(meta.getSuffix()).replace('§', '&'));
final boolean metaContainsName = containsVisibleName(prefix, safeName) || containsVisibleName(suffix, safeName);
final StringBuilder out = new StringBuilder();
if (!prefix.isBlank()) {
out.append(prefix).append(' ');
}
if (!metaContainsName) {
out.append(safeName);
}
if (!suffix.isBlank()) {
out.append(' ').append(suffix);
}
return sanitizeDisplay(out.toString(), safeName);
}
private static String sanitizeDisplay(String formatted, String fallbackName) {
final String cleaned = StringUtils.trimToEmpty(formatted).replaceAll("(?i)(?:\\s*(?:<reset>|[&§]r))+$", "")
.replaceAll("\\s+>", " >").replaceAll("\\s*>$", "");
if (cleaned.isBlank()) {
return fallbackName;
}
return cleaned;
}
private static boolean containsVisibleName(String text, String playerName) {
if (text == null || playerName == null || playerName.isBlank()) {
return false;
}
final String normalizedText = stripFormatting(text).toLowerCase(Locale.ROOT);
final String normalizedName = playerName.toLowerCase(Locale.ROOT);
return normalizedText.contains(normalizedName);
}
private static String stripFormatting(String input) {
if (input == null || input.isBlank()) {
return "";
}
return input.replaceAll("(?i)[&§][0-9A-FK-ORX]", "").replaceAll("<[^>]+>", "").trim();
}
private static void sendTextTopList(PlayerBountiesOG plugin, DiamondBankAPIJava diamondBankAPI,
CommandSender sender)
{
final Set<Map.Entry<UUID, Double>> bountiesSet = plugin.getBountyDataManager().getBounties().entrySet();
final List<Map.Entry<UUID, Double>> bounties = new ArrayList<>(bountiesSet);
bounties.sort((a, b) -> Double.compare(b.getValue(), a.getValue()));
final StringBuilder strb = new StringBuilder();
strb.append(plugin.getLang().getColored("command.bounty.top.top-10")).append('\n');
final int bountiesSize = bounties.size();
final int maxInList = Math.min(10, bountiesSize);
if (bountiesSize > 0) {
for (int i = 0; i < maxInList; i++) {
final Map.Entry<UUID, Double> entry = bounties.get(i);
final OfflinePlayer offlinePlayer = plugin.getServer().getOfflinePlayer(entry.getKey());
String targetName = offlinePlayer.getName();
if (targetName == null || targetName.isBlank()) {
targetName = "Unknown Player";
}
final String formattedBounty = diamondBankAPI
.shardsToDiamonds(diamondBankAPI.diamondsToShards(entry.getValue()));
strb.append("&7 - ");
final String displayName = resolveLuckPermsDisplayName(plugin.getLuckPerms(), entry.getKey(),
targetName);
strb.append(displayName);
strb.append(": &b");
strb.append(formattedBounty);
strb.append(" &bDiamonds");
strb.append('\n');
}
} else {
strb.append(plugin.getLang().getColored("command.bounty.top.no-bounties")).append('\n');
}
String message = strb.toString();
message = message.substring(0, message.length() - 1); // remove last \n
sender.sendMessage(message);
return true;
message = StringUtils.substring(message, 0, message.length() - 1);
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), message);
} else {
UtilitiesOG.trueogMessage((Player) sender, message);
}
}
}
@@ -17,41 +17,57 @@ public class BountyClaimEvent extends Event implements Cancellable {
private boolean cancelled;
public BountyClaimEvent(@NotNull Player claimant, @NotNull Player victim, double amount) {
this.claimant = claimant;
this.victim = victim;
this.amount = amount;
this.cancelled = false;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
public Player getClaimant() {
return claimant;
}
public Player getVictim() {
return victim;
}
public double getAmount() {
return amount;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}
@@ -17,48 +17,67 @@ public class BountySetEvent extends Event implements Cancellable {
private boolean cancelled;
public BountySetEvent(Player setter, @NotNull Player target, float amount) {
this.setter = setter;
this.target = target;
this.amount = amount;
this.cancelled = false;
}
/**
* @return The player who set the bounty or null if it's set by console/command block.
* @return The player who set the bounty or null if it's set by console/command
* block.
*/
public Player getSetter() {
return setter;
}
public Player getTarget() {
return target;
}
public float getAmount() {
public double getAmount() {
return amount;
}
public void setAmount(float amount) {
this.amount = amount;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}
}
@@ -1,14 +0,0 @@
package com.tcoded.playerbountiesplus.gui;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.InventoryHolder;
public interface IPbpGui extends InventoryHolder {
void open();
void setContents();
void handleClick(InventoryClickEvent event);
}
@@ -1,50 +1,356 @@
package com.tcoded.playerbountiesplus.gui;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.Bukkit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.function.Supplier;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
public class MainBountyGui implements IPbpGui {
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
private final PlayerBountiesPlus plugin;
import net.trueog.diamondbankog.api.DiamondBankAPIJava;
import net.trueog.gxui.GUIBase;
import net.trueog.gxui.GUIButton;
import net.trueog.gxui.GUIItem;
public class MainBountyGui extends GUIBase {
private static final List<Integer> PYRAMID_SLOTS = List.of(4, 12, 13, 14, 20, 21, 22, 23, 24, 28, 29, 30, 31, 32,
33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44);
private static final int PREVIOUS_PAGE_SLOT = 47;
private static final int PAGE_INFO_SLOT = 49;
private static final int NEXT_PAGE_SLOT = 51;
private static final int CLOSE_SLOT = 53;
private final PlayerBountiesOG plugin;
private final Player viewer;
private final Inventory inventory;
private final Supplier<List<BountyGuiEntry>> bountySupplier;
private final DiamondBankAPIJava diamondBankAPI;
private final int page;
public MainBountyGui(PlayerBountiesOG plugin, Player viewer, Supplier<List<BountyGuiEntry>> bountySupplier,
DiamondBankAPIJava diamondBankAPI)
{
this(plugin, viewer, bountySupplier, 0, diamondBankAPI);
}
private MainBountyGui(PlayerBountiesOG plugin, Player viewer, Supplier<List<BountyGuiEntry>> bountySupplier,
int page, DiamondBankAPIJava diamondBankAPITransporter)
{
super(plugin, viewer, plugin.getLang().getColored("gui.main.title"), 54, true);
public MainBountyGui(PlayerBountiesPlus plugin, Player viewer) {
this.plugin = plugin;
this.viewer = viewer;
this.bountySupplier = bountySupplier;
this.diamondBankAPI = diamondBankAPITransporter;
this.page = Math.max(0, page);
// Create inventory
this.inventory = Bukkit.createInventory(
this,
9 * 3,
plugin.getLang().getColored("gui.main.title")
);
}
@Override
public Inventory getInventory() {
return this.inventory;
}
@Override
public void open() {
setContents();
// Open the inventory for the viewer
viewer.openInventory(this.inventory);
super.open(false);
}
@Override
public void setContents() {
// TODO: Populate the inventory
public void setupItems() {
final List<BountyGuiEntry> sortedBounties = getSortedBounties();
final int maxPage = getMaxPage(sortedBounties);
final int currentPage = Math.min(page, maxPage);
addNavigationItems(currentPage, maxPage, sortedBounties.size());
if (sortedBounties.isEmpty()) {
addItem(22,
createStaticItem(Material.WRITABLE_BOOK, "&6&lNo Active Bounties",
List.of("&7Nobody currently has a bounty.", "&7Place one with your bounty command to get",
"&7this leaderboard populated again.")));
return;
}
final int startIndex = currentPage * PYRAMID_SLOTS.size();
final int endIndex = Math.min(startIndex + PYRAMID_SLOTS.size(), sortedBounties.size());
int pyramidIndex = 0;
for (int i = startIndex; i < endIndex; i++) {
final BountyGuiEntry entry = sortedBounties.get(i);
final int globalRank = i + 1;
addItem(PYRAMID_SLOTS.get(pyramidIndex), createBountyItem(entry, globalRank));
pyramidIndex++;
}
}
@Override
public void handleClick(InventoryClickEvent event) {
// TODO: Handle inventory clicks
private void addNavigationItems(int currentPage, int maxPage, int totalBounties) {
if (currentPage > 0) {
addItem(PREVIOUS_PAGE_SLOT, createButtonItem(Material.ARROW, "&a&lPrevious Page",
List.of("&7Go to page &f" + currentPage), new GUIButton()
{
@Override
public boolean leftClick() {
return openPage(currentPage - 1);
}
@Override
public boolean leftClickShift() {
return openPage(currentPage - 1);
}
@Override
public boolean rightClick() {
return openPage(currentPage - 1);
}
@Override
public boolean rightClickShift() {
return openPage(currentPage - 1);
}
}));
} else {
addItem(PREVIOUS_PAGE_SLOT,
createStaticItem(Material.GRAY_DYE, "&7Previous Page", List.of("&8Already on the first page.")));
}
addItem(PAGE_INFO_SLOT, createStaticItem(Material.BOOK, "&3&lPage " + (currentPage + 1) + "/" + (maxPage + 1),
List.of("&6Active bounties: &c" + totalBounties)));
if (currentPage < maxPage) {
addItem(NEXT_PAGE_SLOT, createButtonItem(Material.ARROW, "&a&lNext Page",
List.of("&7Go to page &f" + (currentPage + 2)), new GUIButton()
{
@Override
public boolean leftClick() {
return openPage(currentPage + 1);
}
@Override
public boolean leftClickShift() {
return openPage(currentPage + 1);
}
@Override
public boolean rightClick() {
return openPage(currentPage + 1);
}
@Override
public boolean rightClickShift() {
return openPage(currentPage + 1);
}
}));
} else {
addItem(NEXT_PAGE_SLOT,
createStaticItem(Material.GRAY_DYE, "&7Next Page", List.of("&8Already on the last page.")));
}
addItem(CLOSE_SLOT,
createButtonItem(Material.BARRIER, "&c&lClose", List.of("&7Close the bounty menu."), new GUIButton()
{
@Override
public boolean leftClick() {
viewer.closeInventory();
return true;
}
@Override
public boolean leftClickShift() {
viewer.closeInventory();
return true;
}
@Override
public boolean rightClick() {
viewer.closeInventory();
return true;
}
@Override
public boolean rightClickShift() {
viewer.closeInventory();
return true;
}
}));
}
private boolean openPage(int targetPage) {
new MainBountyGui(plugin, viewer, bountySupplier, targetPage, diamondBankAPI).open();
return true;
}
private GUIItem createBountyItem(BountyGuiEntry entry, int rank) {
final String displayName = safeDisplayName(entry.displayName());
final ArrayList<String> lore = new ArrayList<>();
lore.add("&eBounty: &b" + formatBounty(entry.bountyDiamonds()));
lore.add("");
lore.add("&6Claiming the bounty will give you a 50% chance of beheading your victim!");
final GUIItem item;
if (entry.targetName() != null && !entry.targetName().isBlank()) {
item = new GUIItem(Material.PLAYER_HEAD, 1, " &f#" + rank + " " + displayName, entry.targetName());
} else {
item = new GUIItem(Material.PAPER, 1, "&6&l#" + rank + " " + displayName);
}
item.lore(lore);
item.setPlayErrorSound(false);
return item;
}
private String formatBounty(double bountyDiamonds) {
final long shards = diamondBankAPI.diamondsToShards(bountyDiamonds);
return diamondBankAPI.shardsToDiamonds(shards) + " Diamonds";
}
private GUIItem createStaticItem(Material material, String displayName, List<String> lore) {
final GUIItem item = new GUIItem(material, 1, displayName);
item.lore(new ArrayList<>(lore));
item.setPlayErrorSound(false);
return item;
}
private GUIItem createButtonItem(Material material, String displayName, List<String> lore, GUIButton button) {
final GUIItem item = new GUIItem(material, 1, displayName);
item.lore(new ArrayList<>(lore));
item.setButton(button);
item.setPlayErrorSound(false);
return item;
}
private List<BountyGuiEntry> getSortedBounties() {
final List<BountyGuiEntry> supplied = bountySupplier.get();
if (supplied == null || supplied.isEmpty()) {
return Collections.emptyList();
}
final List<BountyGuiEntry> sorted = new ArrayList<>(supplied);
sorted.removeIf(entry -> entry == null || entry.bountyDiamonds() <= 0D);
sorted.sort(Comparator.comparingDouble(BountyGuiEntry::bountyDiamonds).reversed()
.thenComparing(entry -> safeName(entry.targetName()), String.CASE_INSENSITIVE_ORDER));
return sorted;
}
private int getMaxPage(List<BountyGuiEntry> bounties) {
if (bounties.isEmpty()) {
return 0;
}
return (bounties.size() - 1) / PYRAMID_SLOTS.size();
}
private String safeName(String name) {
if (name == null || name.isBlank()) {
return "Unknown Player";
}
return name;
}
private String safeDisplayName(String displayName) {
if (displayName == null || displayName.isBlank()) {
return "&fUnknown Player";
}
return displayName;
}
public static record BountyGuiEntry(UUID targetUuid, String targetName, String displayName, double bountyDiamonds) {
}
}
@@ -0,0 +1,149 @@
package com.tcoded.playerbountiesplus.hook.currency;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import net.trueog.diamondbankog.DiamondBankException;
import net.trueog.diamondbankog.DiamondBankException.EconomyDisabledException;
import net.trueog.diamondbankog.DiamondBankException.InsufficientFundsException;
import net.trueog.diamondbankog.DiamondBankException.InvalidPlayerException;
import net.trueog.diamondbankog.DiamondBankException.PlayerNotOnlineException;
import net.trueog.diamondbankog.api.DiamondBankAPIJava;
import net.trueog.utilitiesog.UtilitiesOG;
public class DiamondBankOGHook implements EconomyHook {
private final PlayerBountiesOG plugin;
private final DiamondBankAPIJava diamondBank;
public DiamondBankOGHook(PlayerBountiesOG plugin, DiamondBankAPIJava diamondBankAPITransporter) {
this.plugin = plugin;
this.diamondBank = diamondBankAPITransporter;
}
@Override
public boolean giveEco(Player player, Player victim, double diamonds) {
final long shards = diamondBank.diamondsToShards(diamonds);
if (shards <= 0L) {
return false;
}
try {
diamondBank.addToPlayerBankShards(
player.getUniqueId(), shards, "Player " + player.getName() + " defeated " + victim.getName()
+ " and earned a bounty of " + diamondBank.shardsToDiamonds(shards) + ".",
"Plugin: PlayerBounties-OG");
} catch (EconomyDisabledException economyDisabledError) {
PlayerBountiesOG
.disableSelf("[PlayerBounties-OG] Paying " + player.getName() + " for killing " + victim.getName()
+ " failed because the economy is disabled! " + economyDisabledError.getMessage());
economyDisabledError.printStackTrace();
return false;
}
return true;
}
@Override
public boolean takeEco(Player player, Player victim, double diamonds) {
final long shards = diamondBank.diamondsToShards(diamonds);
if (shards <= 0L) {
return false;
}
try {
diamondBank
.consumeFromPlayer(player.getUniqueId(), shards,
"Player " + player.getName() + " contributed " + diamondBank.shardsToDiamonds(shards)
+ " Diamonds toward a bounty on " + victim.getName() + ".",
"Plugin: PlayerBounties-OG");
} catch (EconomyDisabledException economyDisabledError) {
PlayerBountiesOG.disableSelf(
"[PlayerBounties-OG] DiamondBank-OG economy disabled: " + economyDisabledError.getMessage());
economyDisabledError.printStackTrace();
return false;
} catch (InvalidPlayerException invalidPlayerError) {
plugin.getLogger().warning("Invalid player for consumeFromPlayer: " + player.getName());
UtilitiesOG.trueogMessage(player,
"&cERROR: your player account could not be found by DiamondBank-OG. Contact an administrator!");
return false;
} catch (InsufficientFundsException insufficientFundsError) {
UtilitiesOG.trueogMessage(player,
"&6WARNING: You do not have enough Diamonds to contribute to that bounty.");
return false;
}
// TODO: Remove PlayerNotOnlineException catch block after next DiamondBank-OG
// update.
catch (PlayerNotOnlineException temporaryPlayerNotOnlineError) {
plugin.getLogger().warning("Player " + player.getName()
+ " not online when attempting to consumeFromPlayer. This error is expected to be removed in the next DiamondBank-OG update.");
temporaryPlayerNotOnlineError.printStackTrace();
return false;
}
return true;
}
public CompletableFuture<Long> getShardBalance(UUID uuid) {
final CompletableFuture<Long> future = new CompletableFuture<>();
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
try {
final long totalShards = diamondBank.getTotalShards(uuid);
future.complete(totalShards);
} catch (DiamondBankException.EconomyDisabledException error) {
PlayerBountiesOG
.disableSelf("The DiamondBank-OG economy is disabled — disabling " + plugin.getName() + "!");
future.completeExceptionally(error);
} catch (Throwable t) {
future.completeExceptionally(t);
}
});
return future;
}
}
@@ -1,27 +0,0 @@
package com.tcoded.playerbountiesplus.hook.currency;
import org.bukkit.entity.Player;
public class DummyEcoHook implements EconomyHook {
@Override
public boolean isValid() {
return false;
}
@Override
public void giveEco(Player player, double amount) {
throw new UnsupportedOperationException("Economy isn't setup. Dummy hook is the active fallback.");
}
@Override
public boolean takeEco(Player player, double amount) {
throw new UnsupportedOperationException("Economy isn't setup. Dummy hook is the active fallback.");
}
@Override
public boolean takeEco(Player player, double amount, boolean force) {
throw new UnsupportedOperationException("Economy isn't setup. Dummy hook is the active fallback.");
}
}
@@ -4,12 +4,8 @@ import org.bukkit.entity.Player;
public interface EconomyHook {
boolean isValid();
boolean giveEco(Player killer, Player victim, double diamonds);
void giveEco(Player player, double amount);
boolean takeEco(Player killer, Player victim, double diamonds);
boolean takeEco(Player player, double amount);
boolean takeEco(Player player, double amount, boolean force);
}
}
@@ -1,57 +0,0 @@
package com.tcoded.playerbountiesplus.hook.currency;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
public class VaultHook implements EconomyHook {
private final PlayerBountiesPlus plugin;
private Economy eco;
public VaultHook(PlayerBountiesPlus plugin) {
this.plugin = plugin;
}
public boolean init() {
if (this.plugin.getServer().getPluginManager().getPlugin("Vault") == null) {
return false;
}
RegisteredServiceProvider<Economy> rsp = this.plugin.getServer().getServicesManager().getRegistration(Economy.class);
if (rsp == null) {
return false;
}
eco = rsp.getProvider();
return true;
}
@Override
public boolean isValid() {
return eco != null;
}
@Override
public void giveEco(Player player, double amount) {
this.eco.depositPlayer(player, amount);
}
@Override
public boolean takeEco(Player player, double amount) {
return this.takeEco(player, amount, false);
}
@Override
public boolean takeEco(Player player, double amount, boolean force) {
double balance = this.eco.getBalance(player);
if (balance < amount && !force) return false;
return this.eco.withdrawPlayer(player, amount).type == EconomyResponse.ResponseType.SUCCESS;
}
}
@@ -0,0 +1,115 @@
package com.tcoded.playerbountiesplus.hook.logging;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.plugin.Plugin;
import net.coreprotect.CoreProtect;
import net.coreprotect.CoreProtectAPI;
public class CoreProtectHook {
private final CoreProtectAPI coreProtectAPI;
public CoreProtectHook(Plugin plugin) {
this.coreProtectAPI = findCoreProtect(plugin);
}
public boolean isEnabled() {
return this.coreProtectAPI != null;
}
public boolean logPlacement(String user, BlockState blockState) {
if (this.coreProtectAPI == null || user == null || blockState == null) {
return false;
}
return this.coreProtectAPI.logPlacement(user, blockState.getLocation(), blockState.getType(),
blockState.getBlockData());
}
public boolean logRemoval(String user, BlockState blockState) {
if (this.coreProtectAPI == null || user == null || blockState == null) {
return false;
}
return this.coreProtectAPI.logRemoval(user, blockState.getLocation(), blockState.getType(),
blockState.getBlockData());
}
public boolean logContainerTransaction(String user, Location location) {
if (this.coreProtectAPI == null || user == null || location == null) {
return false;
}
return this.coreProtectAPI.logContainerTransaction(user, location);
}
public boolean logInteraction(String user, Location location) {
if (this.coreProtectAPI == null || user == null || location == null) {
return false;
}
return this.coreProtectAPI.logInteraction(user, location);
}
public boolean hasPlaced(String user, Block block, int time, int offset) {
if (this.coreProtectAPI == null || user == null || block == null) {
return false;
}
return this.coreProtectAPI.hasPlaced(user, block, time, offset);
}
private static CoreProtectAPI findCoreProtect(Plugin plugin) {
if (plugin == null) {
return null;
}
final Plugin coreProtectPlugin = plugin.getServer().getPluginManager().getPlugin("CoreProtect");
if (!(coreProtectPlugin instanceof CoreProtect coreProtect)) {
return null;
}
final CoreProtectAPI api = coreProtect.getAPI();
if (api == null || !api.isEnabled() || api.APIVersion() < 11) {
return null;
}
return api;
}
}
@@ -1,15 +0,0 @@
package com.tcoded.playerbountiesplus.hook.placeholder;
public class DummyPlaceholderHook implements PlaceholderHook {
@Override
public void enable() {
}
@Override
public void disable() {
}
}
@@ -1,63 +0,0 @@
package com.tcoded.playerbountiesplus.hook.placeholder;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import me.clip.placeholderapi.PlaceholderAPIPlugin;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PlaceholderAPIHook extends PlaceholderExpansion implements PlaceholderHook {
private final PlayerBountiesPlus pbpPlugin;
public PlaceholderAPIHook(PlayerBountiesPlus pbpPlugin, Plugin papiPlugin) {
this.pbpPlugin = pbpPlugin;
if (!(papiPlugin instanceof PlaceholderAPIPlugin)) {
throw new IllegalArgumentException("Plugin is not PlaceholderAPI");
}
}
@Override
public @NotNull String getIdentifier() {
return pbpPlugin.getName().toLowerCase();
}
@Override
public @NotNull String getAuthor() {
return pbpPlugin.getDescription().getAuthors().get(0);
}
@Override
public @NotNull String getVersion() {
return pbpPlugin.getDescription().getVersion();
}
@Override
public boolean persist() {
return true;
}
@Override
public void enable() {
this.register();
}
@Override
public void disable() {
this.unregister();
}
@Override
public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
if (params.equals("bounty")) {
return String.valueOf(pbpPlugin.getBountyDataManager().getBounty(player.getUniqueId()));
} else if (params.equals("hasbounty")) {
return String.valueOf(pbpPlugin.getBountyDataManager().hasBounty(player.getUniqueId()));
}
return "INVALID-OPTION";
}
}
@@ -1,27 +0,0 @@
package com.tcoded.playerbountiesplus.hook.placeholder;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.jetbrains.annotations.NotNull;
public interface PlaceholderHook {
@NotNull
static PlaceholderHook findPlaceholderHook(PlayerBountiesPlus plugin) {
PluginManager pluginManager = plugin.getServer().getPluginManager();
Plugin papiPlugin = pluginManager.getPlugin("PlaceholderAPI");
if (papiPlugin != null) {
return new PlaceholderAPIHook(plugin, papiPlugin);
}
plugin.getLogger().warning("PlaceholderAPI not found, placeholders will be unavailable.");
return new DummyPlaceholderHook();
}
void enable();
void disable();
}
@@ -1,38 +1,57 @@
package com.tcoded.playerbountiesplus.hook.team;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.List;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
public abstract class AbstractTeamHook implements TeamHook {
protected PlayerBountiesPlus plugin;
protected PlayerBountiesOG plugin;
protected JavaPlugin teamPlugin;
public AbstractTeamHook(PlayerBountiesPlus plugin, Plugin teamPlugin) {
public AbstractTeamHook(PlayerBountiesOG plugin, Plugin teamPlugin) {
this.plugin = plugin;
this.teamPlugin = (JavaPlugin) teamPlugin;
}
@Override
public String getPluginName() {
return this.teamPlugin.getName();
}
@Override
public String getAuthor() {
List<String> authors = this.teamPlugin.getDescription().getAuthors();
if (authors.isEmpty()) return "N/A";
final List<String> authors = this.teamPlugin.getPluginMeta().getAuthors();
if (authors.isEmpty()) {
return "N/A";
}
return authors.get(0);
}
@Override
public String[] getAuthors() {
List<String> authors = this.teamPlugin.getDescription().getAuthors();
if (authors.isEmpty()) return new String[0];
final List<String> authors = this.teamPlugin.getPluginMeta().getAuthors();
if (authors.isEmpty()) {
return new String[0];
}
return authors.toArray(new String[0]);
}
}
}
@@ -1,26 +0,0 @@
package com.tcoded.playerbountiesplus.hook.team;
import com.alessiodp.parties.api.Parties;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.UUID;
public class AlessioPartiesHook extends AbstractTeamHook {
public AlessioPartiesHook(PlayerBountiesPlus plugin, Plugin partiesPlugin) {
super(plugin, partiesPlugin);
}
@Override
public boolean isFriendly(Player player1, Player player2) {
UUID uuid1 = player1.getUniqueId();
UUID uuid2 = player2.getUniqueId();
if (!Parties.getApi().isPlayerInParty(uuid1)) return false;
if (!Parties.getApi().isPlayerInParty(uuid2)) return false;
return Parties.getApi().areInTheSameParty(uuid1, uuid2);
}
}
@@ -1,22 +0,0 @@
package com.tcoded.playerbountiesplus.hook.team;
import com.booksaw.betterTeams.Team;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class BetterTeamsHook extends AbstractTeamHook {
public BetterTeamsHook(PlayerBountiesPlus plugin, Plugin teamPlugin) {
super(plugin, teamPlugin);
}
@Override
public boolean isFriendly(Player player1, Player player2) {
if (Team.getTeam(player1) == null) return false;
if (Team.getTeam(player2) == null) return false;
return Team.getTeam(player1) == Team.getTeam(player2);
}
}
@@ -1,34 +0,0 @@
package com.tcoded.playerbountiesplus.hook.team;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import me.loving11ish.clans.api.ClansLiteAPI;
import me.loving11ish.clans.api.models.Clan;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.Nullable;
public class ClansLiteHook extends AbstractTeamHook {
private final ClansLiteAPI api;
public ClansLiteHook(PlayerBountiesPlus plugin, Plugin teamPlugin) {
super(plugin, teamPlugin);
api = ClansLiteAPI.getInstance();
}
public @Nullable String getClanId(Player player) {
Clan clan = api.getClanByBukkitPlayer(player);
return clan == null ? null : clan.getClanFinalName();
}
@Override
public boolean isFriendly(Player player1, Player player2) {
String clanId1 = this.getClanId(player1);
String clanId2 = this.getClanId(player2);
if (clanId1 == null) return false;
if (clanId2 == null) return false;
return clanId1.equals(this.getClanId(player2));
}
}
@@ -1,18 +0,0 @@
package com.tcoded.playerbountiesplus.hook.team;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class PartyAndFriendsHook extends AbstractTeamHook {
public PartyAndFriendsHook(PlayerBountiesPlus plugin, Plugin teamPlugin) {
super(plugin, teamPlugin);
}
@Override
public boolean isFriendly(Player player1, Player player2) {
return false; // todo: figure out which of the 5 different APIs I'm supposed to use...
}
}
@@ -1,27 +0,0 @@
package com.tcoded.playerbountiesplus.hook.team;
import com.massivecraft.factions.FPlayers;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class SaberFactionsHook extends AbstractTeamHook {
public SaberFactionsHook(PlayerBountiesPlus plugin, Plugin teamPlugin) {
super(plugin, teamPlugin);
}
@Override
public boolean isFriendly(Player player1, Player player2) {
FPlayers fPlayers = FPlayers.getInstance();
String factionId1 = fPlayers.getByPlayer(player1).getFactionId();
String factionId2 = fPlayers.getByPlayer(player2).getFactionId();
if (factionId1 == null) return false;
if (factionId2 == null) return false;
return factionId1.equals(factionId2);
}
}
@@ -1,34 +1,48 @@
package com.tcoded.playerbountiesplus.hook.team;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import net.sacredlabyrinth.phaed.simpleclans.Clan;
import net.sacredlabyrinth.phaed.simpleclans.SimpleClans;
import net.sacredlabyrinth.phaed.simpleclans.managers.ClanManager;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.UUID;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import net.sacredlabyrinth.phaed.simpleclans.Clan;
import net.sacredlabyrinth.phaed.simpleclans.SimpleClans;
import net.sacredlabyrinth.phaed.simpleclans.managers.ClanManager;
public class SimpleClansHook extends AbstractTeamHook {
public SimpleClansHook(PlayerBountiesPlus plugin, Plugin teamPlugin) {
public SimpleClansHook(PlayerBountiesOG plugin, Plugin teamPlugin) {
super(plugin, teamPlugin);
}
@Override
public boolean isFriendly(Player player1, Player player2) {
ClanManager clanManager = SimpleClans.getInstance().getClanManager();
UUID uuid1 = player1.getUniqueId();
UUID uuid2 = player2.getUniqueId();
final ClanManager clanManager = SimpleClans.getInstance().getClanManager();
Clan clan1 = clanManager.getClanByPlayerUniqueId(uuid1);
Clan clan2 = clanManager.getClanByPlayerUniqueId(uuid2);
final UUID uuid1 = player1.getUniqueId();
final UUID uuid2 = player2.getUniqueId();
if (clan1 == null) return false;
if (clan2 == null) return false;
final Clan clan1 = clanManager.getClanByPlayerUniqueId(uuid1);
final Clan clan2 = clanManager.getClanByPlayerUniqueId(uuid2);
if (clan1 == null) {
return false;
}
if (clan2 == null) {
return false;
}
return clan1 == clan2;
}
}
}
@@ -1,54 +1,30 @@
package com.tcoded.playerbountiesplus.hook.team;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
public interface TeamHook {
static AbstractTeamHook findTeamHook(PlayerBountiesPlus plugin) {
PluginManager pluginManager = plugin.getServer().getPluginManager();
static AbstractTeamHook findTeamHook(PlayerBountiesOG plugin) {
// loving11ish - ClansLite - https://www.spigotmc.org/resources/clanslite-1-19-4-support.97163/
Plugin clansLitePlugin = pluginManager.getPlugin("ClansLite");
if (clansLitePlugin != null && clansLitePlugin.isEnabled()) {
return new ClansLiteHook(plugin, clansLitePlugin);
}
final PluginManager pluginManager = plugin.getServer().getPluginManager();
// AlessioDP - Parties - https://www.spigotmc.org/resources/parties-an-advanced-parties-manager.3709/
Plugin partiesPlugin = pluginManager.getPlugin("Parties");
if (partiesPlugin != null && partiesPlugin.isEnabled()) {
return new AlessioPartiesHook(plugin, partiesPlugin);
}
// booksaw - BetterTeams - https://www.spigotmc.org/resources/better-teams.17129/
Plugin betterTeamsPlugin = pluginManager.getPlugin("BetterTeams");
if (betterTeamsPlugin != null && betterTeamsPlugin.isEnabled()) {
return new BetterTeamsHook(plugin, betterTeamsPlugin);
}
// RoinujNosde - SimpleClans - https://www.spigotmc.org/resources/simpleclans.71242/
Plugin simpleClansPlugin = pluginManager.getPlugin("SimpleClans");
// RoinujNosde's SimpleClans: TrueOG Network branch.
// https://github.com/true-og/SimpleClans
// License: GPLv3
// (https://raw.githubusercontent.com/true-og/SimpleClans/refs/heads/master/LICENSE)
final Plugin simpleClansPlugin = pluginManager.getPlugin("SimpleClans");
if (simpleClansPlugin != null && simpleClansPlugin.isEnabled()) {
return new SimpleClansHook(plugin, simpleClansPlugin);
}
// SaberLLC - Factions (SaberFactions) - https://www.spigotmc.org/resources/simpleclans.71242/
Plugin saberFactionsPlugin = pluginManager.getPlugin("Factions");
if (saberFactionsPlugin != null &&
saberFactionsPlugin.getDescription().getMain().equals("com.massivecraft.factions.FactionsPlugin") &&
saberFactionsPlugin.isEnabled()) {
return new SaberFactionsHook(plugin, saberFactionsPlugin);
}
// LlmDl - Towny - https://www.spigotmc.org/resources/towny-advanced.72694/
Plugin townyPlugin = pluginManager.getPlugin("Towny");
if (townyPlugin != null && townyPlugin.isEnabled()) {
return new TownyHook(plugin, simpleClansPlugin);
}
return null;
}
String getPluginName();
@@ -59,4 +35,4 @@ public interface TeamHook {
boolean isFriendly(Player player1, Player player2);
}
}
@@ -1,37 +0,0 @@
package com.tcoded.playerbountiesplus.hook.team;
import com.palmergames.bukkit.towny.TownyAPI;
import com.palmergames.bukkit.towny.object.Nation;
import com.palmergames.bukkit.towny.object.Town;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class TownyHook extends AbstractTeamHook {
public TownyHook(PlayerBountiesPlus plugin, Plugin teamPlugin) {
super(plugin, teamPlugin);
}
public Town getTown(Player player) {
return TownyAPI.getInstance().getTown(player);
}
public Nation getNation(Player player) {
return TownyAPI.getInstance().getNation(player);
}
@Override
public boolean isFriendly(Player player1, Player player2) {
Town town1 = getTown(player1);
Town town2 = getTown(player2);
Nation nation1 = getNation(player1);
Nation nation2 = getNation(player2);
boolean sameTown = town1 != null && town2 != null && (town1.hasResident(player2) || town1.hasAlly(town2));
boolean sameNation = nation1 != null && nation2 != null && (nation1.equals(nation2) || nation1.hasAlly(nation2));
return sameTown || sameNation;
}
}
@@ -0,0 +1,364 @@
package com.tcoded.playerbountiesplus.listener;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.BlockState;
import org.bukkit.block.Skull;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.hook.logging.CoreProtectHook;
import net.kyori.adventure.text.TextComponent;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.cacheddata.CachedMetaData;
import net.luckperms.api.model.user.User;
import net.trueog.diamondbankog.api.DiamondBankAPIJava;
import net.trueog.utilitiesog.UtilitiesOG;
public class BountyHeadListener implements Listener {
private final DiamondBankAPIJava diamondBankAPI;
private final NamespacedKey targetKey;
private final NamespacedKey targetUuidKey;
private final NamespacedKey amountKey;
private final LuckPerms luckPerms;
private final CoreProtectHook coreProtectHook;
public BountyHeadListener(PlayerBountiesOG plugin, DiamondBankAPIJava diamondBankAPI, LuckPerms luckPerms,
CoreProtectHook coreProtectHook)
{
this.diamondBankAPI = diamondBankAPI;
this.targetKey = new NamespacedKey(plugin, DeathListener.BOUNTY_HEAD_NAME_KEY);
this.targetUuidKey = new NamespacedKey(plugin, DeathListener.BOUNTY_HEAD_UUID_KEY);
this.amountKey = new NamespacedKey(plugin, DeathListener.BOUNTY_HEAD_AMOUNT_KEY);
this.luckPerms = luckPerms;
this.coreProtectHook = coreProtectHook;
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlace(BlockPlaceEvent event) {
if (!isHeadMaterial(event.getBlockPlaced().getType())) {
return;
}
final ItemMeta itemMeta = event.getItemInHand().getItemMeta();
if (itemMeta == null) {
return;
}
final String targetName = itemMeta.getPersistentDataContainer().get(targetKey, PersistentDataType.STRING);
final String targetUuid = itemMeta.getPersistentDataContainer().get(targetUuidKey, PersistentDataType.STRING);
final Double bountyAmount = itemMeta.getPersistentDataContainer().get(amountKey, PersistentDataType.DOUBLE);
if (targetName == null || targetUuid == null || bountyAmount == null) {
return;
}
final BlockState state = event.getBlockPlaced().getState();
if (!(state instanceof Skull skull)) {
return;
}
final PersistentDataContainer blockData = skull.getPersistentDataContainer();
blockData.set(targetKey, PersistentDataType.STRING, targetName);
blockData.set(targetUuidKey, PersistentDataType.STRING, targetUuid);
blockData.set(amountKey, PersistentDataType.DOUBLE, bountyAmount);
skull.update(true, false);
if (this.coreProtectHook != null) {
this.coreProtectHook.logPlacement(event.getPlayer().getName(), skull);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBreak(BlockBreakEvent event) {
if (!isHeadMaterial(event.getBlock().getType())) {
return;
}
final BlockState state = event.getBlock().getState();
final BlockState snapshot = state;
if (!(state instanceof Skull skull)) {
return;
}
final String targetName = skull.getPersistentDataContainer().get(targetKey, PersistentDataType.STRING);
final String targetUuid = skull.getPersistentDataContainer().get(targetUuidKey, PersistentDataType.STRING);
final Double bountyAmount = skull.getPersistentDataContainer().get(amountKey, PersistentDataType.DOUBLE);
if (targetName == null || targetUuid == null || bountyAmount == null) {
return;
}
final ItemStack drop = new ItemStack(Material.PLAYER_HEAD, 1);
final SkullMeta meta = (SkullMeta) drop.getItemMeta();
meta.setPlayerProfile(skull.getPlayerProfile());
applyBountyData(meta, targetName, targetUuid, bountyAmount);
drop.setItemMeta(meta);
if (this.coreProtectHook != null) {
this.coreProtectHook.logRemoval(event.getPlayer().getName(), snapshot);
}
event.setDropItems(false);
event.getBlock().setType(Material.AIR, false);
event.getBlock().getWorld().dropItemNaturally(event.getBlock().getLocation(), drop);
}
@EventHandler(ignoreCancelled = true)
public void onRightClick(PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK) {
return;
}
final ItemStack item = event.getItem();
if (item != null && isHeadMaterial(item.getType())) {
sendBountyHeadActionbar(event.getPlayer(), item.getItemMeta());
}
if (event.getClickedBlock() == null || !isHeadMaterial(event.getClickedBlock().getType())) {
return;
}
final BlockState state = event.getClickedBlock().getState();
if (!(state instanceof Skull skull)) {
return;
}
sendBountyHeadActionbar(event.getPlayer(), skull.getPersistentDataContainer());
}
private void sendBountyHeadActionbar(Player player, ItemMeta itemMeta) {
if (itemMeta == null) {
return;
}
sendBountyHeadActionbar(player, itemMeta.getPersistentDataContainer());
}
private void sendBountyHeadActionbar(Player player, PersistentDataContainer dataContainer) {
final String targetName = dataContainer.get(targetKey, PersistentDataType.STRING);
final String targetUuid = dataContainer.get(targetUuidKey, PersistentDataType.STRING);
final Double bountyAmount = dataContainer.get(amountKey, PersistentDataType.DOUBLE);
if (targetName == null || targetUuid == null || bountyAmount == null) {
return;
}
final UUID uuid = parseUuid(targetUuid);
final String playerDisplay = formatLuckPermsDisplay(uuid, targetName);
final String diamonds = formatDiamonds(bountyAmount);
player.sendActionBar(
UtilitiesOG.trueogColorize("&cBounty Head: " + playerDisplay + " &7- &b" + diamonds + " &bDiamonds"));
}
private void applyBountyData(SkullMeta meta, String targetName, String targetUuid, double bountyAmount) {
meta.displayName(UtilitiesOG.trueogColorize("&c" + targetName + "'s Bounty Head"));
final UUID uuid = parseUuid(targetUuid);
final String playerDisplay = formatLuckPermsDisplay(uuid, targetName);
final List<TextComponent> lore = new ArrayList<>();
lore.add(UtilitiesOG.trueogColorize("&6Player: " + playerDisplay));
lore.add(UtilitiesOG.trueogColorize("&cBeheaded for: &b" + formatDiamonds(bountyAmount) + " &bDiamonds"));
meta.lore(lore);
meta.getPersistentDataContainer().set(targetKey, PersistentDataType.STRING, targetName);
meta.getPersistentDataContainer().set(targetUuidKey, PersistentDataType.STRING, targetUuid);
meta.getPersistentDataContainer().set(amountKey, PersistentDataType.DOUBLE, bountyAmount);
}
private UUID parseUuid(String uuidString) {
if (uuidString == null || uuidString.isBlank()) {
return null;
}
try {
return UUID.fromString(uuidString);
} catch (IllegalArgumentException ignored) {
return null;
}
}
private String formatLuckPermsDisplay(UUID targetUuid, String fallbackName) {
final String playerName = StringUtils.defaultIfBlank(fallbackName, "Unknown Player");
if (targetUuid == null || luckPerms == null) {
return "&f" + playerName;
}
final User user = luckPerms.getUserManager().getUser(targetUuid);
if (user == null) {
return "&f" + playerName;
}
final CachedMetaData meta = user.getCachedData().getMetaData();
final String prefix = StringUtils.trim(StringUtils.defaultString(meta.getPrefix()).replace('§', '&'));
final String suffix = StringUtils.trim(StringUtils.defaultString(meta.getSuffix()).replace('§', '&'));
final boolean metaContainsName = containsVisibleName(prefix, playerName)
|| containsVisibleName(suffix, playerName);
final StringBuilder out = new StringBuilder();
if (!prefix.isBlank()) {
out.append(prefix).append(' ');
}
if (!metaContainsName) {
out.append(playerName);
}
if (!suffix.isBlank()) {
out.append(' ').append(suffix);
}
return sanitizeDisplay(out.toString(), playerName);
}
private static String sanitizeDisplay(String formatted, String fallbackName) {
final String cleaned = StringUtils.trimToEmpty(formatted).replaceAll("(?i)(?:\\s*(?:<reset>|[&§]r))+$", "")
.replaceAll("\\s*>$", "");
if (cleaned.isBlank()) {
return fallbackName;
}
return cleaned;
}
private static boolean containsVisibleName(String text, String playerName) {
if (text == null || playerName == null || playerName.isBlank()) {
return false;
}
final String normalizedText = stripFormatting(text).toLowerCase(Locale.ROOT);
final String normalizedName = playerName.toLowerCase(Locale.ROOT);
return normalizedText.contains(normalizedName);
}
private static String stripFormatting(String input) {
if (input == null || input.isBlank()) {
return "";
}
return input.replaceAll("(?i)[&§][0-9A-FK-ORX]", "").replaceAll("<[^>]+>", "").trim();
}
private String formatDiamonds(double diamonds) {
try {
return diamondBankAPI.shardsToDiamonds(diamondBankAPI.diamondsToShards(diamonds));
} catch (RuntimeException runtimeException) {
return String.valueOf(diamonds);
}
}
private static boolean isHeadMaterial(Material material) {
return material == Material.PLAYER_HEAD || material == Material.PLAYER_WALL_HEAD;
}
}
@@ -1,93 +1,407 @@
package com.tcoded.playerbountiesplus.listener;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.event.BountyClaimEvent;
import com.tcoded.playerbountiesplus.hook.team.TeamHook;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.persistence.PersistentDataType;
import java.util.UUID;
import com.destroystokyo.paper.profile.PlayerProfile;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.event.BountyClaimEvent;
import com.tcoded.playerbountiesplus.hook.team.TeamHook;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.cacheddata.CachedMetaData;
import net.luckperms.api.model.user.User;
import net.trueog.diamondbankog.api.DiamondBankAPIJava;
import net.trueog.utilitiesog.UtilitiesOG;
public class DeathListener implements Listener {
private final PlayerBountiesPlus plugin;
public static final String BOUNTY_HEAD_NAME_KEY = "bounty_head_target";
public static final String BOUNTY_HEAD_UUID_KEY = "bounty_head_target_uuid";
public static final String BOUNTY_HEAD_AMOUNT_KEY = "bounty_head_diamonds";
private final PlayerBountiesOG plugin;
private final DiamondBankAPIJava diamondBankAPI;
private final LuckPerms luckPerms;
public DeathListener(PlayerBountiesOG plugin, DiamondBankAPIJava diamondBankAPI, LuckPerms luckPerms) {
public DeathListener(PlayerBountiesPlus plugin) {
this.plugin = plugin;
this.diamondBankAPI = diamondBankAPI;
this.luckPerms = luckPerms;
}
@EventHandler(priority = EventPriority.HIGH)
public void onDeath(PlayerDeathEvent event) {
Player victim = event.getEntity();
Player killer = victim.getKiller();
if (killer != null) {
if (!killer.hasPermission("playerbountiesplus.event.claim")) {
killer.sendMessage(plugin.getLang().getColored("death.no-permission"));
return;
}
final Player victim = event.getEntity();
final Player killer = victim.getKiller();
BountyDataManager bountyDataManager = this.plugin.getBountyDataManager();
UUID victimId = victim.getUniqueId();
if (killer == null) {
// Bounty check
if (!bountyDataManager.hasBounty(victimId)) {
return;
}
return;
int bounty = bountyDataManager.getBounty(victimId);
}
// Clan check
TeamHook teamHook = this.plugin.getTeamHook();
if (teamHook != null && teamHook.isFriendly(killer, victim)) {
killer.sendMessage(plugin.getLang().getColored("death.same-team"));
return;
}
if (!killer.hasPermission("playerbountiesplus.event.claim")) {
// Trigger Bounty Claimed Event
BountyClaimEvent claimEvent = new BountyClaimEvent(killer, victim, bounty);
this.plugin.getServer().getPluginManager().callEvent(claimEvent);
UtilitiesOG.trueogMessage(killer, plugin.getLang().getColored("death.no-permission"));
return;
// Check if event is cancelled
if (claimEvent.isCancelled()) {
return;
}
}
// Give reward!
if (plugin.getConfig().getBoolean("bounty-claimable", true)) {
double claimMultiplier = plugin.getConfig().getDouble("bounty-claim-multiplier", 1.0);
double awardedAmount = bounty * claimMultiplier;
final BountyDataManager bountyDataManager = this.plugin.getBountyDataManager();
final UUID victimId = victim.getUniqueId();
if (awardedAmount > 0) {
this.plugin.getEcoHook().giveEco(killer, awardedAmount);
} else if (awardedAmount < 0) {
this.plugin.getEcoHook().takeEco(killer, Math.abs(awardedAmount));
}
}
if (!bountyDataManager.hasBounty(victimId)) {
// Optional - Take from victim as punishment
if (plugin.getConfig().getBoolean("bounty-take-from-victim", false)) {
this.plugin.getEcoHook().takeEco(victim, bounty, true);
}
return;
// Announce Reward
if (plugin.getConfig().getBoolean("bounty-claimed-announce", true)) {
this.plugin.getServer().broadcastMessage(
plugin.getLang().getColored("death.announce-claimed")
.replace("{killer}", killer.getName())
.replace("{victim}", victim.getName())
.replace("{bounty}", String.valueOf(bounty))
);
}
}
final TeamHook teamHook = this.plugin.getTeamHook();
if (teamHook != null && teamHook.isFriendly(killer, victim)) {
UtilitiesOG.trueogMessage(killer, plugin.getLang().getColored("death.same-team"));
return;
}
final double bounty = bountyDataManager.getBounty(victimId);
if (bounty <= 0D) {
// Remove bounty
bountyDataManager.removeBounty(victimId);
bountyDataManager.saveBountiesAsync();
return;
}
final BountyClaimEvent claimEvent = new BountyClaimEvent(killer, victim, bounty);
this.plugin.getServer().getPluginManager().callEvent(claimEvent);
if (claimEvent.isCancelled()) {
return;
}
final boolean bountyClaimable = plugin.getConfig().getBoolean("bounty-claimable", true);
final double claimMultiplier = plugin.getConfig().getDouble("bounty-claim-multiplier", 1.0D);
final double awardedAmount = Math.max(0D, bounty * claimMultiplier);
if (bountyClaimable && awardedAmount > 0D) {
try {
this.plugin.getEcoHook().giveEco(killer, victim, awardedAmount);
} catch (RuntimeException runtimeException) {
plugin.getLogger().severe("Failed to award bounty payout to " + killer.getName() + " for killing "
+ victim.getName() + ": " + runtimeException.getMessage());
runtimeException.printStackTrace();
UtilitiesOG.trueogMessage(killer,
"&cAn error occurred while awarding the bounty payout. The bounty was not removed.");
return;
}
}
// Suppress the normal Minecraft death message because this death is being
// handled as a bounty claim.
event.deathMessage(null);
final String killerDisplay = formatLuckPermsDisplay(killer);
final String victimDisplay = formatLuckPermsDisplay(victim);
final boolean beheaded = maybeDropPlayerHead(event, victim, bounty);
if (beheaded) {
final String bountyDisplay = formatDiamonds(bounty);
final String beheadedMessage = killerDisplay + "&r &abeheaded " + victimDisplay + "&r &afor &b"
+ bountyDisplay + " &bDiamonds&a!";
Bukkit.getOnlinePlayers().forEach(player -> UtilitiesOG.trueogMessage(player, beheadedMessage));
playGlobalCelebrationEffects(killer, victim);
} else if (plugin.getConfig().getBoolean("bounty-claimed-announce", true)) {
final String bountyDisplay = formatDiamonds(bounty);
final String awardedDisplay = formatDiamonds(awardedAmount);
final String message;
if (bountyClaimable && awardedAmount > 0D) {
if (Double.compare(awardedAmount, bounty) == 0) {
message = killerDisplay + "&r &akilled " + victimDisplay + "&r &aand earned &b" + awardedDisplay
+ " &bDiamonds &afor the bounty!";
} else {
message = killerDisplay + "&r &akilled " + victimDisplay + "&r &aand claimed &b" + bountyDisplay
+ " &bDiamonds &afor &b" + awardedDisplay + " &bDiamonds&a!";
}
} else {
message = killerDisplay + "&r &akilled " + victimDisplay + "&r &aand claimed &b" + bountyDisplay
+ " &bDiamonds &abounty!";
}
Bukkit.getOnlinePlayers().forEach(player -> UtilitiesOG.trueogMessage(player, message));
playGlobalCelebrationEffects(killer, victim);
}
bountyDataManager.removeBounty(victimId);
bountyDataManager.saveBountiesAsync();
}
}
private void playGlobalCelebrationEffects(Player killer, Player victim) {
Bukkit.getOnlinePlayers().forEach(player -> {
player.playSound(player.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1.0F, 1.0F);
final Particle fireworkParticle = resolveFireworkParticle();
player.spawnParticle(fireworkParticle, killer.getLocation().add(0D, 1D, 0D), 40, 0.6D, 0.8D, 0.6D, 0.01D);
player.spawnParticle(fireworkParticle, victim.getLocation().add(0D, 1D, 0D), 40, 0.6D, 0.8D, 0.6D, 0.01D);
player.spawnParticle(Particle.TOTEM, killer.getLocation().add(0D, 1D, 0D), 20, 0.5D, 0.7D, 0.5D, 0.01D);
});
}
private Particle resolveFireworkParticle() {
try {
return Particle.valueOf("FIREWORK");
} catch (IllegalArgumentException exception) {
return Particle.FIREWORKS_SPARK;
}
}
private String formatDiamonds(double diamonds) {
try {
return diamondBankAPI.shardsToDiamonds(diamondBankAPI.diamondsToShards(diamonds));
} catch (RuntimeException runtimeException) {
return String.valueOf(diamonds);
}
}
private String formatLuckPermsDisplay(Player player) {
final String playerName = player.getName();
final String prefix = stripLeadingReset(stripTrailingReset(getLuckPermsPrefixLegacy(player)));
final String suffix = stripLeadingReset(stripTrailingReset(getLuckPermsSuffixLegacy(player)));
final String leadingColorCodes = extractLeadingColorCodes(prefix);
final StringBuilder out = new StringBuilder();
if (!prefix.isBlank()) {
out.append(prefix).append(" ");
}
if (leadingColorCodes.isBlank()) {
out.append(playerName);
} else {
out.append(leadingColorCodes).append(playerName);
}
if (!suffix.isBlank()) {
out.append(" ").append(suffix);
}
return out.toString();
}
private boolean maybeDropPlayerHead(PlayerDeathEvent event, Player victim, double bounty) {
final double dropChance = Math.max(0D,
Math.min(100D, plugin.getConfig().getDouble("bounty-head-drop-chance", 50D)));
if (ThreadLocalRandom.current().nextDouble(100D) >= dropChance) {
return false;
}
final ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1);
final SkullMeta headMeta = (SkullMeta) head.getItemMeta();
final PlayerProfile profile = Bukkit.createProfile(victim.getUniqueId());
headMeta.setPlayerProfile(profile);
headMeta.displayName(UtilitiesOG.trueogColorize("&c" + victim.getName() + "'s Bounty Head"));
final String bountyDisplay = formatDiamonds(bounty);
headMeta.lore(java.util.List.of(
Component.text("Target: ", NamedTextColor.GRAY)
.append(Component.text(victim.getName(), NamedTextColor.WHITE)),
Component.text("Beheaded for: ", NamedTextColor.GRAY)
.append(Component.text(bountyDisplay + " Diamonds", NamedTextColor.AQUA))));
headMeta.getPersistentDataContainer().set(new NamespacedKey(plugin, BOUNTY_HEAD_NAME_KEY),
PersistentDataType.STRING, victim.getName());
headMeta.getPersistentDataContainer().set(new NamespacedKey(plugin, BOUNTY_HEAD_UUID_KEY),
PersistentDataType.STRING, victim.getUniqueId().toString());
headMeta.getPersistentDataContainer().set(new NamespacedKey(plugin, BOUNTY_HEAD_AMOUNT_KEY),
PersistentDataType.DOUBLE, bounty);
head.setItemMeta(headMeta);
event.getDrops().add(head);
return true;
}
private String getLuckPermsSuffixLegacy(Player player) {
if (luckPerms == null) {
return "";
}
final User user = luckPerms.getUserManager().getUser(player.getUniqueId());
if (user == null) {
return "";
}
final CachedMetaData meta = user.getCachedData().getMetaData();
final String suffix = meta.getSuffix();
if (suffix == null || suffix.isBlank()) {
return "";
}
return StringUtils.trim(suffix).replace('§', '&');
}
private String getLuckPermsPrefixLegacy(Player player) {
if (luckPerms == null) {
return "";
}
final User user = luckPerms.getUserManager().getUser(player.getUniqueId());
if (user == null) {
return "";
}
final CachedMetaData meta = user.getCachedData().getMetaData();
final String prefix = meta.getPrefix();
if (prefix == null || prefix.isBlank()) {
return "";
}
return StringUtils.trim(prefix).replace('§', '&');
}
private static String stripTrailingReset(String input) {
if (input == null || input.isBlank()) {
return "";
}
return StringUtils.trim(input.replaceAll("(?i)(?:\\s*(?:<reset>|[&§]r))+$", ""));
}
private static String stripLeadingReset(String input) {
if (input == null || input.isBlank()) {
return "";
}
return StringUtils.trim(input.replaceFirst("(?i)^(?:\\s*(?:<reset>|[&§]r))+", ""));
}
private static String extractLeadingColorCodes(String input) {
if (input == null || input.length() < 2) {
return "";
}
final StringBuilder out = new StringBuilder();
for (int i = 0; i < input.length() - 1; i++) {
final char current = input.charAt(i);
if (current != '&' && current != '§') {
break;
}
out.append(current).append(input.charAt(i + 1));
i++;
}
return out.toString();
}
}
@@ -1,28 +0,0 @@
package com.tcoded.playerbountiesplus.listener;
import com.tcoded.playerbountiesplus.gui.IPbpGui;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.InventoryHolder;
public class GuiListener implements Listener {
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
// Get the inventory holder
InventoryHolder holder = event.getView().getTopInventory().getHolder();
// Ensure the holder is a GUI
if (!(holder instanceof IPbpGui gui)) {
return;
}
// Cancel normal click behaviour
event.setCancelled(true);
// Delegate the click handling
gui.handleClick(event);
}
}
@@ -0,0 +1,78 @@
package com.tcoded.playerbountiesplus.listener;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.inventory.InventoryView;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import net.trueog.utilitiesog.UtilitiesOG;
public class GuiProtectionListener implements Listener {
private final PlayerBountiesOG plugin;
public GuiProtectionListener(PlayerBountiesOG plugin) {
this.plugin = plugin;
}
@EventHandler(ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event) {
if (!isMainBountyGui(event.getView())) {
return;
}
if (event.getRawSlot() < event.getView().getTopInventory().getSize()) {
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
public void onInventoryDrag(InventoryDragEvent event) {
if (!isMainBountyGui(event.getView())) {
return;
}
final int topInventorySize = event.getView().getTopInventory().getSize();
for (int rawSlot : event.getRawSlots()) {
if (rawSlot < topInventorySize) {
event.setCancelled(true);
return;
}
}
}
private boolean isMainBountyGui(InventoryView view) {
final HumanEntity player = view.getPlayer();
if (player == null) {
return false;
}
return UtilitiesOG.stripFormatting(view.title().examinableName())
.equals(UtilitiesOG.stripFormatting(plugin.getLang().getColored("gui.main.title")));
}
}
@@ -1,112 +1,130 @@
package com.tcoded.playerbountiesplus.manager;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
public class BountyDataManager {
private final PlayerBountiesPlus plugin;
private final PlayerBountiesOG plugin;
private File bountiesFile;
private FileConfiguration bountiesConfig;
private final Object savingFileLock = new Object();
private final AtomicBoolean savingAsync = new AtomicBoolean(false);
private final ConcurrentHashMap<UUID, Integer> bounties;
private final ConcurrentHashMap<UUID, Double> bounties;
public BountyDataManager(PlayerBountiesOG plugin) {
public BountyDataManager(PlayerBountiesPlus plugin) {
this.plugin = plugin;
this.bounties = new ConcurrentHashMap<>();
}
public void init() {
// Bounties file
String bountiesFileName = "bounties.yml";
final String bountiesFileName = "bounties.yml";
bountiesFile = new File(this.plugin.getDataFolder(), bountiesFileName);
if (!bountiesFile.exists()) this.plugin.saveResource(bountiesFileName, false);
if (!bountiesFile.exists()) {
this.plugin.saveResource(bountiesFileName, false);
}
bountiesConfig = YamlConfiguration.loadConfiguration(bountiesFile);
// Load bounties
Set<String> keys = bountiesConfig.getKeys(false);
for (String key: keys) {
try {
this.bounties.put(UUID.fromString(key), bountiesConfig.getInt(key));
} catch (Exception ex) {
ex.printStackTrace();
}
}
final Set<String> keys = bountiesConfig.getKeys(false);
keys.forEach(key -> this.bounties.put(UUID.fromString(key), bountiesConfig.getDouble(key)));
}
public ConcurrentHashMap<UUID, Integer> getBounties() {
public ConcurrentHashMap<UUID, Double> getBounties() {
return this.bounties;
}
public boolean hasBounty(UUID player) {
return this.bounties.containsKey(player) && this.bounties.get(player) > 0;
}
public void setBounty(UUID player, int amount) {
public void setBounty(UUID player, double amount) {
this.bounties.put(player, amount);
}
public int getBounty(UUID player) {
return this.bounties.getOrDefault(player, 0);
public double getBounty(UUID player) {
return this.bounties.getOrDefault(player, 0.0);
}
public void removeBounty(UUID player) {
this.bounties.remove(player);
}
public void saveBounties() {
synchronized (this.savingFileLock) {
// Clear existing
Set<String> keys = bountiesConfig.getKeys(false);
for (String key : keys) {
bountiesConfig.set(key, null);
}
// Write changes
for (Map.Entry<UUID, Integer> entry : this.bounties.entrySet()) {
this.bountiesConfig.set(entry.getKey().toString(), entry.getValue());
}
final Set<String> keys = bountiesConfig.getKeys(false);
keys.forEach(key -> bountiesConfig.set(key, null));
this.bounties.entrySet()
.forEach(entry -> this.bountiesConfig.set(entry.getKey().toString(), entry.getValue()));
// Save to file
try {
this.bountiesConfig.save(this.bountiesFile);
} catch (IOException e) {
e.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
public void saveBountiesAsync() {
// Wait until the previous save is done
while (this.savingAsync.getAndSet(true)) {
try {
synchronized (this.savingAsync) {
this.savingAsync.wait();
}
} catch (InterruptedException ignored) {}
if (!this.savingAsync.compareAndSet(false, true)) {
return;
}
// Save
this.plugin.getFoliaLib().getScheduler().runAsync(wt -> {
this.saveBounties();
Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> {
try {
this.saveBounties();
} finally {
this.savingAsync.set(false);
this.savingAsync.set(false);
synchronized (this.savingAsync) {
this.savingAsync.notifyAll();
}
});
}
}
}
@@ -1,109 +1,221 @@
package com.tcoded.playerbountiesplus.util;
import com.tcoded.legacycolorcodeparser.LegacyColorCodeParser;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import org.bukkit.ChatColor;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.logging.Logger;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
public class LangUtil {
private final PlayerBountiesPlus plugin;
private static final String DEFAULT_LANG_CODE = "en_us";
private final PlayerBountiesOG plugin;
private final Logger logger;
private final File overrideMessagesFile;
private final FileConfiguration messages;
private final String lang;
private final boolean customLang;
public enum SupportedLang {
DE_DE,
EN_GB,
EN_US,
EN_UWU,
ES_ES,
FR_FR,
HI_IN,
HU_HU,
IT_IT,
NL_NL,
RU_RU,
SE_SE,
ZH_CN,
;
DE_DE, EN_GB, EN_US, EN_UWU, ES_ES, FR_FR, HI_IN, HU_HU, IT_IT, NL_NL, RU_RU, SE_SE, ZH_CN;
public static SupportedLang find(String name) {
for (SupportedLang lang : SupportedLang.values()) {
if (lang.name().equals(name)) return EN_US;
if (name == null || name.isBlank()) {
return null;
}
for (SupportedLang lang : SupportedLang.values()) {
if (StringUtils.equalsIgnoreCase(lang.name(), name)) {
return lang;
}
}
return null;
}
public String fileName() {
return StringUtils.lowerCase(this.name(), Locale.ROOT) + ".yml";
}
}
public LangUtil(PlayerBountiesPlus plugin, String lang) {
public LangUtil(PlayerBountiesOG plugin, String configuredLang) {
this.plugin = plugin;
this.lang = lang;
Logger logger = this.plugin.getLogger();
this.logger = plugin.getLogger();
// for (SupportedLang tmpLang : SupportedLang.values()) {
// plugin.saveResource("lang/" + tmpLang.name().toLowerCase() + ".yml", false);
// }
final SupportedLang resolvedLang = resolveSupportedLang(configuredLang);
this.lang = StringUtils.lowerCase(resolvedLang.name(), Locale.ROOT);
// Resolve the path of the lang files we're going to use
String englishFilePath = "lang/" + SupportedLang.EN_US.name().toLowerCase() + ".yml";
String langFilePath = "lang/" + lang + ".yml";
final String englishFilePath = "lang/" + SupportedLang.EN_US.fileName();
final String langFilePath = "lang/" + resolvedLang.fileName();
// Load internal default English file - Worst case scenario fallback
InputStream internalEnglishDefaultFile = plugin.getResource(englishFilePath);
if (internalEnglishDefaultFile == null) throw new IllegalStateException("Internal default English file could not be found!");
FileConfiguration englishDefaults = YamlConfiguration.loadConfiguration(new InputStreamReader(internalEnglishDefaultFile));
final FileConfiguration englishDefaults = loadBundledYaml(englishFilePath, true);
final FileConfiguration selectedLangDefaults = resolvedLang == SupportedLang.EN_US ? englishDefaults
: loadBundledYaml(langFilePath, false);
if (resolvedLang != SupportedLang.EN_US) {
selectedLangDefaults.setDefaults(englishDefaults);
// Check if language is supported
SupportedLang supportedLang = SupportedLang.find(lang.toUpperCase());
if (supportedLang == null) {
logger.severe(String.format("Unsupported language was found: %s!", lang));
logger.info("You can contribute new languages by following the instructions at the top of the config.yml file :)");
throw new IllegalStateException("Unsupported language in config.yml");
}
// Load user-specified internal language file
InputStream internalLangFile = plugin.getResource(langFilePath);
if (internalLangFile == null) throw new IllegalStateException(String.format("Internal language file could not be found! (Lang: %s)", lang));
FileConfiguration defaults = YamlConfiguration.loadConfiguration(new InputStreamReader(internalLangFile));
defaults.setDefaults(englishDefaults);
// Check if the user has created an override language file
this.overrideMessagesFile = new File(plugin.getDataFolder(), langFilePath);
if (this.overrideMessagesFile.exists()) {
logger.warning(String.format("Using custom override language file for language: %s", lang));
this.messages = YamlConfiguration.loadConfiguration(this.overrideMessagesFile);
this.messages.setDefaults(defaults);
this.messages.setDefaults(selectedLangDefaults);
this.customLang = true;
this.logger.warning("Using custom override language file: " + this.overrideMessagesFile.getPath());
} else {
this.messages = defaults;
this.messages = selectedLangDefaults;
this.customLang = false;
}
}
public String get(String key) {
if (this.messages == null) return "STARTUP-ERROR-CONTACT-DEV";
return this.messages.getString(key);
private SupportedLang resolveSupportedLang(String configuredLang) {
final String normalized = configuredLang == null ? DEFAULT_LANG_CODE
: StringUtils.upperCase(StringUtils.trim(configuredLang), Locale.ROOT);
final SupportedLang supportedLang = SupportedLang.find(normalized);
if (supportedLang != null) {
return supportedLang;
}
this.logger.warning("Unsupported language in config.yml: " + configuredLang + ". Falling back to "
+ DEFAULT_LANG_CODE + ".");
this.logger.info("You can contribute new languages by following the instructions at the top of config.yml.");
return SupportedLang.EN_US;
}
private FileConfiguration loadBundledYaml(String path, boolean required) {
final InputStream resource = this.plugin.getResource(path);
if (resource == null) {
if (required) {
throw new IllegalStateException("Required bundled language file could not be found: " + path);
}
this.logger.warning("Bundled language file not found: " + path + ". Falling back to English.");
return new YamlConfiguration();
}
final InputStream input = resource;
final InputStreamReader reader = new InputStreamReader(input, StandardCharsets.UTF_8);
return YamlConfiguration.loadConfiguration(reader);
}
public String getColored(String key) {
String text = this.get(key);
text = LegacyColorCodeParser.convertHexToLegacy('&', text);
return ChatColor.translateAlternateColorCodes('&', text);
if (key == null || key.isBlank()) {
return "";
}
final String value = this.messages.getString(key);
if (value != null) {
return value;
}
this.logger.warning("Missing language key: " + key + " (lang=" + this.lang + ")");
return key;
}
public List<String> getColoredList(String key) {
if (key == null || key.isBlank()) {
return Collections.emptyList();
}
if (!this.messages.contains(key)) {
this.logger.warning("Missing language list key: " + key + " (lang=" + this.lang + ")");
return List.of(key);
}
final List<String> values = this.messages.getStringList(key);
if (values == null || values.isEmpty()) {
return Collections.emptyList();
}
return new ArrayList<>(values);
}
public boolean contains(String key) {
return this.messages.contains(key);
}
public String getLang() {
return lang;
return this.lang;
}
public boolean isCustomLang() {
return customLang;
return this.customLang;
}
}
public File getOverrideMessagesFile() {
return this.overrideMessagesFile;
}
}
+4 -1
View File
@@ -36,9 +36,12 @@ bounty-claim-multiplier: 1.0
# If we should announce that the bounty was claimed
bounty-claimed-announce: true
# Chance (0-100) that claiming a bounty drops the victim's player head.
bounty-head-drop-chance: 50.0
# If we should announce that the bounty was placed
bounty-placed-announce: true
# Should the bounty money be taken from the player who dies?
# This can reduce same-team killing (or the use of alts) to claim the bounty from themselves
bounty-take-from-victim: false
bounty-take-from-victim: false
+1 -1
View File
@@ -47,7 +47,7 @@ command:
not-enough-money: "&cYou don't have enough money for that!"
internal-invalid-value: "&cAn invalid value was reached during internal processing. Please report this to an administrator!"
success: "&cYou placed a bounty of {bounty} on {target}'s head!"
announce: "\nA bounty of {bounty} was placed on {target}'s head by {player}!{extra}\n"
announce: "\nA bounty of {bounty} was placed on {target}'s &ahead by&r {player}!{extra}\n"
announce-extra: " (Total: {total})"
check:
no-player-specified: "&cYou need to specify a player! /bounty check <player>"
+11 -13
View File
@@ -1,20 +1,18 @@
name: PlayerBountiesPlus
version: '${project.version}'
main: com.tcoded.playerbountiesplus.PlayerBountiesPlus
api-version: 1.13
authors: [ TechnicallyCoded ]
description: Claim bounties only if you are not on the same clan
website: https://tcoded.com
folia-supported: true
name: PlayerBounties-OG
version: '${version}'
main: com.tcoded.playerbountiesplus.PlayerBountiesOG
api-version: '${apiVersion}'
authors: [ TechnicallyCoded, NotAlexNoyle ]
description: A player bounty plugin for TrueOG Network using our custom Diamond Economy.
website: https://github.com/true-og/PlayerBounties-OG/
folia-supported: false
depend:
- Vault
- DiamondBank-OG
softdepend:
- ClansLite
- Parties
- BetterTeams
- CoreProtect-OG
- SimpleClans
- Towny
- LuckPerms
commands:
bounty: