9
0
mirror of https://github.com/Auxilor/EcoJobs.git synced 2025-12-20 15:39:26 +00:00

Compare commits

..

157 Commits

Author SHA1 Message Date
Will FP
4257c45920 libreforge-updater 2025-10-06 08:56:29 +01:00
Will FP
8a05885940 Merge remote-tracking branch 'origin/develop' 2025-09-26 16:16:04 +01:00
Will FP
42033f31b6 libreforge-updater 2025-09-11 09:57:55 +01:00
Exanthiax
662e978cbf Improved EcoJobs top placeholder and added new /jobs top command 2025-08-27 18:57:43 +01:00
Exanthiax
ec8ddba84c fixed level-xp-requirements ignoring first few values 2025-08-27 18:51:51 +01:00
Will FP
d5eea9549f libreforge-updater 2025-08-01 10:03:49 +01:00
Will FP
744f5bf4b0 Merge pull request #37 from Exanthiax/master
Update Job.kt
2025-08-01 09:40:03 +01:00
Exanthiax
1a6c879305 Update Job.kt 2025-07-16 18:32:52 +01:00
Will FP
682446aa90 libreforge-updater 2025-07-05 16:44:53 +01:00
Will FP
2e2f44a387 libreforge-updater 2025-07-04 09:49:51 +01:00
Will FP
ec1fe90c8c libreforge-updater 2025-03-29 14:21:51 +00:00
Will FP
7420415514 Merge pull request #33 from Exanthiax/reset-all-command
added "all" args to reset command
2025-03-29 14:18:16 +00:00
Will FP
11bce9975d Merge pull request #34 from Exanthiax/level-up-effects
added level-up-effects
2025-03-29 14:18:00 +00:00
Will FP
013d8a0068 Merge branch 'master' into level-up-effects 2025-03-29 14:17:28 +00:00
Will FP
338c1c3499 Merge pull request #35 from Exanthiax/trigger-effects
added join-effects and leave-effects
2025-03-29 14:16:40 +00:00
Exanthiax
cdcc45aef8 update all current jobs 2025-03-09 22:52:32 +00:00
Exanthiax
533d036a18 moved below placeholders 2025-02-04 23:12:04 +00:00
Exanthiax
03e99e2e1e updated ymls 2025-02-04 23:05:41 +00:00
Exanthiax
86b7ad2971 added level-up-effects
added `level-up-effects`
deprecated `level-commands` with message
2025-02-04 21:39:57 +00:00
Exanthiax
7065642d97 Update _example.yml 2025-02-04 18:04:56 +00:00
Exanthiax
e6c486bc3a added join-effects and leave-effects 2025-02-04 18:02:48 +00:00
Exanthiax
c99769a1e3 added "all" args
Within reset command, you can now use "all" as player or job.
Added new lang messages accordingly.
2025-01-31 13:38:06 +00:00
Will FP
6fc1ba72d8 libreforge-updater 2025-01-31 11:53:47 +00:00
Will FP
b08687eba2 Merge pull request #31 from Penumbrae/patch-1
Wrong usage of a filter
2025-01-31 11:41:53 +00:00
Will FP
8cd544b327 Merge pull request #32 from Exanthiax/new-xp-methods
New xp methods
2025-01-31 11:41:44 +00:00
Exanthiax
5d40c32c1e Fixed xp-required and placeholders. 2025-01-28 23:35:34 +00:00
Exanthiax
ee155ccca6 Update _example.yml 2025-01-28 20:04:22 +00:00
Exanthiax
acdb4d0f78 added xp-formula and max-level 2025-01-28 19:45:56 +00:00
Will FP
b99a72808c libreforge-updater 2025-01-25 13:49:33 +00:00
Will FP
6bd56c8d95 Fix 2025-01-25 13:48:09 +00:00
Will FP
e90f321517 libreforge-updater 2025-01-25 13:45:31 +00:00
Penumbrae
4c021781e5 Wrong usage of a filter
This job had the filter "items" to filter pickaxes, which doesn't work in this case. This essentially means that the players would be able to earn money and xp by breaking a block in any way.

Changed it to the in_mainhand condition.
2025-01-25 00:37:55 +00:00
Will FP
abfce4428f libreforge-updater 2024-11-06 18:31:32 +00:00
Will FP
d7b7f6895e libreforge-updater 2024-10-22 12:12:52 +01:00
Will FP
2a97bc2d29 libreforge-updater 2024-09-22 16:58:16 +01:00
Auxilor
af4d3058e8 libreforge-updater 2024-09-02 11:29:55 +01:00
Auxilor
802360e885 libreforge-updater 2024-08-30 17:24:55 +01:00
Auxilor
79a396f5d3 libreforge-updater 2024-08-29 12:09:03 +01:00
Auxilor
e264e49b05 libreforge-updater 2024-08-23 15:35:08 +01:00
Auxilor
d9263bcb53 libreforge-updater 2024-08-21 18:58:06 +01:00
Auxilor
4681bd63e1 libreforge-updater 2024-08-15 15:07:19 +01:00
Auxilor
998e25e7ec libreforge-updater 2024-08-03 13:41:10 +01:00
Auxilor
f1f7ec5afd libreforge-updater 2024-07-25 10:04:20 +01:00
Auxilor
875928b4c2 libreforge-updater 2024-07-21 12:19:05 +01:00
Auxilor
049cb72385 libreforge-updater 2024-07-19 20:28:24 +01:00
Auxilor
b7decc9eb8 libreforge-updater 2024-07-18 13:23:59 +01:00
Auxilor
44c59de546 libreforge-updater 2024-07-16 17:13:29 +01:00
Auxilor
fdbbf8102c libreforge-updater 2024-07-13 20:45:06 +01:00
Auxilor
cf7084fd44 libreforge-updater 2024-07-08 15:58:17 +01:00
Auxilor
fa4e0dc67a libreforge-updater 2024-07-05 13:02:32 +01:00
Auxilor
210a6e821e libreforge-updater 2024-07-03 17:43:43 +01:00
Auxilor
b520442dee libreforge-updater 2024-06-29 16:43:48 +01:00
Auxilor
58966f04ff libreforge-updater 2024-06-28 15:56:11 +01:00
Auxilor
4588122b20 libreforge-updater 2024-06-27 18:54:14 +01:00
Auxilor
b98ee1d0dc libreforge-updater 2024-06-26 16:52:06 +01:00
Auxilor
929e6d59d8 libreforge-updater 2024-06-25 15:13:45 +01:00
Auxilor
e6884a0320 libreforge-updater 2024-06-24 15:06:21 +01:00
Auxilor
569f63e22d Updated to Java 21 2024-06-24 14:00:38 +01:00
Auxilor
49aecb54bf libreforge-updater 2024-06-23 17:26:20 +01:00
Auxilor
da80fbdcce libreforge-updater 2024-06-23 13:18:38 +01:00
Will FP
c66919ec49 libreforge-updater 2024-05-31 20:35:53 +01:00
Will FP
117f412ed3 libreforge-updater 2024-05-11 18:20:35 +01:00
Will FP
1bd643eb8a libreforge-updater 2024-04-17 20:32:58 +01:00
Auxilor
2eb7625711 libreforge-updater 2024-04-15 18:19:26 +01:00
Auxilor
48b86099c9 libreforge-updater 2024-04-11 13:17:25 +01:00
Auxilor
966051bc21 libreforge-updater 2024-03-29 16:08:35 +00:00
Will FP
442ea73366 libreforge-updater 2024-03-11 17:36:28 +00:00
Will FP
52a6b45c85 libreforge-updater 2024-03-10 20:07:46 +00:00
Will FP
dfff7c339c libreforge-updater 2024-03-02 15:19:29 +00:00
Will FP
eb13e26512 libreforge-updater 2024-02-22 13:16:51 +00:00
Will FP
7219918101 libreforge-updater 2024-02-15 13:00:56 +00:00
Will FP
92787738b6 libreforge-updater 2024-02-08 19:47:41 +00:00
Will FP
05cf850aab libreforge-updater 2024-01-30 11:25:31 +00:00
Will FP
ac9f26bcce libreforge-updater 2024-01-18 17:01:43 +00:00
Will FP
72f30769ad libreforge-updater 2024-01-16 13:25:44 +00:00
Will FP
7282046ba0 libreforge-updater 2024-01-13 14:22:59 +00:00
Will FP
0646965c9f libreforge-updater 2024-01-07 13:50:30 +00:00
Will FP
243407ce3c libreforge-updater 2024-01-06 09:18:30 +00:00
Auxilor
1e2b101011 libreforge-updater 2024-01-04 17:25:16 +00:00
Auxilor
ecf99839bf libreforge-updater 2024-01-01 20:02:16 +00:00
Will FP
b414ff57ab libreforge-updater 2023-12-27 14:15:49 +01:00
Will FP
a476fac03e libreforge-updater 2023-12-24 14:54:07 +01:00
Auxilor
50b42f38ba libreforge-updater 2023-12-20 15:57:06 +00:00
Will FP
08d5fa6b0c libreforge-updater 2023-12-14 16:12:08 +00:00
Will FP
c3febb89ec libreforge-updater 2023-12-11 12:11:41 +00:00
Will FP
7e3ba5293f libreforge-updater 2023-12-07 17:23:58 +00:00
Will FP
19ef0341fa libreforge-updater 2023-12-03 15:57:13 +00:00
Will FP
1bfaf7f7e1 libreforge-updater 2023-11-30 14:26:14 +00:00
Will FP
827f8430e1 libreforge-updater 2023-11-26 23:23:30 +00:00
Will FP
6192ce5bb6 libreforge-updater 2023-11-23 13:20:15 +00:00
Auxilor
fe59c30f52 libreforge-updater 2023-11-21 22:40:38 +00:00
Auxilor
7763ea48fd libreforge-updater 2023-11-19 14:13:20 +00:00
Auxilor
aef5d348bc libreforge-updater 2023-11-17 19:01:23 +00:00
Auxilor
d0bf9c848b libreforge-updater 2023-11-11 17:57:58 +00:00
Auxilor
6468ba5312 libreforge-updater 2023-11-10 13:58:22 +00:00
Auxilor
649253b82a libreforge-updater 2023-11-05 13:40:57 +00:00
Auxilor
e2cafdf031 libreforge-updater 2023-10-30 13:30:02 +00:00
Auxilor
3bc5661ea6 Updated to 3.37.2 2023-10-30 12:50:20 +00:00
Auxilor
c83bf6e607 The Job level GUI title is now customisable 2023-10-30 12:50:10 +00:00
Auxilor
b161bc4adf libreforge-updater 2023-10-28 14:14:29 +01:00
Auxilor
30af9048af libreforge-updater 2023-10-24 15:37:59 +01:00
Auxilor
8cb2fd8700 libreforge-updater 2023-10-19 12:51:32 +01:00
Auxilor
e0efc21da9 libreforge-updater 2023-10-14 14:19:51 +01:00
Auxilor
24951ea269 libreforge-updater 2023-10-14 14:17:54 +01:00
Auxilor
1041aa6f5f libreforge-updater 2023-10-02 11:52:57 +01:00
Auxilor
691e08fb44 libreforge-updater 2023-09-26 14:43:48 +01:00
Auxilor
f049f31778 libreforge-updater 2023-09-20 15:32:48 +01:00
Auxilor
01d24cd517 libreforge-updater 2023-09-17 11:19:20 +01:00
Auxilor
12c4d1938f libreforge-updater 2023-09-13 15:07:52 +01:00
Auxilor
edc1f58b40 libreforge-updater 2023-09-07 16:01:46 +01:00
Auxilor
9c0a8ee1dc libreforge-updater 2023-09-02 17:34:33 +01:00
Auxilor
8315707aed libreforge-updater 2023-08-31 16:59:34 +01:00
Auxilor
1f1ece53ce libreforge-updater 2023-08-30 11:31:28 +01:00
Auxilor
92af313c43 Added use-local-storage 2023-08-30 09:49:12 +01:00
Auxilor
0d207545b8 libreforge-updater 2023-08-26 18:11:33 +01:00
Auxilor
83ece163c0 libreforge-updater 2023-08-23 15:31:48 +01:00
Auxilor
608c16d554 libreforge-updater 2023-08-19 15:32:41 +01:00
Auxilor
fd6f525a65 libreforge-updater 2023-08-15 18:50:13 +01:00
Auxilor
9c01b582eb libreforge-updater 2023-08-13 14:42:40 +01:00
Auxilor
30ae94e8e2 libreforge-updater 2023-08-10 19:59:29 +01:00
Auxilor
9e15f12800 libreforge-updater 2023-08-10 19:57:27 +01:00
Auxilor
aaf922c79a libreforge-updater 2023-08-09 15:58:38 +01:00
Auxilor
4008d0a9d0 libreforge-updater 2023-08-09 14:40:33 +01:00
Auxilor
7cbcbaad8d libreforge-updater 2023-08-09 14:37:18 +01:00
Auxilor
496dff834d libreforge-updater 2023-08-08 17:59:18 +01:00
Auxilor
d81e03ef6f libreforge-updater 2023-08-05 21:06:57 +01:00
Auxilor
85a6a03d41 libreforge-updater 2023-07-27 15:21:35 +01:00
Auxilor
6f78e4b704 libreforge-updater 2023-07-27 15:18:43 +01:00
Auxilor
2656156bcf libreforge-updater 2023-07-25 14:38:13 +01:00
Auxilor
4e3d419e53 libreforge-updater 2023-07-23 11:40:21 +01:00
Auxilor
436b176e36 libreforge-updater 2023-07-22 14:59:42 +01:00
Auxilor
efb8bda519 libreforge-updater 2023-07-21 12:32:56 +01:00
Auxilor
097582fe5e libreforge-updater 2023-07-20 13:06:54 +01:00
Auxilor
1a6a8b3e38 libreforge-updater 2023-07-19 14:14:47 +01:00
Auxilor
3f54f8af2d libreforge-updater 2023-07-17 18:32:24 +01:00
Auxilor
94ca19447f libreforge-updater 2023-07-16 13:33:11 +01:00
Auxilor
2d67115569 libreforge-updater 2023-07-12 13:07:18 +01:00
Auxilor
6e9e9b000f libreforge-updater 2023-07-09 17:24:37 +01:00
Auxilor
a34727feb5 libreforge-updater 2023-07-06 18:46:59 +01:00
Auxilor
b744fbfe2d libreforge-updater 2023-07-04 14:49:45 +01:00
Auxilor
2db3a90049 libreforge-updater 2023-06-27 10:41:45 +01:00
Auxilor
466f80f860 libreforge-updater 2023-06-21 10:22:36 +01:00
Auxilor
2f177f34f1 libreforge-updater 2023-06-19 11:11:32 +02:00
Will FP
2c2b008678 Create CODEOWNERS 2023-06-17 21:22:31 +02:00
Auxilor
9c26ba3b91 libreforge-updater 2023-06-10 13:32:36 +01:00
Auxilor
1c16e52b97 libreforge-updater 2023-06-05 16:26:02 +01:00
Auxilor
f6fe3477c6 Fixed Publications 2023-06-03 18:03:16 +01:00
Auxilor
ee3298d260 libreforge-updater 2023-06-03 15:44:50 +01:00
Auxilor
65dcbf2d98 libreforge-updater 2023-06-01 12:32:47 +01:00
Auxilor
cba4ed6e49 libreforge-updater 2023-05-30 16:09:51 +01:00
Auxilor
241435dafe libreforge-updater 2023-05-24 14:57:27 +01:00
Auxilor
84277d5b68 libreforge-updater 2023-05-23 16:11:17 +01:00
Auxilor
6f63dd2af6 libreforge-updater 2023-05-20 17:40:09 +01:00
Auxilor
7b577dca25 libreforge-updater 2023-05-18 16:24:52 +01:00
Auxilor
59a5bcb68d libreforge-updater 2023-05-17 15:56:32 +01:00
Auxilor
6592a6ff73 libreforge-updater 2023-05-16 20:29:31 +01:00
Auxilor
c9c82e4591 libreforge-updater 2023-05-15 10:51:56 +01:00
44 changed files with 591 additions and 250 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @WillFP

View File

@@ -15,11 +15,11 @@ jobs:
- name: Checkout latest code
uses: actions/checkout@v2
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: 17
java-version: 21
- name: Change wrapper permissions
run: chmod +x ./gradlew

View File

@@ -1,9 +1,11 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
java
`java-library`
`maven-publish`
kotlin("jvm") version "1.7.10"
id("com.github.johnrengelman.shadow") version "8.0.0"
kotlin("jvm") version "2.1.0"
id("com.gradleup.shadow") version "8.3.0"
id("com.willfp.libreforge-gradle-plugin") version "1.0.0"
}
@@ -25,7 +27,7 @@ allprojects {
apply(plugin = "java")
apply(plugin = "kotlin")
apply(plugin = "maven-publish")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "com.gradleup.shadow")
repositories {
mavenLocal()
@@ -37,14 +39,14 @@ allprojects {
}
dependencies {
compileOnly("com.willfp:eco:6.55.0")
compileOnly("com.willfp:eco:6.56.0")
compileOnly("org.jetbrains:annotations:23.0.0")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.7.10")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
}
java {
withSourcesJar()
toolchain.languageVersion.set(JavaLanguageVersion.of(17))
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}
tasks {
@@ -54,8 +56,8 @@ allprojects {
}
compileKotlin {
kotlinOptions {
jvmTarget = "17"
compilerOptions {
jvmTarget.set(JvmTarget.JVM_21)
}
}

View File

@@ -10,9 +10,12 @@ dependencies {
publishing {
publications {
register("maven", MavenPublication::class) {
from(components["java"])
register<MavenPublication>("maven") {
groupId = project.group.toString()
version = project.version.toString()
artifactId = rootProject.name
artifact(rootProject.tasks.shadowJar.get().archiveFile)
}
}

View File

@@ -10,6 +10,7 @@ import com.willfp.ecojobs.api.getJobLevel
import com.willfp.ecojobs.api.jobLimit
import com.willfp.ecojobs.commands.CommandEcoJobs
import com.willfp.ecojobs.commands.CommandJobs
import com.willfp.ecojobs.jobs.EcoJobsJobTopPlaceholder
import com.willfp.ecojobs.jobs.JobLevelListener
import com.willfp.ecojobs.jobs.Jobs
import com.willfp.ecojobs.jobs.PriceHandler
@@ -30,7 +31,9 @@ import com.willfp.libreforge.filters.Filters
import com.willfp.libreforge.loader.LibreforgePlugin
import com.willfp.libreforge.loader.configs.ConfigCategory
import com.willfp.libreforge.registerHolderProvider
import com.willfp.libreforge.registerSpecificHolderProvider
import com.willfp.libreforge.triggers.Triggers
import org.bukkit.entity.Player
import org.bukkit.event.Listener
import java.util.regex.Pattern
@@ -56,12 +59,14 @@ class EcoJobsPlugin : LibreforgePlugin() {
Triggers.register(TriggerLeaveJob)
Filters.register(FilterJob)
registerHolderProvider { player ->
registerSpecificHolderProvider<Player> { player ->
player.activeJobs.map { it.getLevel(player.getJobLevel(it)) }.map {
SimpleProvidedHolder(it)
}
}
EcoJobsJobTopPlaceholder(this).register()
PlayerPlaceholder(
this,
"limit"
@@ -82,28 +87,6 @@ class EcoJobsPlugin : LibreforgePlugin() {
}
level.toString()
}.register()
DynamicPlaceholder(
this,
Pattern.compile("top_[a-z]+_[0-9]+_[a-z]+")
) {
val split = it.split("_")
val jobId = split.getOrNull(1) ?: return@DynamicPlaceholder "You must specify the job id!"
val job = Jobs.getByID(jobId) ?: return@DynamicPlaceholder "Invalid job id!"
val placeString = split.getOrNull(2) ?: return@DynamicPlaceholder "You must specify the place!"
val place = placeString.toIntOrNull() ?: return@DynamicPlaceholder "Invalid place!"
val type = split.getOrNull(3) ?: return@DynamicPlaceholder "You must specify the top type!"
val topEntry = job.getTop(place)
return@DynamicPlaceholder when (type) {
"name" -> topEntry?.player?.savedDisplayName
?: this.langYml.getFormattedString("top.name-empty")
"amount" -> topEntry?.amount?.toNiceString()
?: this.langYml.getFormattedString("top.amount-empty")
else -> "Invalid type: $type! Available types: name/amount"
}
}.register()
}
override fun loadPluginCommands(): List<PluginCommand> {

View File

@@ -140,7 +140,7 @@ fun OfflinePlayer.resetJob(job: Job) {
/**
* Get the experience required to advance to the next level.
*/
fun OfflinePlayer.getJobXPRequired(job: Job) = job.getExpForLevel(this.getJobLevel(job) + 1)
fun OfflinePlayer.getJobXPRequired(job: Job) = job.getFormattedExpForLevel(this.getJobLevel(job) + 1)
/**
* Get progress to next level between 0 and 1, where 0 is none and 1 is complete.

View File

@@ -12,6 +12,7 @@ class CommandJobs(plugin: EcoPlugin) : PluginCommand(plugin, "jobs", "ecojobs.co
init {
this.addSubcommand(CommandJoin(plugin))
.addSubcommand(CommandLeave(plugin))
.addSubcommand(CommandTop(plugin))
}
override fun onExecute(player: Player, args: List<String>) {

View File

@@ -10,6 +10,7 @@ import com.willfp.ecojobs.api.resetJob
import com.willfp.ecojobs.jobs.Jobs
import org.bukkit.Bukkit
import org.bukkit.command.CommandSender
import org.bukkit.util.StringUtil
class CommandReset(plugin: EcoPlugin) : Subcommand(plugin, "reset", "ecojobs.command.reset", false) {
override fun onExecute(sender: CommandSender, args: List<String>) {
@@ -24,16 +25,68 @@ class CommandReset(plugin: EcoPlugin) : Subcommand(plugin, "reset", "ecojobs.com
}
val playerName = args[0]
val jobName = args[1]
// Reset all jobs for all players
if (playerName.equals("all", ignoreCase = true) && jobName.equals("all", ignoreCase = true)) {
Bukkit.getOnlinePlayers().forEach { player ->
Jobs.values().forEach { job ->
if (player.hasJob(job)) {
player.forceLeaveJob(job)
player.resetJob(job)
}
}
}
sender.sendMessage(plugin.langYml.getMessage("reset-all-players-all-jobs"))
return
}
// Reset a specific job for all players
if (playerName.equals("all", ignoreCase = true)) {
val job = Jobs.getByID(jobName)
if (job == null) {
sender.sendMessage(plugin.langYml.getMessage("invalid-job"))
return
}
Bukkit.getOnlinePlayers().forEach { player ->
if (player.hasJob(job)) {
player.forceLeaveJob(job)
player.resetJob(job)
}
}
sender.sendMessage(
plugin.langYml.getMessage("reset-all-players")
.replace("%job%", job.name)
)
return
}
// Reset all jobs for a specific player
val player = Bukkit.getPlayer(playerName)
if (player == null) {
sender.sendMessage(plugin.langYml.getMessage("invalid-player"))
return
}
val job = Jobs.getByID(args[1])
if (jobName.equals("all", ignoreCase = true)) {
Jobs.values().forEach { job ->
if (player.hasJob(job)) {
player.forceLeaveJob(job)
player.resetJob(job)
}
}
sender.sendMessage(
plugin.langYml.getMessage("reset-all-jobs")
.replace("%player%", player.savedDisplayName)
)
return
}
// Reset a specific job for a specific player
val job = Jobs.getByID(jobName)
if (job == null) {
sender.sendMessage(plugin.langYml.getMessage("invalid-job"))
return
@@ -55,12 +108,23 @@ class CommandReset(plugin: EcoPlugin) : Subcommand(plugin, "reset", "ecojobs.com
}
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> {
val completions = mutableListOf<String>()
if (args.size == 1) {
return Bukkit.getOnlinePlayers().map { it.name }
StringUtil.copyPartialMatches(
args[0],
listOf("all") union Bukkit.getOnlinePlayers().map { player -> player.name },
completions
)
return completions
}
if (args.size == 2) {
return Jobs.values().map { it.id }
StringUtil.copyPartialMatches(
args[1],
listOf("all") union Jobs.values().map { it.id },
completions
)
return completions
}
return emptyList()

View File

@@ -0,0 +1,87 @@
package com.willfp.ecojobs.commands
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.command.impl.Subcommand
import com.willfp.eco.core.placeholder.context.placeholderContext
import com.willfp.eco.util.formatEco
import com.willfp.eco.util.savedDisplayName
import com.willfp.ecojobs.jobs.Jobs
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.util.StringUtil
class CommandTop(plugin: EcoPlugin) : Subcommand(plugin, "top", "ecojobs.command.top", false) {
override fun onExecute(sender: CommandSender, args: List<String>) {
plugin.scheduler.runAsync {
val job = Jobs.getByID(args.getOrNull(0))
if (job == null) {
sender.sendMessage(plugin.langYml.getMessage("invalid-job"))
return@runAsync
}
val page = args.getOrNull(1)?.toIntOrNull() ?: 1
if (args.getOrNull(1)?.let { it.isNotBlank() && !it.matches("\\d+".toRegex()) } == true) {
sender.sendMessage(plugin.langYml.getMessage("invalid-page"))
return@runAsync
}
val offset = (page - 1) * 10
val positions = (offset + 1..offset + 10).toList()
val top = positions.mapNotNull { job.getTop(it) }
val messages = plugin.langYml.getStrings("top.format").toMutableList()
val lines = mutableListOf<String>()
top.forEachIndexed { index, entry ->
val line = plugin.langYml.getString("top-line-format")
.replace("%rank%", (offset + index + 1).toString())
.replace("%level%", entry.level.toString())
.replace("%player%", entry.player.savedDisplayName)
lines.add(line)
}
val linesIndex = messages.indexOf("%lines%")
if (linesIndex != -1) {
messages.removeAt(linesIndex)
messages.addAll(linesIndex, lines)
}
messages.forEach { message ->
sender.sendMessage(
message.formatEco(
placeholderContext(
player = sender as? Player
)
)
)
}
}
}
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> {
val completions = mutableListOf<String>()
if (args.size == 1) {
StringUtil.copyPartialMatches(
args[0],
Jobs.values().map { it.id },
completions
)
return completions
}
if (args.size == 2 && Jobs.getByID(args[0]) != null) {
StringUtil.copyPartialMatches(
args[1],
listOf("1", "2", "3", "4", "5"),
completions
)
return completions
}
return emptyList()
}
}

View File

@@ -0,0 +1,37 @@
package com.willfp.ecojobs.jobs
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.placeholder.RegistrablePlaceholder
import com.willfp.eco.core.placeholder.context.PlaceholderContext
import com.willfp.eco.util.savedDisplayName
import java.util.regex.Pattern
class EcoJobsJobTopPlaceholder(
private val plugin: EcoPlugin
) : RegistrablePlaceholder {
private val pattern = Pattern.compile("top_([a-z0-9_]+)_(\\d+)_(name|level|amount)")
override fun getPattern(): Pattern = pattern
override fun getPlugin(): EcoPlugin = plugin
override fun getValue(params: String, ctx: PlaceholderContext): String? {
val emptyPosition: String = plugin.langYml.getString("top.empty-position")
val matcher = pattern.matcher(params)
if (!matcher.matches()) {
return null
}
val jobId = matcher.group(1)
val place = matcher.group(2).toIntOrNull() ?: return null
val type = matcher.group(3)
val job = Jobs.getByID(jobId) ?: return null
return when (type) {
"name" -> job.getTop(place)?.player?.savedDisplayName ?: emptyPosition
"level", "amount" -> job.getTop(place)?.level?.toString() ?: emptyPosition
else -> null
}
}
}

View File

@@ -9,12 +9,15 @@ import com.willfp.eco.core.items.builder.ItemStackBuilder
import com.willfp.eco.core.placeholder.PlayerPlaceholder
import com.willfp.eco.core.placeholder.PlayerStaticPlaceholder
import com.willfp.eco.core.placeholder.PlayerlessPlaceholder
import com.willfp.eco.core.placeholder.context.placeholderContext
import com.willfp.eco.core.price.ConfiguredPrice
import com.willfp.eco.core.price.impl.PriceEconomy
import com.willfp.eco.core.registry.Registrable
import com.willfp.eco.util.NumberUtils
import com.willfp.eco.util.NumberUtils.evaluateExpression
import com.willfp.eco.util.formatEco
import com.willfp.eco.util.toNiceString
import com.willfp.eco.util.toNumeral
import com.willfp.ecojobs.EcoJobsPlugin
import com.willfp.ecojobs.api.activeJobs
import com.willfp.ecojobs.api.canJoinJob
@@ -24,20 +27,23 @@ import com.willfp.ecojobs.api.getJobXP
import com.willfp.ecojobs.api.getJobXPRequired
import com.willfp.ecojobs.api.hasJobActive
import com.willfp.ecojobs.api.jobLimit
import com.willfp.ecojobs.util.LeaderboardCacheEntry
import com.willfp.ecojobs.util.LevelInjectable
import com.willfp.libreforge.ViolationContext
import com.willfp.libreforge.conditions.ConditionList
import com.willfp.libreforge.conditions.Conditions
import com.willfp.libreforge.counters.Counters
import com.willfp.libreforge.effects.EffectList
import com.willfp.libreforge.effects.Effects
import com.willfp.libreforge.effects.executors.impl.NormalExecutorFactory
import org.bukkit.Bukkit
import org.bukkit.OfflinePlayer
import org.bukkit.configuration.InvalidConfigurationException
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import java.time.Duration
import java.util.Objects
import java.util.concurrent.TimeUnit
import kotlin.math.max
import java.util.UUID
class Job(
val id: String,
@@ -49,8 +55,11 @@ class Job(
.build<Int, LeaderboardCacheEntry?>()
val name = config.getFormattedString("name")
val description = config.getFormattedString("description")
val isUnlockedByDefault = config.getBool("unlocked-by-default")
val resetsOnQuit = config.getBool("reset-on-quit")
val joinPrice = ConfiguredPrice.create(config.getSubsection("join-price")) ?: ConfiguredPrice(
@@ -71,9 +80,11 @@ class Job(
EcoJobsPlugin.instance.namespacedKeyFactory.create("${id}_xp"), PersistentDataKeyType.DOUBLE, 0.0
)
private val xpFormula = config.getStringOrNull("xp-formula")
private val levelXpRequirements = listOf(0) + config.getInts("level-xp-requirements")
val maxLevel = levelXpRequirements.size
val maxLevel = config.getIntOrNull("max-level") ?: levelXpRequirements?.size ?: Int.MAX_VALUE
val levelGUI = JobLevelGUI(plugin, this)
@@ -106,6 +117,10 @@ class Job(
}
init {
if (xpFormula == null && levelXpRequirements == null) {
throw InvalidConfigurationException("Skill $id has no requirements or xp formula")
}
config.injectPlaceholders(PlayerStaticPlaceholder(
"level"
) { p ->
@@ -122,24 +137,7 @@ class Job(
ViolationContext(plugin, "Job $id")
)
for (string in config.getStrings("level-commands")) {
val split = string.split(":")
if (split.size == 1) {
for (level in 1..maxLevel) {
val commands = levelCommands[level] ?: mutableListOf()
commands.add(string)
levelCommands[level] = commands
}
} else {
val level = split[0].toInt()
val command = string.removePrefix("$level:")
val commands = levelCommands[level] ?: mutableListOf()
commands.add(command)
levelCommands[level] = commands
}
}
manageLevelCommands(config)
PlayerPlaceholder(
plugin, "${id}_percentage_progress"
@@ -188,8 +186,59 @@ class Job(
) {
Bukkit.getOfflinePlayers().count { this in it.activeJobs }.toString()
}.register()
PlayerPlaceholder(
plugin, "${id}_leaderboard_rank"
) { player ->
val emptyPosition = plugin.langYml.getString("top.empty-position")
val position = getPosition(player.uniqueId)
position?.toString() ?: emptyPosition
}.register()
}
@Deprecated("Use level-up-effects instead")
private fun manageLevelCommands(config: Config) {
if (config.getStrings("level-commands").isNotEmpty()) {
plugin.logger.warning("$id job: The `level-commands` key is deprecated and will be removed in future versions. Switch to `level-up-effects` instead. Refer to the wiki for more info.")
}
for (string in config.getStrings("level-commands")) {
val split = string.split(":")
if (split.size == 1) {
for (level in 1..maxLevel) {
val commands = levelCommands[level] ?: mutableListOf()
commands.add(string)
levelCommands[level] = commands
}
} else {
val level = split[0].toInt()
val command = string.removePrefix("$level:")
val commands = levelCommands[level] ?: mutableListOf()
commands.add(command)
levelCommands[level] = commands
}
}
}
val levelUpEffects = Effects.compileChain(
config.getSubsections("level-up-effects"),
NormalExecutorFactory.create(),
ViolationContext(plugin, "Job $id level-up-effects")
)
val joinEffects = Effects.compileChain(
config.getSubsections("join-effects"),
NormalExecutorFactory.create(),
ViolationContext(plugin, "Job $id join-effects")
)
val leaveEffects = Effects.compileChain(
config.getSubsections("leave-effects"),
NormalExecutorFactory.create(),
ViolationContext(plugin, "Job $id leave-effects")
)
override fun onRegister() {
jobXpGains.forEach { it.bind(JobXPAccumulator(this)) }
}
@@ -272,20 +321,31 @@ class Job(
}
fun injectPlaceholdersInto(lore: List<String>, player: Player, forceLevel: Int? = null): List<String> {
val withPlaceholders = lore.map {
it.replace("%percentage_progress%", (player.getJobProgress(this) * 100).toNiceString())
val withPlaceholders = lore.map { line ->
var result = line
.replace("%percentage_progress%", (player.getJobProgress(this) * 100).toNiceString())
.replace("%current_xp%", player.getJobXP(this).toNiceString())
.replace("%required_xp%", this.getExpForLevel(player.getJobLevel(this) + 1).let { req ->
if (req == Int.MAX_VALUE) {
plugin.langYml.getFormattedString("infinity")
} else {
req.toNiceString()
}
}).replace("%description%", this.description).replace("%job%", this.name)
.replace("%required_xp%", this.getFormattedExpForLevel(player.getJobLevel(this) + 1))
.replace("%description%", this.description).replace("%job%", this.name)
.replace("%level%", (forceLevel ?: player.getJobLevel(this)).toString())
.replace("%level_numeral%", NumberUtils.toNumeral(forceLevel ?: player.getJobLevel(this)))
.replace("%join_price%", this.joinPrice.getDisplay(player))
.replace("%leave_price%", this.leavePrice.getDisplay(player))
.replace("%rank%", this.getPosition(player.uniqueId)?.toString() ?: plugin.langYml.getString("top.empty-position"))
val level = forceLevel ?: player.getJobLevel(this)
val regex = Regex("%level_(-?\\d+)(_numeral)?%")
// Handle dynamic %level_X% and %level_X_numeral%
result = regex.replace(result) { match ->
val offset = match.groupValues[1].toIntOrNull() ?: return@replace match.value
val isNumeral = match.groupValues[2].isNotEmpty()
val newLevel = level + offset
if (isNumeral) newLevel.toNumeral() else newLevel.toString()
}
result
}.toMutableList()
val processed = mutableListOf<List<String>>()
@@ -347,14 +407,36 @@ class Job(
}.build()
}
fun getExpForLevel(level: Int): Int {
/**
* Get the XP required to reach the next level, if currently at [level].
*/
fun getExpForLevel(level: Int): Double {
if (level < 1 || level > maxLevel) {
return Int.MAX_VALUE
return Double.MAX_VALUE
}
return levelXpRequirements[level - 1]
if (xpFormula != null) {
return evaluateExpression(
xpFormula,
placeholderContext(
injectable = LevelInjectable(level - 1)
)
)
}
return levelXpRequirements[level - 1].toDouble()
}
fun getFormattedExpForLevel(level: Int): String {
val required = getExpForLevel(level)
return if (required.isInfinite()) {
plugin.langYml.getFormattedString("infinity")
} else {
required.toNiceString()
}
}
@Deprecated("Use level-up-effects instead")
fun executeLevelCommands(player: Player, level: Int) {
val commands = levelCommands[level] ?: emptyList()
@@ -371,6 +453,14 @@ class Job(
}
}
fun getPosition(uuid: UUID): Int? {
val leaderboard = Bukkit.getOfflinePlayers().sortedByDescending { it.getJobLevel(this) }
.map { it.uniqueId }
val index = leaderboard.indexOf(uuid)
return if (index == -1) null else index + 1
}
override fun getID(): String {
return this.id
}
@@ -394,11 +484,6 @@ private class LevelPlaceholder(
operator fun invoke(level: Int) = function(level)
}
data class LeaderboardCacheEntry(
val player: OfflinePlayer,
val amount: Int
)
private fun Collection<LevelPlaceholder>.format(string: String, level: Int): String {
var process = string
for (placeholder in this) {
@@ -408,44 +493,3 @@ private fun Collection<LevelPlaceholder>.format(string: String, level: Int): Str
}
fun OfflinePlayer.getJobLevelObject(job: Job): JobLevel = job.getLevel(this.getJobLevel(job))
private val expMultiplierCache = Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build<Player, Double> {
it.cacheJobExperienceMultiplier()
}
val Player.jobExperienceMultiplier: Double
get() = expMultiplierCache.get(this)
private fun Player.cacheJobExperienceMultiplier(): Double {
if (this.hasPermission("ecojobs.xpmultiplier.quadruple")) {
return 4.0
}
if (this.hasPermission("ecojobs.xpmultiplier.triple")) {
return 3.0
}
if (this.hasPermission("ecojobs.xpmultiplier.double")) {
return 2.0
}
if (this.hasPermission("ecojobs.xpmultiplier.50percent")) {
return 1.5
}
return 1 + getNumericalPermission("ecojobs.xpmultiplier", 0.0) / 100
}
fun Player.getNumericalPermission(permission: String, default: Double): Double {
var highest: Double? = null
for (permissionAttachmentInfo in this.effectivePermissions) {
val perm = permissionAttachmentInfo.permission
if (perm.startsWith(permission)) {
val found = perm.substring(perm.lastIndexOf(".") + 1).toDoubleOrNull() ?: continue
highest = max(highest ?: Double.MIN_VALUE, found)
}
}
return highest ?: default
}

View File

@@ -13,6 +13,7 @@ import com.willfp.eco.core.gui.slot.MaskItems
import com.willfp.eco.core.items.Items
import com.willfp.eco.core.items.builder.ItemStackBuilder
import com.willfp.eco.util.NumberUtils
import com.willfp.eco.util.formatEco
import com.willfp.ecojobs.api.getJobLevel
import com.willfp.ecomponent.components.LevelComponent
import com.willfp.ecomponent.components.LevelState
@@ -65,7 +66,9 @@ class JobLevelGUI(
}
menu = menu(plugin.configYml.getInt("level-gui.rows")) {
title = job.name
title = plugin.configYml.getString("level-gui.title")
.replace("%job%", job.name)
.formatEco()
maxPages(component.pages)

View File

@@ -2,6 +2,7 @@ package com.willfp.ecojobs.jobs
import com.willfp.ecojobs.EcoJobsPlugin
import com.willfp.ecojobs.api.event.PlayerJobLevelUpEvent
import com.willfp.libreforge.toDispatcher
import org.bukkit.Sound
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
@@ -16,6 +17,7 @@ class JobLevelListener(
val player = event.player
val level = event.level
job.levelUpEffects?.trigger(player.toDispatcher())
job.executeLevelCommands(player, level)
if (this.plugin.configYml.getBool("level-up.sound.enabled")) {

View File

@@ -1,9 +1,12 @@
package com.willfp.ecojobs.jobs
import com.github.benmanes.caffeine.cache.Caffeine
import com.willfp.ecojobs.api.giveJobExperience
import com.willfp.ecojobs.api.hasJobActive
import com.willfp.libreforge.counters.Accumulator
import org.bukkit.entity.Player
import java.util.concurrent.TimeUnit
import kotlin.math.max
class JobXPAccumulator(
private val job: Job
@@ -16,3 +19,44 @@ class JobXPAccumulator(
player.giveJobExperience(job, count)
}
}
private val expMultiplierCache = Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build<Player, Double> {
it.cacheJobExperienceMultiplier()
}
val Player.jobExperienceMultiplier: Double
get() = expMultiplierCache.get(this)
private fun Player.cacheJobExperienceMultiplier(): Double {
if (this.hasPermission("ecojobs.xpmultiplier.quadruple")) {
return 4.0
}
if (this.hasPermission("ecojobs.xpmultiplier.triple")) {
return 3.0
}
if (this.hasPermission("ecojobs.xpmultiplier.double")) {
return 2.0
}
if (this.hasPermission("ecojobs.xpmultiplier.50percent")) {
return 1.5
}
return 1 + getNumericalPermission("ecojobs.xpmultiplier", 0.0) / 100
}
fun Player.getNumericalPermission(permission: String, default: Double): Double {
var highest: Double? = null
for (permissionAttachmentInfo in this.effectivePermissions) {
val perm = permissionAttachmentInfo.permission
if (perm.startsWith(permission)) {
val found = perm.substring(perm.lastIndexOf(".") + 1).toDoubleOrNull() ?: continue
highest = max(highest ?: Double.MIN_VALUE, found)
}
}
return highest ?: default
}

View File

@@ -30,8 +30,8 @@ object Jobs : ConfigCategory("job", "jobs") {
* @return The matching [Job], or null if not found.
*/
@JvmStatic
fun getByID(name: String): Job? {
return registry[name]
fun getByID(name: String?): Job? {
return name?.let { registry[it] }
}
override fun clear(plugin: LibreforgePlugin) {

View File

@@ -2,6 +2,7 @@ package com.willfp.ecojobs.jobs
import com.willfp.ecojobs.api.event.PlayerJobJoinEvent
import com.willfp.ecojobs.api.event.PlayerJobLeaveEvent
import com.willfp.libreforge.toDispatcher
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
@@ -23,6 +24,7 @@ object PriceHandler : Listener {
}
price.pay(player)
job.joinEffects?.trigger(player.toDispatcher())
}
@EventHandler(
@@ -40,5 +42,6 @@ object PriceHandler : Listener {
}
price.pay(player)
job.leaveEffects?.trigger(player.toDispatcher())
}
}

View File

@@ -2,9 +2,12 @@ package com.willfp.ecojobs.libreforge
import com.willfp.eco.core.config.interfaces.Config
import com.willfp.ecojobs.api.activeJobs
import com.willfp.libreforge.Dispatcher
import com.willfp.libreforge.NoCompileData
import com.willfp.libreforge.ProvidedHolder
import com.willfp.libreforge.arguments
import com.willfp.libreforge.conditions.Condition
import com.willfp.libreforge.get
import org.bukkit.entity.Player
object ConditionHasActiveJob : Condition<NoCompileData>("has_active_job") {
@@ -12,7 +15,14 @@ object ConditionHasActiveJob : Condition<NoCompileData>("has_active_job") {
require("job", "You must specify the job!")
}
override fun isMet(player: Player, config: Config, compileData: NoCompileData): Boolean {
override fun isMet(
dispatcher: Dispatcher<*>,
config: Config,
holder: ProvidedHolder,
compileData: NoCompileData
): Boolean {
val player = dispatcher.get<Player>() ?: return false
return player.activeJobs.any { it.id == config.getString("job").lowercase() }
}
}

View File

@@ -4,9 +4,13 @@ import com.willfp.eco.core.config.interfaces.Config
import com.willfp.ecojobs.api.event.PlayerJobLevelUpEvent
import com.willfp.ecojobs.api.getJobLevel
import com.willfp.ecojobs.jobs.Jobs
import com.willfp.libreforge.Dispatcher
import com.willfp.libreforge.NoCompileData
import com.willfp.libreforge.ProvidedHolder
import com.willfp.libreforge.arguments
import com.willfp.libreforge.conditions.Condition
import com.willfp.libreforge.get
import com.willfp.libreforge.toDispatcher
import com.willfp.libreforge.updateEffects
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
@@ -18,7 +22,14 @@ object ConditionHasJobLevel : Condition<NoCompileData>("has_job_level") {
require("level", "You must specify the level!")
}
override fun isMet(player: Player, config: Config, compileData: NoCompileData): Boolean {
override fun isMet(
dispatcher: Dispatcher<*>,
config: Config,
holder: ProvidedHolder,
compileData: NoCompileData
): Boolean {
val player = dispatcher.get<Player>() ?: return false
return player.getJobLevel(
Jobs.getByID(config.getString("job").lowercase()) ?: return false
) >= config.getIntFromExpression("level", player)
@@ -26,6 +37,6 @@ object ConditionHasJobLevel : Condition<NoCompileData>("has_job_level") {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
fun handle(event: PlayerJobLevelUpEvent) {
event.player.updateEffects()
event.player.toDispatcher().updateEffects()
}
}

View File

@@ -4,6 +4,7 @@ import com.willfp.ecojobs.api.event.PlayerJobExpGainEvent
import com.willfp.ecojobs.jobs.Job
import com.willfp.ecojobs.jobs.Jobs
import com.willfp.libreforge.effects.templates.MultiMultiplierEffect
import com.willfp.libreforge.toDispatcher
import org.bukkit.event.EventHandler
object EffectJobXpMultiplier : MultiMultiplierEffect<Job>("job_xp_multiplier") {
@@ -19,6 +20,6 @@ object EffectJobXpMultiplier : MultiMultiplierEffect<Job>("job_xp_multiplier") {
@EventHandler(ignoreCancelled = true)
fun handle(event: PlayerJobExpGainEvent) {
event.amount *= getMultiplier(event.player, event.job)
event.amount *= getMultiplier(event.player.toDispatcher(), event.job)
}
}

View File

@@ -1,6 +1,7 @@
package com.willfp.ecojobs.libreforge
import com.willfp.ecojobs.api.event.PlayerJobExpGainEvent
import com.willfp.libreforge.toDispatcher
import com.willfp.libreforge.triggers.Trigger
import com.willfp.libreforge.triggers.TriggerData
import com.willfp.libreforge.triggers.TriggerParameter
@@ -18,7 +19,7 @@ object TriggerGainJobXp : Trigger("gain_job_xp") {
val player = event.player
this.dispatch(
player,
player.toDispatcher(),
TriggerData(
player = player,
location = player.location,

View File

@@ -2,6 +2,7 @@ package com.willfp.ecojobs.libreforge
import com.willfp.ecojobs.api.event.PlayerJobJoinEvent
import com.willfp.ecojobs.api.getJobLevel
import com.willfp.libreforge.toDispatcher
import com.willfp.libreforge.triggers.Trigger
import com.willfp.libreforge.triggers.TriggerData
import com.willfp.libreforge.triggers.TriggerParameter
@@ -20,7 +21,7 @@ object TriggerJoinJob : Trigger("join_job") {
val player = event.player as? Player ?: return
this.dispatch(
player,
player.toDispatcher(),
TriggerData(
player = player,
location = player.location,

View File

@@ -2,6 +2,7 @@ package com.willfp.ecojobs.libreforge
import com.willfp.ecojobs.api.event.PlayerJobLeaveEvent
import com.willfp.ecojobs.api.getJobLevel
import com.willfp.libreforge.toDispatcher
import com.willfp.libreforge.triggers.Trigger
import com.willfp.libreforge.triggers.TriggerData
import com.willfp.libreforge.triggers.TriggerParameter
@@ -19,7 +20,7 @@ object TriggerLeaveJob : Trigger("leave_job") {
val player = event.player as? Player ?: return
this.dispatch(
player,
player.toDispatcher(),
TriggerData(
player = player,
location = player.location,

View File

@@ -1,6 +1,7 @@
package com.willfp.ecojobs.libreforge
import com.willfp.ecojobs.api.event.PlayerJobLevelUpEvent
import com.willfp.libreforge.toDispatcher
import com.willfp.libreforge.triggers.Trigger
import com.willfp.libreforge.triggers.TriggerData
import com.willfp.libreforge.triggers.TriggerParameter
@@ -18,7 +19,7 @@ object TriggerLevelUpJob : Trigger("level_up_job") {
val player = event.player
this.dispatch(
player,
player.toDispatcher(),
TriggerData(
player = player,
location = player.location,

View File

@@ -0,0 +1,8 @@
package com.willfp.ecojobs.util
import org.bukkit.OfflinePlayer
data class LeaderboardCacheEntry(
val player: OfflinePlayer,
val level: Int
)

View File

@@ -0,0 +1,27 @@
package com.willfp.ecojobs.util
import com.willfp.eco.core.placeholder.InjectablePlaceholder
import com.willfp.eco.core.placeholder.PlaceholderInjectable
import com.willfp.eco.core.placeholder.StaticPlaceholder
class LevelInjectable(
level: Int
) : PlaceholderInjectable {
private val placeholders = listOf(
StaticPlaceholder(
"level"
) { level.toString() }
)
override fun getPlaceholderInjections(): List<InjectablePlaceholder> {
return placeholders
}
override fun addInjectablePlaceholder(p0: Iterable<InjectablePlaceholder>) {
return
}
override fun clearInjectedPlaceholders() {
return
}
}

View File

@@ -3,6 +3,11 @@
# by Auxilor
#
# Even if eco is set up to use a database, you can
# force EcoJobs to save to local storage to disable
# cross-server sync.
use-local-storage: false
jobs:
limit: 3 # The most jobs a player can have at once.
# You can set custom limits with the ecojobs.limit.<number> permission
@@ -119,6 +124,7 @@ gui:
level-gui:
rows: 6
title: "%job%"
mask:
# The way the mask works is by having a list of materials

View File

@@ -27,6 +27,13 @@ join-price:
# Reference with %join_lore%
join-lore: []
# A list of effects to run when the player joins the job.
# Read https://plugins.auxilor.io/effects/configuring-an-effect
join-effects:
- id: broadcast
args:
message: "&8» &a%player% &8joined the &6Miner &8job!"
# The price to leave this job (set to 0 to disable)
# Read here for more: https://plugins.auxilor.io/all-plugins/prices
leave-price:
@@ -39,7 +46,22 @@ leave-price:
leave-lore:
- " &8» This will cost %leave_price%"
# The xp requirements for each job level - add new levels by adding more to this list
# A list of effects to run when the player leaves the job.
# Read https://plugins.auxilor.io/effects/configuring-an-effect
leave-effects:
- id: send_message
args:
message: "&8» &8You left the &6Miner &8job!"
# There are two ways to specify level XP requirements:
# 1. A formula to calculate for infinite levels
# 2. A list of XP requirements for each level
# Formula
# xp-formula: (2 ^ %level%) * 25
# max-level: 100 # The max level of the job
# List
level-xp-requirements:
- 100
- 120
@@ -133,10 +155,13 @@ level-up-messages:
1:
- "&8» &8Earn &a$%money%&8 for each &a%blocks%&8 blocks mined"
# Commands to be sent on levelup, can be formatted two ways:
# level:command (e.g. 10:eco give %player% 1000), which would execute that command for level 10
# command (e.g. eco give %player% 5000), which would execute that command for all levels
level-commands: [ ]
# Effects to run when the skill levels up
# %level% is the level the skill leveled up to.
# If you want to restrict this to certain levels, you can use
# require: %level% = 20, or require: %level% < 50, etc.
# If you want a reward to run every x levels, you can use
# every: 1, or every: 12, etc
level-up-effects: [ ]
# The effects for the job, has %level% as a placeholder
effects:

View File

@@ -10,6 +10,8 @@ join-price:
type: coins
display: "&a$%value%"
join-effects: []
join-lore: []
leave-price:
@@ -17,6 +19,8 @@ leave-price:
type: coins
display: "&a$%value%"
leave-effects: []
leave-lore:
- ""
@@ -95,7 +99,7 @@ level-up-messages:
1:
- "&8» &8Earn &a$%money%&8 for each bee you breed"
level-commands: [ ]
level-up-effects: [ ]
effects:
- id: give_money

View File

@@ -10,6 +10,8 @@ join-price:
type: coins
display: "&a$%value%"
join-effects: []
join-lore: []
leave-price:
@@ -17,6 +19,8 @@ leave-price:
type: coins
display: "&a$%value%"
leave-effects: []
leave-lore:
- ""
@@ -94,7 +98,7 @@ level-up-messages:
1:
- "&8» &8Earn &a$%money%&8 for each &a%blocks%&8 blocks placed"
level-commands: [ ]
level-up-effects: [ ]
effects:
- id: give_money

View File

@@ -10,6 +10,8 @@ join-price:
type: coins
display: "&a$%value%"
join-effects: []
join-lore: []
leave-price:
@@ -17,6 +19,8 @@ leave-price:
type: coins
display: "&a$%value%"
leave-effects: []
leave-lore:
- ""
@@ -92,7 +96,7 @@ level-up-messages:
1:
- "&8» &8Earn &a$%money%&8 for each enchanted item"
level-commands: [ ]
level-up-effects: [ ]
effects:
- id: give_money

View File

@@ -10,6 +10,8 @@ join-price:
type: coins
display: "&a$%value%"
join-effects: []
join-lore: []
leave-price:
@@ -17,6 +19,8 @@ leave-price:
type: coins
display: "&a$%value%"
leave-effects: []
leave-lore:
- ""
@@ -107,7 +111,7 @@ level-up-messages:
1:
- "&8» &8Earn &a$%money%&8 for each crop farmed"
level-commands: [ ]
level-up-effects: [ ]
effects:
- id: give_money

View File

@@ -10,6 +10,8 @@ join-price:
type: coins
display: "&a$%value%"
join-effects: []
join-lore: []
leave-price:
@@ -17,6 +19,8 @@ leave-price:
type: coins
display: "&a$%value%"
leave-effects: []
leave-lore:
- ""
@@ -92,7 +96,7 @@ level-up-messages:
1:
- "&8» &8Earn &a$%money%&8 for each fish caught"
level-commands: [ ]
level-up-effects: [ ]
effects:
- id: give_money

View File

@@ -10,6 +10,8 @@ join-price:
type: coins
display: "&a$%value%"
join-effects: []
join-lore: []
leave-price:
@@ -17,6 +19,8 @@ leave-price:
type: coins
display: "&a$%value%"
leave-effects: []
leave-lore:
- ""
@@ -104,7 +108,7 @@ level-up-messages:
1:
- "&8» &7Earn &a$%money%&7 for each log chopped."
level-commands: [ ]
level-up-effects: [ ]
effects:
- id: give_money

View File

@@ -10,6 +10,8 @@ join-price:
type: coins
display: "&a$%value%"
join-effects: []
join-lore: []
leave-price:
@@ -17,6 +19,8 @@ leave-price:
type: coins
display: "&a$%value%"
leave-effects: []
leave-lore:
- ""
@@ -74,15 +78,17 @@ level-xp-requirements:
xp-gain-methods:
- trigger: mine_block
multiplier: 0.5
conditions: [ ]
filters:
items:
- "*wooden_pickaxe"
- "*stone_pickaxe"
- "*iron_pickaxe"
- "*golden_pickaxe"
- "*diamond_pickaxe"
- "*netherite_pickaxe"
filters: [ ]
conditions:
- id: in_mainhand
args:
items:
- "*wooden_pickaxe"
- "*stone_pickaxe"
- "*iron_pickaxe"
- "*golden_pickaxe"
- "*diamond_pickaxe"
- "*netherite_pickaxe"
level-placeholders:
- id: "money"
@@ -102,21 +108,23 @@ level-up-messages:
1:
- "&8» &8Earn &a$%money%&8 for each &a%blocks%&8 blocks mined"
level-commands: [ ]
level-up-effects: [ ]
effects:
- id: give_money
args:
every: "ceil(10 - %level% / 10)"
amount: "0.4 * %level%"
filters:
items:
- "*wooden_pickaxe"
- "*stone_pickaxe"
- "*iron_pickaxe"
- "*golden_pickaxe"
- "*diamond_pickaxe"
- "*netherite_pickaxe"
conditions:
- id: in_mainhand
args:
items:
- "*wooden_pickaxe"
- "*stone_pickaxe"
- "*iron_pickaxe"
- "*golden_pickaxe"
- "*diamond_pickaxe"
- "*netherite_pickaxe"
triggers:
- mine_block

View File

@@ -10,6 +10,8 @@ join-price:
type: coins
display: "&a$%value%"
join-effects: []
join-lore: []
leave-price:
@@ -17,6 +19,8 @@ leave-price:
type: coins
display: "&a$%value%"
leave-effects: []
leave-lore:
- ""
@@ -95,7 +99,7 @@ level-up-messages:
- "&8» &8Earn &a$%money%&8 per heart of health that"
- " &8mobs you kill have"
level-commands: [ ]
level-up-effects: [ ]
effects:
- id: give_money

View File

@@ -10,6 +10,8 @@ join-price:
type: coins
display: "&a$%value%"
join-effects: []
join-lore: []
leave-price:
@@ -17,6 +19,8 @@ leave-price:
type: coins
display: "&a$%value%"
leave-effects: []
leave-lore:
- ""
@@ -92,7 +96,7 @@ level-up-messages:
1:
- "&8» &8Earn &a$%money%&8 for each smelted item"
level-commands: [ ]
level-up-effects: [ ]
effects:
- id: give_money

View File

@@ -18,6 +18,8 @@ join-price:
type: coins
display: "&a$%value%"
join-effects: []
join-lore: []
leave-price:
@@ -25,6 +27,8 @@ leave-price:
type: coins
display: "&a$%value%"
leave-effects: []
leave-lore:
- ""
@@ -133,7 +137,7 @@ level-up-messages:
1:
- "&8» &8Earn &a$%money%&8 for each tool crafted"
level-commands: [ ]
level-up-effects: [ ]
effects:
- id: give_money

View File

@@ -8,6 +8,9 @@ messages:
needs-player: "&cYou must specify a player!"
gave-xp: "&fYou have given &a%xp% &fXP to %player%&f's %job%&f!"
reset-xp: "&fYou have reset %player%&f's %job%&f XP!"
reset-all-players: "&fYou have reset all players' %job%&f XP!"
reset-all-jobs: "&fYou have reset %player%&f's XP for all jobs!"
reset-all-players-all-jobs: "&fYou have reset all players' XP for all jobs!"
needs-job: "&cYou must specify a job!"
need-amount: "&cYou must specify a amount!"
invalid-player: "&cInvalid player!"
@@ -31,6 +34,9 @@ menu:
infinity: "∞"
top-line-format: "%rank%. %player% - %level%"
top:
name-empty: "&cEmpty"
amount-empty: "0"
empty-position: "&cN/A"
format:
- "---- Jobs Leaderboard ----"
- "%lines%"

View File

@@ -1,75 +0,0 @@
name: ${pluginName}
version: ${version}
main: com.willfp.ecojobs.EcoJobsPlugin
api-version: 1.19
dependencies:
- name: eco
required: true
bootstrap: false
- name: libreforge
required: false
bootstrap: false
load-after:
- name: eco
bootstrap: false
permissions:
ecojobs.*:
description: All EcoJobs permissions
default: op
children:
ecojobs.command.*: true
ecojobs.command.*:
description: All commands
default: op
children:
ecojobs.command.ecojobs: true
ecojobs.command.reload: true
ecojobs.command.jobs: true
ecojobs.command.unlock: true
ecojobs.command.givexp: true
ecojobs.command.join: true
ecojobs.command.leave: true
ecojobs.command.reset: true
ecojobs.command.reload:
description: Allows reloading the config
default: op
ecojobs.command.ecojobs:
description: Allows the use of /ecojobs.
default: true
ecojobs.command.jobs:
description: Allows the use of /jobs.
default: true
ecojobs.command.unlock:
description: Allows the use of /ecojobs unlock.
default: op
ecojobs.command.givexp:
description: Allows the use of /ecojobs givexp.
default: op
ecojobs.command.reset:
description: Allows the use of /ecojobs reset.
default: op
ecojobs.command.join:
description: Allows the use of /jobs join.
default: true
ecojobs.command.leave:
description: Allows the use of /jobs leave.
default: true
ecojobs.xpmultiplier.50percent:
description: Gives the player 50% more job experience
default: false
ecojobs.xpmultiplier.double:
description: Gives the player 2x job experience
default: false
ecojobs.xpmultiplier.triple:
description: Gives the player 3x job experience
default: false
ecojobs.xpmultiplier.quadruple:
description: Gives the player 4x job experience
default: false

View File

@@ -1,5 +1,5 @@
#libreforge-updater
#Sun May 14 13:07:47 BST 2023
#Mon Oct 06 08:56:29 BST 2025
kotlin.code.style=official
libreforge-version=4.11.0
version=3.11.0
libreforge-version=4.79.0
version=3.77.0

Binary file not shown.

View File

@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -1,6 +0,0 @@
jdk: openjdk17
before_install:
- source "$HOME/.sdkman/bin/sdkman-init.sh"
- sdk update
- sdk install java 17.0.1-tem
- sdk use java 17.0.1-tem

View File

@@ -2,11 +2,15 @@ pluginManagement {
repositories {
gradlePluginPortal()
mavenLocal()
maven("https://repo.jpenilla.xyz/snapshots/")
maven("https://repo.auxilor.io/repository/maven-public/")
maven("https://repo.papermc.io/repository/maven-public/")
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "EcoJobs"
// Core