Custom
custom/code
Custom Code Node
Execute arbitrary Groovy code from inside your PNode graph. Access the full Bukkit/Paper API with up to 4 inputs and 4 outputs.
Security notice: Groovy code runs with full server permissions.
Only give trusted users access to graphs containing Custom Code nodes.
Script Bindings
The following variables are available in every script:
| Variable | Type | Description |
|---|---|---|
in0–in3 |
Object |
Resolved input values. |
out0–out3 |
Object |
Must be set by the script to pass data to output ports. |
server |
org.bukkit.Server |
The Bukkit server instance. |
logger |
java.util.logging.Logger |
The PNode plugin logger. |
ctx |
dev.pnode.node.ExecutionContext |
The current graph execution context. |
plugin |
dev.pnode.PNodePlugin |
The PNode plugin instance. |
Inputs
| Name | Type | Description |
|---|---|---|
exec |
exec | Incoming execution. |
in0 |
any | Input 0 — accessible as in0 in the script. |
in1 |
any | Input 1 — accessible as in1 in the script. |
in2 |
any | Input 2 — accessible as in2 in the script. |
in3 |
any | Input 3 — accessible as in3 in the script. |
Outputs
| Name | Type | Description |
|---|---|---|
exec |
exec | Continues after execution. |
out0 |
any | Output 0 — set as out0 in the script. |
out1 |
any | Output 1 — set as out1 in the script. |
out2 |
any | Output 2 — set as out2 in the script. |
out3 |
any | Output 3 — set as out3 in the script. |
Groovy Examples
Hello World
Set out0 to a greeting.
out0 = "Hello, " + in0 + "!"
Get player UUID
Get the UUID of a player passed as in0.
out0 = in0?.getUniqueId()?.toString()
Format balance
Format a number as a currency string.
out0 = String.format("$%,.2f", (double) in0)
List all online player names
Collect all online player names into a list.
out0 = server.onlinePlayers.collect { it.name }
Check time of day
Return whether it is daytime in a world.
def world = server.getWorld("world")
def time = world?.time ?: 0
out0 = (time >= 0 && time < 12000) ? "day" : "night"
Send title with custom colours
Build and send a title using Adventure API.
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.format.NamedTextColor
def player = in0
def title = Component.text("Welcome!").color(NamedTextColor.GOLD)
def sub = Component.text("Enjoy your stay").color(NamedTextColor.GRAY)
player?.showTitle(
net.kyori.adventure.title.Title.title(title, sub)
)
Simple HTTP request (async)
Fetch data from an API asynchronously (enable async mode).
import groovy.json.JsonSlurper
def url = new URL("https://api.example.com/data")
def response = new JsonSlurper().parse(url)
logger.info("Got response: ${response}")
Math and conditions
Compute a tax amount and decide a category.
def income = (double) in0
def tax = income > 1000 ? income * 0.2 : income * 0.1
out0 = tax
out1 = tax > 200 ? "high" : "low"
Tips & Patterns
Null safety with ?.
Use the safe-navigation operator to avoid NullPointerExceptions.
// Safe — returns null if player is null instead of crashing
def name = in0?.name
out0 = name ?: "unknown"
String interpolation with GStrings
def player = in0
out0 = "Player ${player?.name} is at ${player?.location?.blockX}, ${player?.location?.blockY}"
Working with collections
// Filter online players with health below 5
def lowHealthPlayers = server.onlinePlayers
.findAll { it.health < 5 }
.collect { it.name }
out0 = lowHealthPlayers // list of names
out1 = lowHealthPlayers.size() // count
Scheduling a delayed task
Use the Bukkit scheduler from inside a Custom Code node.
def targetPlayer = in0
plugin.server.scheduler.runTaskLater(plugin, {
if (targetPlayer?.isOnline()) {
targetPlayer.sendMessage("§aThis message arrived 5 seconds later!")
}
} as Runnable, 100L) // 100 ticks = 5 seconds
Reading & writing YAML config values
// Read a value from PNode's config.yml
def webPort = plugin.config.getInt("web-server.port", 8080)
out0 = webPort
Using the execution context for cross-node data
// Store something for later nodes to read via Get Variable
ctx.setVariable("score", 42)
// Or read a previously set variable
def score = ctx.getVariable("score")
out0 = score
Parsing JSON (e.g. from an API)
import groovy.json.JsonSlurper
def jsonStr = in0 as String
def parsed = new JsonSlurper().parseText(jsonStr)
out0 = parsed.someField
out1 = parsed.anotherField
Error handling
try {
def result = someRiskyOperation(in0)
out0 = result
out1 = true // success flag
} catch (Exception e) {
logger.warning("Custom code error: ${e.message}")
out0 = null
out1 = false
}