Compare commits

..
Author SHA1 Message Date
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
TechnicallyCoded 0bb178f344 Add README (#21) 2025-08-08 22:46:39 +02:00
TechnicallyCoded 4b739a0561 Add start of GUI framework (#20) 2025-08-08 18:45:35 +02:00
TechnicallyCoded 908f04ce30 Add %playerbountiesplus_hasbounty% placeholder (#19)
Part of #9
2025-08-08 18:00:52 +02:00
TechnicallyCoded 13b6ac5724 Add permissions for setting and claiming bounties (#18)
Fixes #4
2025-08-08 17:57:09 +02:00
TechnicallyCoded 118c78959b 1.4.17 release 2025-06-18 01:20:28 +02:00
TechnicallyCoded 5d9d070a72 Fix tab completions 2025-06-18 01:02:05 +02:00
TechnicallyCoded f57883745c Update lang files 2025-06-18 00:43:14 +02:00
TechnicallyCoded 2471003e38 Fix get lang missing 2025-06-18 00:19:53 +02:00
TechnicallyCoded a798586951 1.4.16 - Release 2025-06-17 23:46:08 +02:00
TechnicallyCoded 62891307cd Fix tab-completions 2025-06-17 23:45:53 +02:00
TechnicallyCoded 1beb8de05d Add "get" admin subcommand 2025-06-12 18:30:17 +02:00
TechnicallyCoded 8f4b0294f8 Fix permissions (part 2) 2025-06-12 18:30:00 +02:00
TechnicallyCoded e263a872b0 1.4.15 - Fix permissions 2025-06-12 18:19:04 +02:00
TechnicallyCoded 3f18f57bbf Fix friendly player team checks 2025-06-05 19:14:13 +02:00
TechnicallyCoded f947450fbe Merge pull request #16 from TechnicallyCoded/codex/add-admin-commands-for-bounties
Add admin bounty editing commands
2025-06-05 14:09:56 +02:00
TechnicallyCoded b9255ab4e9 Update sub-command name 2025-06-05 13:53:42 +02:00
TechnicallyCoded 1d8c25368a v1.4.14 - Add admin commands 2025-06-05 13:44:31 +02:00
TechnicallyCoded b07acb7f68 Merge branch 'main' into codex/add-admin-commands-for-bounties 2025-06-05 13:44:14 +02:00
TechnicallyCoded 563953088c Fix permissions indentation 2025-06-05 13:20:41 +02:00
TechnicallyCoded cf2c447c40 v1.4.13 - Add bounty events 2025-05-30 17:44:42 +02:00
TechnicallyCoded cd3e2bc2f9 v1.4.12 - Fix bounties claim check 2025-05-30 17:34:30 +02:00
TechnicallyCoded db23661546 v1.4.11 - Fix versioning 2025-03-05 22:40:32 +01:00
TechnicallyCoded 8bf198090a v1.4.11 - Update Saber-Factions 2025-01-24 23:19:13 +01:00
TechnicallyCoded 8382c46b5f v1.4.10 - Fix compilation errors 2025-01-24 22:57:25 +01:00
TechnicallyCoded a8ef396f14 Merge pull request #14 from TechnicallyCoded/dev
v1.4.9 - Merge Dev
2025-01-24 22:46:14 +01:00
71 changed files with 4674 additions and 1213 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.
+46
View File
@@ -0,0 +1,46 @@
# PlayerBounties-OG
## Overview
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 [DiamondBank-OG](https://github.com/true-og/DiamondBank-OG) and supports [SimpleClans](https://github.com/true-og/SimpleClans) for team detection.
- Inventory GUI for viewing bounties.
- Localized messages in multiple languages.
- Uses [LuckPerms](https://github.com/true-og/LuckPerms) for player name formatting.
## Commands
- `/bounty set <player> <amount>` – set a bounty on a player
- `/bounty top` – list the top bounties
- `/bounty check <player>` – check a player's bounty
- `/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 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
## Permissions
| Permission | Default |
| --- | --- |
| `playerbountiesplus.command.bounty` | all |
| `playerbountiesplus.command.bounty.set` | all |
| `playerbountiesplus.event.claim` | all |
| `playerbountiesplus.command.admin` | op |
| `playerbountiesplus.command.admin.version` | op |
| `playerbountiesplus.command.admin.reload` | op |
| `playerbountiesplus.command.admin.bounty.set` | op |
| `playerbountiesplus.command.admin.bounty.add` | op |
| `playerbountiesplus.command.admin.bounty.remove` | op |
| `playerbountiesplus.command.admin.bounty.delete` | op |
| `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 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
+148
View File
@@ -0,0 +1,148 @@
/* 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/") }
}
/* ---------------------- 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.
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 ebd8df041e.
+1
Submodule libs/Utilities-OG added at 3705eafbc3.
-195
View File
@@ -1,195 +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.9</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>devmart-other</id>
<url>https://nexuslite.gcnt.net/repos/other/</url>
</repository>
<repository>
<id>devmart-public</id>
<url>https://nexuslite.gcnt.net/repos/public/</url>
</repository>
<repository>
<id>devmart-tcoded</id>
<url>https://nexuslite.gcnt.net/repos/tcoded/</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.tcoded</groupId>
<artifactId>FoliaLib</artifactId>
<version>0.2.6</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.tcoded.lightlibs</groupId>
<artifactId>SpigotUpdateChecker</artifactId>
<version>1.1.2</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.2-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,292 @@
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.currency.EconomyHook;
import com.tcoded.playerbountiesplus.hook.team.TeamHook;
import com.tcoded.playerbountiesplus.listener.DeathListener;
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;
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.");
}
// 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);
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;
}
// 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,222 +0,0 @@
package com.tcoded.playerbountiesplus;
import com.google.common.collect.ImmutableList;
import com.tcoded.folialib.FoliaLib;
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.manager.BountyDataManager;
import com.tcoded.playerbountiesplus.util.LangUtil;
import com.tcoded.updatechecker.SimpleUpdateChecker;
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);
}
// Listener
this.getServer().getPluginManager().registerEvents(new DeathListener(this), 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().getImpl().runAsync(runnable)
);
}
@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,9 +1,9 @@
package com.tcoded.playerbountiesplus.command;
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 java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@@ -12,74 +12,113 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
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"));
final Player player;
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), "&cERROR: Only players can use this command.");
return true;
} else {
player = (Player) sender;
}
String action = args[0].toLowerCase();
if (args.length < 1) {
UtilitiesOG.trueogMessage(player, plugin.getLang().getColored("command.bounty.no-action"));
return true;
}
final String action = args[0].toLowerCase();
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) {
@Nullable List<String> options = new ArrayList<>();
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())).collect(Collectors.toList());
} else if (args.length > 1) {
final String subCommand = args[0].toLowerCase();
return switch (subCommand) {
case "set" -> BountySetCmd.onTabComplete(sender, args).stream()
.filter(suggestion -> suggestion.toLowerCase().startsWith(args[1].toLowerCase()))
.collect(Collectors.toList());
case "check" -> BountyCheckCmd.onTabComplete(sender, args).stream()
.filter(suggestion -> suggestion.toLowerCase().startsWith(args[1].toLowerCase()))
.collect(Collectors.toList());
case "top" -> Collections.emptyList();
default -> Collections.emptyList();
};
if (args.length < 2) {
String arg0 = args[0].toLowerCase();
String[] actions = {"set", "top", "check"};
for (String action : actions) {
if (action.startsWith(arg0)) {
options.add(action);
}
}
}
else if (args.length == 2) {
String arg0 = args[0].toLowerCase();
String arg1 = args[1].toLowerCase();
if (arg0.equals("set") || arg0.equals("check")) {
this.plugin.getServer().getOnlinePlayers().stream()
.map(Player::getName)
.filter(name -> name.toLowerCase().startsWith(arg1))
.forEach(options::add);
}
}
else if (args.length == 3) {
String arg0 = args[0].toLowerCase();
String arg2 = args[2].toLowerCase();
if (arg0.equals("set")) {
if (arg2.equals("")) options.add("<amount>");
}
}
return options;
return Collections.emptyList();
}
}
}
@@ -1,66 +1,120 @@
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 org.bukkit.ChatColor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
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 java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
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", "help");
private final PlayerBountiesPlus plugin;
private static final ArrayList<String> completions = Lists.newArrayList("reload", "version", "bounty", "help");
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 = args[0].toLowerCase();
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);
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 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) {
return completions.stream()
.filter(s -> s.startsWith(args[0].toLowerCase()))
.collect(Collectors.toList());
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()))
.collect(Collectors.toList());
} else if (args.length > 1) {
final String subCommand = args[0].toLowerCase();
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,31 +1,74 @@
package com.tcoded.playerbountiesplus.command.admin;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
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;
public class PlayerBountiesPlusReloadCmd {
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.
return Collections.emptyList();
}
}
@@ -1,34 +1,58 @@
package com.tcoded.playerbountiesplus.command.admin;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.util.LangUtil;
import org.bukkit.ChatColor;
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.
return Collections.emptyList();
}
}
@@ -0,0 +1,155 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
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(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (!sender.hasPermission(PERMISSION)) {
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) {
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;
}
final String playerName = args[2];
final int amount;
try {
amount = Integer.parseInt(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;
}
final OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
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;
}
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();
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;
}
@Nullable
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());
} else if (args.length == 4) {
// Suggest a placeholder for the amount.
return Collections.singletonList("<amount>");
}
return Collections.emptyList();
}
}
@@ -0,0 +1,96 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
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(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (args.length < 2) {
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;
}
final String action = args[1].toLowerCase();
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) {
final String sub = args[1].toLowerCase();
switch (sub) {
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);
}
}
final String input = args[args.length - 1].toLowerCase();
return suggestions.stream().filter(opt -> opt.toLowerCase().startsWith(input)).collect(Collectors.toList());
}
}
@@ -0,0 +1,121 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
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 AdminBountyDeleteCmd {
private static final String PERMISSION = "playerbountiesplus.command.admin.bounty.delete";
public static boolean handleCmd(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (!sender.hasPermission(PERMISSION)) {
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) {
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;
}
final String playerName = args[2];
final OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
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;
}
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);
}
return true;
}
@Nullable
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());
}
return Collections.emptyList();
}
}
@@ -0,0 +1,120 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
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(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (!sender.hasPermission(PERMISSION)) {
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) {
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;
}
final String playerName = args[2];
final OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
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;
}
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);
}
return true;
}
@Nullable
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());
}
return Collections.emptyList();
}
}
@@ -0,0 +1,163 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
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(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (!sender.hasPermission(PERMISSION)) {
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) {
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;
}
final String playerName = args[2];
final int amount;
try {
amount = Integer.parseInt(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;
}
final OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
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;
}
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();
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;
}
@Nullable
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());
} else if (args.length == 4) {
// Suggest a placeholder for the amount.
return Collections.singletonList("<amount>");
}
return Collections.emptyList();
}
}
@@ -0,0 +1,149 @@
package com.tcoded.playerbountiesplus.command.admin.bounty;
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(PlayerBountiesOG plugin, CommandSender sender, Command cmd, String label,
String[] args)
{
if (!sender.hasPermission(PERMISSION)) {
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) {
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;
}
final String playerName = args[2];
final int amount;
try {
amount = Integer.parseInt(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;
}
final OfflinePlayer target = plugin.getServer().getOfflinePlayer(playerName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
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;
}
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);
}
return true;
}
@Nullable
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());
} else if (args.length == 4) {
// Suggest a placeholder for the amount.
return Collections.singletonList("<amount>");
}
return Collections.emptyList();
}
}
@@ -1,50 +1,120 @@
package com.tcoded.playerbountiesplus.command.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.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.UUID;
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())).collect(Collectors.toList());
}
return Collections.emptyList();
}
}
@@ -1,111 +1,288 @@
package com.tcoded.playerbountiesplus.command.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.Bukkit;
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.UUID;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
import com.tcoded.playerbountiesplus.event.BountySetEvent;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
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;
}
String playerNameArg = args[1];
float amount;
if (sender instanceof Player && !sender.hasPermission("playerbountiesplus.command.bounty.set")) {
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");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noPermDetailed);
} else {
UtilitiesOG.trueogMessage((Player) sender, noPermDetailed);
}
return true;
}
final String playerNameArg = args[1];
final double parsedAmount;
try {
amount = Integer.parseInt(args[2]);
} catch (NumberFormatException ex) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.amount-nan"));
parsedAmount = Integer.parseInt(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;
}
Player target = plugin.getServer().getPlayerExact(playerNameArg);
final Player target = plugin.getServer().getPlayerExact(playerNameArg);
if (target == null) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.player-not-found"));
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
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))
);
// 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;
}
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))
);
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;
}
// Check money
if (sender instanceof Player) {
Player player = (Player) sender;
boolean allowed = plugin.getEcoHook().takeEco(player, amount);
// 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.
if (event.isCancelled()) {
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.
if (amount <= 0) {
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;
}
// Check economy. Only charge if sender is a player.
if (sender instanceof Player player) {
final boolean allowed = plugin.getEcoHook().takeEco(player, target, amount);
if (!allowed) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.not-enough-money"));
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;
}
}
// Apply bounty multiplier
amount *= (float) plugin.getConfig().getDouble("bounty-multiplier", 1.0);
final UUID playerUUID = target.getUniqueId();
// Sanity check final amount
if (amount <= 0) {
sender.sendMessage(plugin.getLang().getColored("command.bounty.set.internal-invalid-value"));
return true;
}
UUID playerUUID = target.getUniqueId();
// Calculate total bounty including previous bounties
BountyDataManager bountyDataManager = plugin.getBountyDataManager();
int bountyAlreadyPresent = bountyDataManager.getBounty(playerUUID);
int totalBounty = ((int) amount) + bountyAlreadyPresent;
// Calculate total bounty including previous bounties.
final BountyDataManager bountyDataManager = plugin.getBountyDataManager();
final double bountyAlreadyPresent = bountyDataManager.getBounty(playerUUID);
final double chargeAndBountyAmount = (int) amount;
final double totalBounty = chargeAndBountyAmount + bountyAlreadyPresent;
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())
);
// Confirmation.
final String bountySetSuccessMessage = plugin.getLang().getColored("command.bounty.set.success")
.replace("{bounty}", String.valueOf(chargeAndBountyAmount))
.replace("{total}", String.valueOf(totalBounty)).replace("{target}", target.getName())
.replace("{player}", sender.getName());
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), bountySetSuccessMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, bountySetSuccessMessage);
}
// Announcement.
final String extra;
if (bountyAlreadyPresent == 0) {
extra = "";
} else {
extra = plugin.getLang().getColored("command.bounty.set.announce-extra").replace("{total}",
String.valueOf(totalBounty));
// 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)
);
Bukkit.getOnlinePlayers()
.forEach((Player player) -> UtilitiesOG.trueogMessage(player,
plugin.getLang().getColored("command.bounty.set.announce")
.replace("{bounty}", String.valueOf(chargeAndBountyAmount))
.replace("{target}", target.getName()).replace("{player}", sender.getName())
.replace("{extra}", extra)));
}
bountyDataManager.saveBountiesAsync();
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())).collect(Collectors.toList());
} else if (args.length == 3) {
// Suggest a placeholder for the amount.
return Collections.singletonList("<amount>");
}
return Collections.emptyList();
}
}
@@ -1,47 +1,133 @@
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.Set;
import java.util.UUID;
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.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");
new MainBountyGui(plugin, player, () -> buildGuiEntries(plugin), 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";
}
entries.add(new MainBountyGui.BountyGuiEntry(entry.getKey(), targetName, entry.getValue()));
}
return entries;
}
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 - ");
strb.append(targetName);
strb.append(": ");
strb.append(formattedBounty);
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 = message.substring(0, message.length() - 1);
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), message);
} else {
UtilitiesOG.trueogMessage((Player) sender, message);
}
}
}
}
@@ -0,0 +1,73 @@
package com.tcoded.playerbountiesplus.event;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BountyClaimEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Player claimant;
private final Player victim;
private final double amount;
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;
}
}
@@ -0,0 +1,83 @@
package com.tcoded.playerbountiesplus.event;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public class BountySetEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Player setter;
private final Player target;
private float amount;
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.
*/
public Player getSetter() {
return setter;
}
public Player getTarget() {
return target;
}
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;
}
}
@@ -0,0 +1,358 @@
package com.tcoded.playerbountiesplus.gui;
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 java.util.regex.Pattern;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import com.tcoded.playerbountiesplus.PlayerBountiesOG;
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 static final Pattern MINECRAFT_USERNAME_PATTERN = Pattern.compile("^[A-Za-z0-9_]{1,16}$");
private final PlayerBountiesOG plugin;
private final Player viewer;
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);
this.plugin = plugin;
this.viewer = viewer;
this.bountySupplier = bountySupplier;
this.diamondBankAPI = diamondBankAPITransporter;
this.page = Math.max(0, page);
}
public void open() {
super.open(false);
}
@Override
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, "&e&lNo Active Bounties",
List.of("&7Nobody currently has a bounty.", "&7Place one with your bounty command to get",
"&7this leaderboard moving 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++;
}
}
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, "&e&lPage " + (currentPage + 1) + "/" + (maxPage + 1),
List.of("&7Active bounties: &f" + totalBounties, "&7Shown per page: &f" + PYRAMID_SLOTS.size(),
"&7Sorted from highest to lowest.")));
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 targetName = safeName(entry.targetName());
final ArrayList<String> lore = new ArrayList<>();
lore.add("&7Rank: &f#" + rank);
lore.add("&7Target: &f" + targetName);
lore.add("&7Bounty: &6" + formatBounty(entry.bountyDiamonds()));
lore.add("");
lore.add("&8Highest bounty sits at the top.");
final GUIItem item;
if (isUsableHeadName(targetName)) {
item = new GUIItem(Material.PLAYER_HEAD, 1, "&6&l#" + rank + " &f" + targetName, targetName);
} else {
item = new GUIItem(Material.PAPER, 1, "&6&l#" + rank + " &f" + targetName);
}
item.lore(lore);
item.setPlayErrorSound(false);
return item;
}
private String formatBounty(double bountyDiamonds) {
final long shards = diamondBankAPI.diamondsToShards(bountyDiamonds);
return diamondBankAPI.shardsToDiamonds(shards);
}
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 boolean isUsableHeadName(String name) {
return name != null && !name.isBlank() && !"Unknown Player".equals(name)
&& MINECRAFT_USERNAME_PATTERN.matcher(name).matches();
}
public static record BountyGuiEntry(UUID targetUuid, String targetName, 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;
}
}
@@ -1,15 +0,0 @@
package com.tcoded.playerbountiesplus.hook.placeholder;
public class DummyPlaceholderHook implements PlaceholderHook {
@Override
public void enable() {
}
@Override
public void disable() {
}
}
@@ -1,61 +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()));
}
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,18 +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;
public class AlessioPartiesHook extends AbstractTeamHook {
public AlessioPartiesHook(PlayerBountiesPlus plugin, Plugin partiesPlugin) {
super(plugin, partiesPlugin);
}
@Override
public boolean isFriendly(Player player1, Player player2) {
return Parties.getApi().areInTheSameParty(player1.getUniqueId(), player2.getUniqueId());
}
}
@@ -1,19 +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) {
return Team.getTeam(player1) == Team.getTeam(player2);
}
}
@@ -1,29 +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 clanIdVictim = this.getClanId(player1);
return clanIdVictim != null && clanIdVictim.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,22 +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();
return factionId1.equals(factionId2);
}
}
@@ -1,21 +1,48 @@
package com.tcoded.playerbountiesplus.hook.team;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import net.sacredlabyrinth.phaed.simpleclans.SimpleClans;
import net.sacredlabyrinth.phaed.simpleclans.managers.ClanManager;
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();
return clanManager.getClanByPlayerUniqueId(player1.getUniqueId()) == clanManager.getClanByPlayerUniqueId(player2.getUniqueId());
final ClanManager clanManager = SimpleClans.getInstance().getClanManager();
final UUID uuid1 = player1.getUniqueId();
final UUID uuid2 = player2.getUniqueId();
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,34 +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 town = getTown(player1);
Nation player1Nation = getNation(player1);
Nation player2Nation = getNation(player2);
boolean sameTown = town != null && town.hasResident(player2);
boolean sameNation = player1Nation != null && player1Nation.equals(player2Nation);
return sameTown || sameNation;
}
}
@@ -1,78 +1,269 @@
package com.tcoded.playerbountiesplus.listener;
import com.tcoded.playerbountiesplus.PlayerBountiesPlus;
import com.tcoded.playerbountiesplus.hook.team.TeamHook;
import com.tcoded.playerbountiesplus.manager.BountyDataManager;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
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 java.util.UUID;
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.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;
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) {
BountyDataManager bountyDataManager = this.plugin.getBountyDataManager();
UUID victimId = victim.getUniqueId();
final Player victim = event.getEntity();
final Player killer = victim.getKiller();
// Bounty check
if (bountyDataManager.hasBounty(victimId)) {
return;
}
if (killer == null) {
int bounty = bountyDataManager.getBounty(victimId);
return;
// Clan check
TeamHook teamHook = this.plugin.getTeamHook();
if (teamHook != null && teamHook.isFriendly(killer, victim)) {
killer.sendMessage(plugin.getLang().getColored("death.same-team"));
return;
}
}
// Give reward!
if (plugin.getConfig().getBoolean("bounty-claimable", true)) {
double claimMultiplier = plugin.getConfig().getDouble("bounty-claim-multiplier", 1.0);
double awardedAmount = bounty * claimMultiplier;
if (!killer.hasPermission("playerbountiesplus.event.claim")) {
if (awardedAmount > 0) {
this.plugin.getEcoHook().giveEco(killer, awardedAmount);
} else if (awardedAmount < 0) {
this.plugin.getEcoHook().takeEco(killer, Math.abs(awardedAmount));
}
}
UtilitiesOG.trueogMessage(killer, plugin.getLang().getColored("death.no-permission"));
return;
// Optional - Take from victim as punishment
if (plugin.getConfig().getBoolean("bounty-take-from-victim", false)) {
this.plugin.getEcoHook().takeEco(victim, bounty, true);
}
}
// 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 BountyDataManager bountyDataManager = this.plugin.getBountyDataManager();
final UUID victimId = victim.getUniqueId();
if (!bountyDataManager.hasBounty(victimId)) {
return;
}
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;
}
}
if (plugin.getConfig().getBoolean("bounty-claimed-announce", true)) {
final String killerDisplay = formatLuckPermsDisplay(killer);
final String victimDisplay = formatLuckPermsDisplay(victim);
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 + " &akilled " + victimDisplay + " &aand earned the &b" + awardedDisplay
+ " &abounty!";
} else {
message = killerDisplay + " &akilled " + victimDisplay + " &aand claimed the &b" + bountyDisplay
+ " &abounty for &b" + awardedDisplay + "&a!";
}
} else {
message = killerDisplay + " &akilled " + victimDisplay + " &aand claimed the &b" + bountyDisplay
+ " &abounty!";
}
Bukkit.getOnlinePlayers().forEach(player -> UtilitiesOG.trueogMessage(player, message));
}
bountyDataManager.removeBounty(victimId);
bountyDataManager.saveBountiesAsync();
}
}
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 prefix = stripLeadingReset(stripTrailingReset(getLuckPermsPrefixLegacy(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 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,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().getImpl().runAsync(() -> {
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,220 @@
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.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 (lang.name().equalsIgnoreCase(name)) {
return lang;
}
}
return null;
}
public String fileName() {
return this.name().toLowerCase(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 = resolvedLang.name().toLowerCase(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
: configuredLang.trim().toUpperCase(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;
}
}
+25
View File
@@ -1,6 +1,7 @@
death:
same-team: "&aDer Spieler, den du getötet hast, hat eine aktive Belohnung, aber du bist im selben Team wie er!"
announce-claimed: "&4&l{killer} hat die Belohnung von {victim} im Wert von ${bounty} beansprucht"
no-permission: "&cSie dürfen keine Kopfgelder beanspruchen!"
command:
no-permission: "&cDu hast keine Berechtigung, diesen Befehl zu verwenden!"
@@ -10,6 +11,30 @@ command:
reloaded: "&aDie Konfigurationsdateien wurden erfolgreich neu geladen!"
version:
no-permission: "&7(Version nicht sichtbar: Fehlende Berechtigung)"
bounty:
set:
missing-args: "&cBenutzung: /pbp bounty set <Spieler> <Betrag>"
amount-nan: "&cDas ist keine gültige Zahl!"
player-not-found: "&cDieser Spieler ist nicht online oder existiert nicht!"
success: "&aBelohnung für {target} auf {bounty} gesetzt."
add:
missing-args: "&cBenutzung: /pbp bounty add <Spieler> <Betrag>"
amount-nan: "&cDas ist keine gültige Zahl!"
player-not-found: "&cDieser Spieler ist nicht online oder existiert nicht!"
success: "&a{amount} zur Belohnung von {target} hinzugefügt. Gesamt: {total}."
remove:
missing-args: "&cBenutzung: /pbp bounty remove <Spieler> <Betrag>"
amount-nan: "&cDas ist keine gültige Zahl!"
player-not-found: "&cDieser Spieler ist nicht online oder existiert nicht!"
success: "&a{amount} von der Belohnung von {target} entfernt. Gesamt: {total}."
delete:
missing-args: "&cBenutzung: /pbp bounty delete <Spieler>"
player-not-found: "&cDieser Spieler ist nicht online oder existiert nicht!"
success: "&aBelohnung für {target} gelöscht."
get:
missing-args: "&cBenutzung: /pbp bounty get <Spieler>"
player-not-found: "&cDieser Spieler ist nicht online oder existiert nicht!"
success: "&a{target} hat derzeit eine Belohnung von {bounty}."
bounty:
no-action: "&cDu musst eine Aktion angeben! /bounty <set/top/check>"
invalid-action: "&cDas ist keine gültige Aktion!"
+26 -1
View File
@@ -1,6 +1,7 @@
death:
same-team: "&aThe player you killed has an active bounty but you are in the same team as they are!"
announce-claimed: "&4&l{killer} claimed {victim}'s bounty worth ${bounty}"
no-permission: "&cYou are not allowed to claim bounties!"
command:
no-permission: "&cYou don't have the permission to use this command!"
@@ -10,6 +11,30 @@ command:
reloaded: "&aSuccessfully reloaded the configuration files!"
version:
no-permission: "&7(Version not visible: Missing permission)"
bounty:
set:
missing-args: "&cUsage: /pbp bounty set <player> <amount>"
amount-nan: "&cThat's not a valid number!"
player-not-found: "&cThat player is not online or doesn't exist!"
success: "&aSet {target}'s bounty to {bounty}."
add:
missing-args: "&cUsage: /pbp bounty add <player> <amount>"
amount-nan: "&cThat's not a valid number!"
player-not-found: "&cThat player is not online or doesn't exist!"
success: "&aAdded {amount} bounty to {target}. Total: {total}."
remove:
missing-args: "&cUsage: /pbp bounty remove <player> <amount>"
amount-nan: "&cThat's not a valid number!"
player-not-found: "&cThat player is not online or doesn't exist!"
success: "&aRemoved {amount} bounty from {target}. Total: {total}."
delete:
missing-args: "&cUsage: /pbp bounty delete <player>"
player-not-found: "&cThat player is not online or doesn't exist!"
success: "&aDeleted bounty for {target}."
get:
missing-args: "&cUsage: /pbp bounty get <player>"
player-not-found: "&cThat player is not online or doesn't exist!"
success: "&a{target} currently has a bounty of {bounty}."
bounty:
no-action: "&cYou need to specify an action! /bounty <set/top/check>"
invalid-action: "&cThat's not a valid action!"
@@ -31,4 +56,4 @@ command:
bounty-found: "&aThere is a bounty worth {bounty} on {target}'s head!"
top:
top-10: "&eTop 10 bounties:"
no-bounties: "&r &cNo bounties were set!"
no-bounties: "&r &cNo bounties were set!"
+31 -1
View File
@@ -1,6 +1,7 @@
death:
same-team: "&aThe player you killed has an active bounty but you are in the same team as they are!"
announce-claimed: "&4&l{killer} claimed {victim}'s bounty worth ${bounty}"
no-permission: "&cYou are not allowed to claim bounties!"
command:
no-permission: "&cYou don't have the permission to use this command!"
@@ -10,6 +11,30 @@ command:
reloaded: "&aSuccessfully reloaded the configuration files!"
version:
no-permission: "&7(Version not visible: Missing permission)"
bounty:
set:
missing-args: "&cUsage: /pbp bounty set <player> <amount>"
amount-nan: "&cThat's not a valid number!"
player-not-found: "&cThat player is not online or doesn't exist!"
success: "&aSet {target}'s bounty to {bounty}."
add:
missing-args: "&cUsage: /pbp bounty add <player> <amount>"
amount-nan: "&cThat's not a valid number!"
player-not-found: "&cThat player is not online or doesn't exist!"
success: "&aAdded {amount} bounty to {target}. Total: {total}."
remove:
missing-args: "&cUsage: /pbp bounty remove <player> <amount>"
amount-nan: "&cThat's not a valid number!"
player-not-found: "&cThat player is not online or doesn't exist!"
success: "&aRemoved {amount} bounty from {target}. Total: {total}."
delete:
missing-args: "&cUsage: /pbp bounty delete <player>"
player-not-found: "&cThat player is not online or doesn't exist!"
success: "&aDeleted bounty for {target}."
get:
missing-args: "&cUsage: /pbp bounty get <player>"
player-not-found: "&cThat player is not online or doesn't exist!"
success: "&a{target} currently has a bounty of {bounty}."
bounty:
no-action: "&cYou need to specify an action! /bounty <set/top/check>"
invalid-action: "&cThat's not a valid action!"
@@ -31,4 +56,9 @@ command:
bounty-found: "&aThere is a bounty worth {bounty} on {target}'s head!"
top:
top-10: "&eTop 10 bounties:"
no-bounties: "&r &cNo bounties were set!"
no-bounties: "&r &cNo bounties were set!"
gui:
main:
title: "&eBounties"
+1
View File
@@ -1,6 +1,7 @@
death:
same-team: "&aDa pwayer you kiwwed has an active bounty but you awe in da same team as they awe!"
announce-claimed: "&4&w{killer} cwaimed {victim}'s bounty wowth ${bounty}"
no-permission: "&cYou awe nyot awwowed to cwaim bounties!"
command:
no-permission: "&cYou don't have da pewmission to use this command!"
+28 -3
View File
@@ -1,15 +1,40 @@
death:
same-team: "&aEl jugador que mataste tiene una recompensa activa pero estás en el mismo equipo que él."
announce-claimed: "&4&l{killer} reclamó la recompensa de {victim} valorada en ${bounty}"
no-permission: "&c¡No se le permite reclamar recompensas!"
command:
no-permission: "&cNo tienes permiso para usar este comando."
no-permission-detailed: "{no-permission-msg} &7({permission})"
admin:
reload:
reloaded: "&aLos archivos de configuración se han recargado con éxito."
reloaded: "&a¡Archivos de configuración recargados con éxito!"
version:
no-permission: "&7(Versión no visible: Permiso faltante)"
no-permission: "&7(Versión no visible: Falta permiso)"
bounty:
set:
missing-args: "&cUso: /pbp bounty set <jugador> <cantidad>"
amount-nan: "&c¡Ese no es un número válido!"
player-not-found: "&c¡Ese jugador no está en línea o no existe!"
success: "&aSe ha establecido la recompensa de {target} en {bounty}."
add:
missing-args: "&cUso: /pbp bounty add <jugador> <cantidad>"
amount-nan: "&c¡Ese no es un número válido!"
player-not-found: "&c¡Ese jugador no está en línea o no existe!"
success: "&aSe ha añadido una recompensa de {amount} a {target}. Total: {total}."
remove:
missing-args: "&cUso: /pbp bounty remove <jugador> <cantidad>"
amount-nan: "&c¡Ese no es un número válido!"
player-not-found: "&c¡Ese jugador no está en línea o no existe!"
success: "&aSe ha eliminado una recompensa de {amount} de {target}. Total: {total}."
delete:
missing-args: "&cUso: /pbp bounty delete <jugador>"
player-not-found: "&c¡Ese jugador no está en línea o no existe!"
success: "&aRecompensa eliminada para {target}."
get:
missing-args: "&cUso: /pbp bounty get <jugador>"
player-not-found: "&c¡Ese jugador no está en línea o no existe!"
success: "&a{target} actualmente tiene una recompensa de {bounty}."
bounty:
no-action: "&cDebes especificar una acción! /bounty <set/top/check>"
invalid-action: "&cEsa no es una acción válida."
@@ -31,4 +56,4 @@ command:
bounty-found: "&aHay una recompensa valorada en {bounty} en la cabeza de {target}."
top:
top-10: "&eLos 10 mejores recompensas:"
no-bounties: "&r &cNo se han establecido recompensas."
no-bounties: "&r &cNo se han establecido recompensas."
+40 -1
View File
@@ -1,6 +1,7 @@
death:
same-team: "&aLe joueur que vous avez tué a une prime sur sa tête mais vous êtes dans la même équipe!"
announce-claimed: "&4&l{killer} a gagné la prime de {victim} au prix de ${bounty}"
no-permission: "&cVous n'êtes pas autorisé à réclamer des primes!"
command:
no-permission: "&cVous n'avez pas la permission d'utiliser cette commande!"
@@ -10,6 +11,30 @@ command:
reloaded: "&aLes fichiers de configuration ont été mis à jour avec succès!"
version:
no-permission: "&7(Version non visible: Permission manquante)"
bounty:
set:
missing-args: "&cUtilisation : /pbp bounty set <joueur> <montant>"
amount-nan: "&cCe n'est pas un nombre valide !"
player-not-found: "&cCe joueur n'est pas en ligne ou n'existe pas !"
success: "&aPrime de {target} définie à {bounty}."
add:
missing-args: "&cUtilisation : /pbp bounty add <joueur> <montant>"
amount-nan: "&cCe n'est pas un nombre valide !"
player-not-found: "&cCe joueur n'est pas en ligne ou n'existe pas !"
success: "&aAjouté {amount} de prime à {target}. Total : {total}."
remove:
missing-args: "&cUtilisation : /pbp bounty remove <joueur> <montant>"
amount-nan: "&cCe n'est pas un nombre valide !"
player-not-found: "&cCe joueur n'est pas en ligne ou n'existe pas !"
success: "&aRetiré {amount} de la prime de {target}. Total : {total}."
delete:
missing-args: "&cUtilisation : /pbp bounty delete <joueur>"
player-not-found: "&cCe joueur n'est pas en ligne ou n'existe pas !"
success: "&aPrime supprimée pour {target}."
get:
missing-args: "&cUtilisation : /pbp bounty get <joueur>"
player-not-found: "&cCe joueur n'est pas en ligne ou n'existe pas !"
success: "&a{target} a actuellement une prime de {bounty}."
bounty:
no-action: "&cVous devez spécifier une action! /bounty <set/top/check>"
invalid-action: "&cCeci n'est pas une action valable!"
@@ -24,6 +49,20 @@ command:
success: "&cVous avez placé une prime de {bounty} sur la tête de {target}!"
announce: "\nUne prime de {bounty} a été placée sur la tête de {target} par {player}!{extra}\n"
announce-extra: " (Total: {total})"
add:
missing-args: "&cUtilisation : /pbp bounty add <joueur> <montant>"
amount-nan: "&cCe n'est pas un nombre valide !"
player-not-found: "&cCe joueur n'est pas en ligne ou n'existe pas !"
success: "&aAjouté {amount} de prime à {target}. Total : {total}."
remove:
missing-args: "&cUtilisation : /pbp bounty remove <joueur> <montant>"
amount-nan: "&cCe n'est pas un nombre valide !"
player-not-found: "&cCe joueur n'est pas en ligne ou n'existe pas !"
success: "&aRetiré {amount} de la prime de {target}. Total : {total}."
delete:
missing-args: "&cUtilisation : /pbp bounty delete <joueur>"
player-not-found: "&cCe joueur n'est pas en ligne ou n'existe pas !"
success: "&aPrime supprimée pour {target}."
check:
no-player-specified: "&cVous devez spécifier un joueur! /bounty check <player>"
player-not-found: "&cCe joueur n'est pas en ligne ou n'existe pas"
@@ -31,4 +70,4 @@ command:
bounty-found: "&aIl y a une prime de {bounty} sur la tête de {target}!"
top:
top-10: "&eLes top 10 primes:"
no-bounties: "&r &cAucune prime n'a été placée!"
no-bounties: "&r &cAucune prime n'a été placée!"
+1
View File
@@ -1,6 +1,7 @@
death:
same-team: "&aवह खिलाड़ी जिसे आपने मार डाला है, उसके पास एक सक्रिय इनाम है, लेकिन आप उनकी टीम में हैं!"
announce-claimed: "&4&l{killer} ने {victim} के इनाम {bounty} को मांग लिया"
no-permission: "&cआपको इनामों का दावा करने की अनुमति नहीं है!"
command:
no-permission: "&cआपके पास इस कमांड का उपयोग करने की अनुमति नहीं है!"
+1
View File
@@ -5,6 +5,7 @@
death:
same-team: "&aA játékos, akit megöltél, aktív fejpénzt volt a fején, de ugyanabba a csapatba tartozol, mint ő!"
announce-claimed: "&4&l{killer} behajtotta {victim} fejpénzét és megkapta jutalmát aminek értéke: ${bounty}"
no-permission: "&cNem igényelheted a fejpénzeket!"
command:
no-permission: "&cNincs jogosultságod ennek a parancsnak a használatához!"
+25
View File
@@ -1,6 +1,7 @@
death:
same-team: "&aIl giocatore che hai ucciso ha una taglia attiva, ma sei nella stessa squadra!"
announce-claimed: "&4&l{killer} ha reclamato la taglia di {victim} del valore di ${bounty}"
no-permission: "&cNon ti è permesso riscuotere le taglie!"
command:
no-permission: "&cNon hai il permesso di utilizzare questo comando!"
@@ -10,6 +11,30 @@ command:
reloaded: "&aHai ricaricato con successo i file di configurazione!"
version:
no-permission: "&7(Versione non visibile: Permesso mancante)"
bounty:
set:
missing-args: "&cUso: /pbp bounty set <giocatore> <quantità>"
amount-nan: "&cQuesto non è un numero valido!"
player-not-found: "&cQuesto giocatore non è online o non esiste!"
success: "&aTaglia di {bounty} impostata per {target}."
add:
missing-args: "&cUso: /pbp bounty add <giocatore> <quantità>"
amount-nan: "&cQuesto non è un numero valido!"
player-not-found: "&cQuesto giocatore non è online o non esiste!"
success: "&aAggiunta una taglia di {amount} a {target}. Totale: {total}."
remove:
missing-args: "&cUso: /pbp bounty remove <giocatore> <quantità>"
amount-nan: "&cQuesto non è un numero valido!"
player-not-found: "&cQuesto giocatore non è online o non esiste!"
success: "&aRimossa una taglia di {amount} da {target}. Totale: {total}."
delete:
missing-args: "&cUso: /pbp bounty delete <giocatore>"
player-not-found: "&cQuesto giocatore non è online o non esiste!"
success: "&aTaglia eliminata per {target}."
get:
missing-args: "&cUso: /pbp bounty get <giocatore>"
player-not-found: "&cQuesto giocatore non è online o non esiste!"
success: "&a{target} ha attualmente una taglia di {bounty}."
bounty:
no-action: "&cDevi specificare un'azione! /bounty <set/top/check>"
invalid-action: "&cQuesta non è un'azione valida!"
+27 -2
View File
@@ -1,15 +1,40 @@
death:
same-team: "&aDe speler die je hebt gedood heeft een actieve beloning, maar je zit in hetzelfde team als zij!"
announce-claimed: "&4&l{killer} heeft de beloning van {victim} ter waarde van ${bounty} geclaimd"
no-permission: "&cU mag geen premies claimen!"
command:
no-permission: "&cJe hebt geen toestemming om deze opdracht te gebruiken!"
no-permission-detailed: "{no-permission-msg} &7({permission})"
admin:
reload:
reloaded: "&aDe configuratiebestanden zijn succesvol herladen!"
reloaded: "&aConfiguratiebestanden succesvol herladen!"
version:
no-permission: "&7(Versie niet zichtbaar: Ontbrekende toestemming)"
no-permission: "&7(Versie niet zichtbaar: Ontbrekend recht)"
bounty:
set:
missing-args: "&cGebruik: /pbp bounty set <speler> <bedrag>"
amount-nan: "&cDat is geen geldig getal!"
player-not-found: "&cDie speler is niet online of bestaat niet!"
success: "&aDe premie van {target} is ingesteld op {bounty}."
add:
missing-args: "&cGebruik: /pbp bounty add <speler> <bedrag>"
amount-nan: "&cDat is geen geldig getal!"
player-not-found: "&cDie speler is niet online of bestaat niet!"
success: "&a{amount} premie toegevoegd aan {target}. Totaal: {total}."
remove:
missing-args: "&cGebruik: /pbp bounty remove <speler> <bedrag>"
amount-nan: "&cDat is geen geldig getal!"
player-not-found: "&cDie speler is niet online of bestaat niet!"
success: "&a{amount} premie verwijderd van {target}. Totaal: {total}."
delete:
missing-args: "&cGebruik: /pbp bounty delete <speler>"
player-not-found: "&cDie speler is niet online of bestaat niet!"
success: "&aPremie verwijderd voor {target}."
get:
missing-args: "&cGebruik: /pbp bounty get <speler>"
player-not-found: "&cDie speler is niet online of bestaat niet!"
success: "&a{target} heeft momenteel een premie van {bounty}."
bounty:
no-action: "&cJe moet een actie specificeren! /beloning <zet/hoogte/controle>"
invalid-action: "&cDit is geen geldige actie!"
+25
View File
@@ -1,6 +1,7 @@
death:
same-team: "&aИгрок, которого вы убили, имеет активную награду, но вы находитесь в одной команде с ними!"
announce-claimed: "&4&l{killer} получил награду {victim} на сумму ${bounty}"
no-permission: "&cВам не разрешено требовать наград!"
command:
no-permission: "&cУ вас нет разрешения использовать эту команду!"
@@ -10,6 +11,30 @@ command:
reloaded: "&aКонфигурационные файлы успешно перезагружены!"
version:
no-permission: "&7(Версия не видна: Отсутствует разрешение)"
bounty:
set:
missing-args: "&cИспользование: /pbp bounty set <игрок> <сумма>"
amount-nan: "&cЭто не число!"
player-not-found: "&cЭтот игрок не в сети или не существует!"
success: "&aНаграда {target} установлена на {bounty}."
add:
missing-args: "&cИспользование: /pbp bounty add <игрок> <сумма>"
amount-nan: "&cЭто не число!"
player-not-found: "&cЭтот игрок не в сети или не существует!"
success: "&aДобавлено {amount} к награде {target}. Всего: {total}."
remove:
missing-args: "&cИспользование: /pbp bounty remove <игрок> <сумма>"
amount-nan: "&cЭто не число!"
player-not-found: "&cЭтот игрок не в сети или не существует!"
success: "&aУдалено {amount} из награды {target}. Всего: {total}."
delete:
missing-args: "&cИспользование: /pbp bounty delete <игрок>"
player-not-found: "&cЭтот игрок не в сети или не существует!"
success: "&aНаграда для {target} удалена."
get:
missing-args: "&cИспользование: /pbp bounty get <игрок>"
player-not-found: "&cЭтот игрок не в сети или не существует!"
success: "&aУ {target} сейчас награда {bounty}."
bounty:
no-action: "&cВы должны указать действие! /bounty <set/top/check>"
invalid-action: "&cЭто недопустимое действие!"
+25
View File
@@ -1,6 +1,7 @@
death:
same-team: "&aDen spelare du dödade har en aktiv prissumma, men du tillhör samma lag som de är!"
announce-claimed: "&4&l{killer} har tagit {victim}s prissumma värd {bounty} dollar"
no-permission: "&cDu får inte hämta in prissummor!"
command:
no-permission: "&cDu har inte behörighet att använda detta kommando!"
@@ -10,6 +11,30 @@ command:
reloaded: "&aKonfigurationsfilerna har laddats om framgångsrikt!"
version:
no-permission: "&7(Version ej synlig: Saknad behörighet)"
bounty:
set:
missing-args: "&cAnvändning: /pbp bounty set <spelare> <summa>"
amount-nan: "&cDet är inte ett giltigt nummer!"
player-not-found: "&cDen spelaren är inte online eller existerar inte!"
success: "&aPrissumman för {target} har satts till {bounty}."
add:
missing-args: "&cAnvändning: /pbp bounty add <spelare> <summa>"
amount-nan: "&cDet är inte ett giltigt nummer!"
player-not-found: "&cDen spelaren är inte online eller existerar inte!"
success: "&aLade till {amount} i prissumma för {target}. Totalt: {total}."
remove:
missing-args: "&cAnvändning: /pbp bounty remove <spelare> <summa>"
amount-nan: "&cDet är inte ett giltigt nummer!"
player-not-found: "&cDen spelaren är inte online eller existerar inte!"
success: "&aTog bort {amount} från prissumman för {target}. Totalt: {total}."
delete:
missing-args: "&cAnvändning: /pbp bounty delete <spelare>"
player-not-found: "&cDen spelaren är inte online eller existerar inte!"
success: "&aPrissumman för {target} har tagits bort."
get:
missing-args: "&cAnvändning: /pbp bounty get <spelare>"
player-not-found: "&cDen spelaren är inte online eller existerar inte!"
success: "&a{target} har för närvarande en prissumma på {bounty}."
bounty:
no-action: "&cDu måste ange en åtgärd! /bounty <set/top/check>"
invalid-action: "&cDet är inte en giltig åtgärd!"
+26
View File
@@ -1,6 +1,7 @@
death:
same-team: "&a你击杀的玩家有悬赏,但你与他们在同一队伍中!"
announce-claimed: "&4&l{killer} 已领取 {victim} 的悬赏,价值 ${bounty}"
no-permission: "&c你没有权限领取悬赏!"
command:
no-permission: "&c你没有权限使用此命令!"
@@ -10,6 +11,30 @@ command:
reloaded: "&a成功重新加载配置文件!"
version:
no-permission: "&7(无法查看版本:缺少权限)"
bounty:
set:
missing-args: "&c用法:/pbp bounty set <玩家> <金额>"
amount-nan: "&c这不是一个有效的数字!"
player-not-found: "&c该玩家不在线或不存在!"
success: "&a已将 {target} 的悬赏设置为 {bounty}。"
add:
missing-args: "&c用法:/pbp bounty add <玩家> <金额>"
amount-nan: "&c这不是一个有效的数字!"
player-not-found: "&c该玩家不在线或不存在!"
success: "&a已为 {target} 增加了 {amount} 悬赏。总计:{total}。"
remove:
missing-args: "&c用法:/pbp bounty remove <玩家> <金额>"
amount-nan: "&c这不是一个有效的数字!"
player-not-found: "&c该玩家不在线或不存在!"
success: "&a已为 {target} 移除了 {amount} 悬赏。总计:{total}。"
delete:
missing-args: "&c用法:/pbp bounty delete <玩家>"
player-not-found: "&c该玩家不在线或不存在!"
success: "&a已删除 {target} 的悬赏。"
get:
missing-args: "&c用法:/pbp bounty get <玩家>"
player-not-found: "&c该玩家不在线或不存在!"
success: "&a{target} 当前有一个悬赏,金额为 {bounty}。"
bounty:
no-action: "&c你需要指定一个操作!/bounty <set/top/check>"
invalid-action: "&c这不是一个有效的操作!"
@@ -32,3 +57,4 @@ command:
top:
top-10: "&e前10名悬赏:"
no-bounties: "&r &c没有设置悬赏!"
+23 -18
View File
@@ -1,34 +1,39 @@
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
- SimpleClans
- Towny
- LuckPerms
commands:
bounty:
permission: playerbountiesplus.command.bounty
aliases: [bounties, prime, primes]
playerbountiesplusadmin:
permission: playerbountiesplus.command.admin
aliases: [playerbountiesplus, pbpa, pbp]
permissions:
playerbountiesplus.command.bounty:
default: true
playerbountiesplus.command.playerbountiesplus:
playerbountiesplus.command.admin:
default: op
children:
playerbountiesplus.command.playerbountiesplus.version:
default: true
playerbountiesplus.command.playerbountiesplus.reload:
default: op
playerbountiesplus.command.admin.version: {}
playerbountiesplus.command.admin.reload: {}
playerbountiesplus.command.admin.bounty.set: {}
playerbountiesplus.command.admin.bounty.add: {}
playerbountiesplus.command.admin.bounty.remove: {}
playerbountiesplus.command.admin.bounty.delete: {}
playerbountiesplus.command.bounty.set:
default: true
playerbountiesplus.event.claim:
default: true