Replace
A high-performance, type-safe Kotlin library designed for Minecraft plugins to handle dynamic placeholders with built-in caching and smart state management.
Install / Use
/learn @MrLarkyy/ReplaceREADME
Replace 🔄
Replace is a high-performance, type-safe Kotlin library designed for Minecraft plugins to handle dynamic placeholders with built-in caching and smart state management.
✨ Key Features
- Smart Updating: Automatically avoids redundant updates to save CPU and network bandwidth (crucial for packet-based systems).
- Type-Safe Contexts: Link placeholders to specific types (e.g.,
Player,Entity, or custom objects). - Context Transformations: Easily map data types (e.g., provide a
Gameobject and automatically inheritPlayerplaceholders). - Update Intervals: Built-in throttling to control how often values are re-calculated.
- Multi-Format: Support for
Stringliterals and KyoriComponents out of the box.
📦 Installation
Add the repository and dependency to your build.gradle.kts:
repositories {
maven("https://repo.nekroplex.com/releases")
}
dependencies {
implementation("gg.aquatic.replace:Replace:26.0.2")
}
🚀 Quick Start
1. Define Placeholders
You can define placeholders that return simple strings or complex Kyori components.
// A constant placeholder (only calculated once per session)
val playerName = Placeholder.Literal<Player>("name", isConst = true) { player, _ ->
player.name
}
// A dynamic placeholder with internal arguments (e.g., %stat_kills%)
val statPlaceholder = Placeholder.Literal<Player>("stat", isConst = false) { player, arg ->
when (arg.lowercase()) {
"kills" -> getKills(player).toString()
"deaths" -> getDeaths(player).toString()
else -> "0"
}
}
2. Global Registration
Register placeholders globally so they are automatically included when creating new contexts for that type.
Placeholders.register(playerName, statPlaceholder)
3. Context & Transformations
A PlaceholderContext manages the lifecycle of your placeholders. You can transform contexts to reuse existing logic.
class MyGameSession(val player: Player, val score: Int)
// Create a context for MyGameSession that INHERITS all Player placeholders
val gameContext = Placeholders.resolverFor<MyGameSession>(
maxUpdateInterval = 20, // 20 ticks
transforms = arrayOf(
Placeholders.Transform { it.player } // Tell the context how to get a Player from a MyGameSession
)
)
4. Efficient Updating
The library uses a "State" system. You can check if a value actually changed before sending updates to a player.
val component = Component.text("Welcome %name%! Kills: %stat_kills%")
val contextItem = gameContext.createItem(mySession, component)
// Attempt to update (respects maxUpdateInterval)
val updateResult = contextItem.tryUpdate(mySession)
if (updateResult.wasUpdated) {
val newComponent = updateResult.value
player.sendMessage(newComponent)
}
5. Placeholder DSL (New! 🌳)
For complex placeholders with multiple branches and arguments (PAPI-style), you can use the built-in DSL. It handles underscored tokens and quoted arguments automatically.
Placeholders.registerDSL<Player>("rank") {
// %rank_name%
"name" {
handle { getRankName(binder) }
}
// %rank_info_<rank>%
"info" {
stringArgument("target_rank") {
handle {
val rank = string("target_rank")
"Details for $rank..."
}
}
}
// Optional arguments logic: %rank_status% or %rank_status_detailed%
"status" {
handle { "Simple Status" }
"detailed" {
handle { "Very Detailed Status" }
}
}
}
Example with shared handler
Placeholders.registerDSL<Player>("stat") {
// Shared handler for both %stat_wins% and %stat_wins_<player>%
"wins" {
handle {
val targetName = string("player") ?: binder.name
getWins(targetName).toString()
}
stringArgument("player") {
// No handler needed here; it automatically falls back to the parent
}
}
}
🔌 PlaceholderAPI Support
If PlaceholderAPI is present on the server, Replace can automatically wrap PAPI placeholders into its type-safe system using the papi identifier:
%papi_player_name% → Automatically resolved via PAPI.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
💬 Community & Support
Got questions, need help, or want to showcase what you've built with Replace? Join our community!
- Discord: Join the Aquatic Development Discord
- Issues: Open a ticket on GitHub for bugs or feature requests.
Built with ❤️ by Larkyy
Related Skills
openpencil
2.1kThe world's first open-source AI-native vector design tool and the first to feature concurrent Agent Teams. Design-as-Code. Turn prompts into UI directly on the live canvas. A modern alternative to Pencil.
ui-ux-pro-max-skill
61.3kAn AI SKILL that provide design intelligence for building professional UI/UX multiple platforms
ui-ux-pro-max-skill
61.3kAn AI SKILL that provide design intelligence for building professional UI/UX multiple platforms
onlook
25.1kThe Cursor for Designers • An Open-Source AI-First Design tool • Visually build, style, and edit your React App with AI
