Skip to content

Conversation

@tajobe
Copy link
Member

@tajobe tajobe commented May 31, 2025

Adds title sender

The main motivation was adding a title announcement type, but obviously there's a bit more here per the CHANGELOG.

  • Completely reworked the configuration format (and how it's loaded)...
    • Addition of title type exposed a need to have polymorphic messages (eg title has both a main title and subtitle, rather than simple string)
    • Need to have title configurations (like fades/stay) made having that all read via the same config.get... calls pretty awkward
    • Now allows for per-message configs for things like boss bar or title bar if overriding the announcement config is desired
    • This opens the door to addition possibilities like JSON components
    • Durations can now be configured more expressively and explicitly (eg 60s, 10m, 1h) rather than implicitly being either minutes or seconds
  • No longer producing both an online and offline jar variant (specifically for this plugin, not broadly applicable though the options/logic added here should get backported to the template). 2 main problems here:
    • libraries doesn't isolate the classpath at all...Spigot/craftbukkit/etc ship with jackson (an old version...) so having jackson pulled via libraries in the plugin.yml doesn't work (old version is on classpath, resolved first)
    • I tried for some time to have 2 shadow jars...one "online" with a gradle configuration to specify libraries that should be shaded in/provided anyway(rest would go in libraries:) and the regular "offline"-mode shadow jar with everything. This resulted in some weirdness/conflicts with what could be picked up in the jar vs out. Very much not worth it for the smaller download size...
  • kotlin-reflect (jackson kotlin module dependency) being required on the classpath has some problems requiring workarounds...
    • Shadow relocation breaks reflection due to some builtins/metadata. For example, kotlin.Any isn't a real class contained in the stdlib jar, but a virtual/builtin type. Shadow relocations references to it, but the builtin doesn't change and thus it's not found.
    • Minimization + reflection don't play super nice together since shadow doesn't find references and minimizes things it shouldn't

Completes #3

@tajobe tajobe requested review from a team and Puremin0rez May 31, 2025 22:50
jvmToolchain(21)
}

val shadowJarOnly: Boolean = project.property("shadowJarOnly")?.toString()?.toBoolean() ?: false
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't anticipate this being something that gets toggled on and off in this plugin, but I wanted this to be something I could move into the template (which actually should in part be a Gradle plugin...)

import com.fasterxml.jackson.databind.ser.std.StdSerializer
import kotlin.time.Duration

class DurationSerializer : StdSerializer<Duration>(Duration::class.java) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class isn't strictly necessary to read (deserialize) the config, but including it is helpful for testing. For example, to create the default config I constructed a SimpleAnnounceConfig object and got the yaml out via a test class with println(objectMapper.writeValueAsString(config))

import org.bukkit.plugin.Plugin
import org.simplemc.simpleannounce.config.SimpleAnnounceConfig.AnnouncementConfig.Title

class TitleSender(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "main" "feature" of this PR is only ~30 lines out of almost 1000 changed 😬

override val includesPermissions: List<String> = emptyList(),
override val excludesPermissions: List<String> = emptyList(),
@field:JsonAlias("message") override val messages: List<BossBarMessage>,
@field:JsonUnwrapped val barConfig: BarConfig = BarConfig(),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could have used some other kotlin config library like hoplite instead of jackson and avoided a small portion of the pain (with an old version of jackson being included with spigot), but would have still had to deal with the kotlin-reflect problems and would lose the ability to unwrap properties like I do here.

...this makes it so the announcement configuration for a boss-type announcement has the barConfig fields directly (eg hold) instead of nested inside a barConfig field/object. Same with them being on the messages themselves.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May or may not be interesting for you, but Configurate is a popular config library for modern plugins (Paper uses it)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hoplite is simpler and easier to use IMO, but both would lose some of the jackson niceties (although Configurate seems to use jackson for its JSON support). Configurate also uses kotlin-reflect for its kotlin data class support, so many of the same things would need to be addressed anyway.

@tajobe tajobe merged commit bdf0d86 into main Jun 1, 2025
1 check passed
@tajobe tajobe mentioned this pull request Jun 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants