{"ok":true,"count":166,"data":[{"id":"trigger/event","name":"Event Trigger","category":"Triggers","color":"#e74c3c","description":"Fires whenever a Bukkit/Paper event is dispatched on the server. Accepts any class that implements org.bukkit.event.Event.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Execution flow continues here when the event fires."},{"name":"event","type":"event","description":"The raw event object for use with Event Get Player, Event Cancel, etc."}],"properties":[{"key":"event","type":"event_class","default":"org.bukkit.event.player.PlayerJoinEvent","label":"Event Class","description":"Fully-qualified Bukkit event class name."},{"key":"priority","type":"select","options":["LOWEST","LOW","NORMAL","HIGH","HIGHEST","MONITOR"],"default":"NORMAL","label":"Priority","description":"Listener priority — lower fires earlier, MONITOR should not modify the event."},{"key":"ignoreCancelled","type":"boolean","default":false,"label":"Ignore Cancelled","description":"When true, this node will not fire for events that were already cancelled."}],"notes":"Use this node when you need to react to any Bukkit event that does not have a dedicated trigger node. Common events: PlayerDeathEvent, EntityDamageEvent, BlockGrowEvent, etc.","examples":[{"title":"Reward player on death","description":"Listen to PlayerDeathEvent and broadcast a message.","steps":["Set Event Class to org.bukkit.event.player.PlayerDeathEvent","Connect the event output to an Event Get Player node","Pipe the player into a Player Message node"]}]},{"id":"trigger/command","name":"Command Trigger","category":"Triggers","color":"#e67e22","description":"Registers a custom command on the server and fires the graph when it is executed.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when the command is executed."},{"name":"sender","type":"sender","description":"The CommandSender (player or console) who ran the command."},{"name":"args","type":"list","description":"List of string arguments passed after the command name."}],"properties":[{"key":"command","type":"string","default":"myscript","label":"Command Name","description":"The command without the leading slash."},{"key":"description","type":"string","default":"PNode script command","label":"Description","description":"Shown in /help."},{"key":"permission","type":"string","default":"","label":"Permission Node","description":"Required permission. Leave blank to allow everyone."},{"key":"playerOnly","type":"boolean","default":false,"label":"Player Only","description":"When true, console cannot use the command."}],"notes":"The command is registered dynamically when the graph is enabled and unregistered when it is disabled. Use a List Get node (index 0, 1, …) to access individual arguments from the args output.","examples":[{"title":"Simple /greet command","description":"Send \"Hello, <name>!\" when a player runs /greet <name>.","steps":["Set Command Name to greet","Connect sender → Player Message","Use List Get (index 0) on args to get the name argument","Use String Format (\"{0} says hello to {1}!\") before the message"]}]},{"id":"trigger/timer","name":"Timer Trigger","category":"Triggers","color":"#9b59b6","description":"Fires the graph repeatedly on a Bukkit scheduler task.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires on every tick interval."},{"name":"tick","type":"number","description":"The current server tick count at the time of firing."}],"properties":[{"key":"delay","type":"number","default":20,"label":"Initial Delay (ticks)","description":"How many ticks to wait before the first execution (20 ticks = 1 second)."},{"key":"period","type":"number","default":20,"label":"Interval (ticks)","description":"How many ticks between each execution."},{"key":"async","type":"boolean","default":false,"label":"Run Async","description":"Run off the main thread. Useful for heavy work but you must not call Bukkit API from async context."}],"notes":"The timer is started when the graph is enabled and cancelled when disabled. 20 ticks = 1 second, 200 ticks = 10 seconds, 1200 ticks = 1 minute.","examples":[{"title":"Announce every 5 minutes","description":"Broadcast a server tip every 5 minutes.","steps":["Set Interval to 6000 (5 × 60 × 20)","Connect exec → Broadcast Message","Set the broadcast message text"]}]},{"id":"trigger/manual","name":"Manual Trigger","category":"Triggers","color":"#1abc9c","description":"A trigger that can only be started manually via the PNode web editor or the /pnode run command. Useful for testing graphs.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when the graph is manually triggered."}],"properties":[],"notes":"This node does not register any event listener or scheduler task. It is purely for on-demand testing and debugging of your graph.","examples":[]},{"id":"trigger/chat","name":"Chat Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player sends a chat message. Optionally filters by a message prefix.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when the trigger conditions are met."},{"name":"player","type":"player","description":"The player who sent the message."},{"name":"message","type":"string","description":"The full chat message text."}],"properties":[{"key":"prefix","type":"string","default":"","label":"Message Prefix Filter","description":"Only fire when the message starts with this text. Leave blank to match all messages."}],"notes":"The underlying Bukkit AsyncPlayerChatEvent is used. Cancelling the event from within this graph will suppress the message from chat.","examples":[{"title":"Custom chat command via prefix","description":"React when a player types \"!heal\".","steps":["Set Prefix Filter to !heal","Connect player → Player Set Health","Set health to 20"]}]},{"id":"trigger/block_break","name":"Block Break Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player breaks a block. Optionally filters by material type.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when a block is broken."},{"name":"player","type":"player","description":"The player who broke the block."},{"name":"block","type":"string","description":"Material name of the broken block (e.g. DIAMOND_ORE)."},{"name":"location","type":"location","description":"Location of the broken block."}],"properties":[{"key":"material","type":"string","default":"","label":"Material Filter","description":"Only fire for this material. Leave blank to fire for any block."}],"notes":"Cancel this event using an Event Cancel node to prevent the block from actually being broken.","examples":[{"title":"Diamond ore drop bonus","description":"Drop an extra diamond when a player breaks DIAMOND_ORE.","steps":["Set Material Filter to DIAMOND_ORE","Connect location → Drop Item node","Add a Material node set to DIAMOND, connect name → Drop Item (material). Set amount to 1."]}]},{"id":"trigger/block_place","name":"Block Place Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player places a block. Optionally filters by material type.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when a block is placed."},{"name":"player","type":"player","description":"The player who placed the block."},{"name":"block","type":"string","description":"Material name of the placed block."},{"name":"location","type":"location","description":"Location where the block was placed."}],"properties":[{"key":"material","type":"string","default":"","label":"Material Filter","description":"Only fire for this material. Leave blank to fire for any block."}],"notes":"Cancel this event to prevent the block from being placed.","examples":[]},{"id":"trigger/player_join","name":"Player Join Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player connects to the server.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when a player joins."},{"name":"player","type":"player","description":"The player who joined."},{"name":"joinMessage","type":"string","description":"The default join message shown in chat."}],"properties":[],"notes":"A common use-case is to welcome new players, give starter kits, or teleport to spawn.","examples":[{"title":"Welcome title","description":"Show a welcome title to every player who joins.","steps":["Connect player → Send Title node","Set title to \"&6Welcome!\" and subtitle to \"&7Enjoy your stay\""]}]},{"id":"trigger/player_quit","name":"Player Quit Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player disconnects from the server.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when a player quits."},{"name":"player","type":"player","description":"The player who quit."},{"name":"quitMessage","type":"string","description":"The default quit/leave message."}],"properties":[],"notes":"Useful for cleanup tasks, saving data, or broadcasting custom leave messages.","examples":[]},{"id":"trigger/inventory_click","name":"Inventory Click Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player clicks inside any inventory.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires on click."},{"name":"player","type":"player","description":"The player who clicked."},{"name":"slot","type":"number","description":"The slot index that was clicked (0-based)."},{"name":"item","type":"item_stack","description":"The ItemStack in the clicked slot (AIR if empty)."},{"name":"inventoryTitle","type":"string","description":"The title of the open inventory."}],"properties":[],"notes":"Cancel the event using Event Cancel to prevent item movement. Filter by inventoryTitle to target custom GUI inventories.","examples":[{"title":"Custom GUI button","description":"Detect a click in a custom shop GUI and run logic.","steps":["Connect inventoryTitle → String Ops (EQUALS) → Branch","On true branch: proceed with your shop logic","Cancel the event to prevent item drag-out"]}]},{"id":"trigger/startup","name":"Startup Trigger","category":"Triggers","color":"#e74c3c","description":"Fires once when the graph is enabled (i.e. when the server starts or the graph is toggled on).","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires once at startup."}],"properties":[],"notes":"Use this to initialise data, create initial inventory setups, or broadcast a startup message.","examples":[]},{"id":"trigger/player_death","name":"Player Death Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player dies.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when a player dies."},{"name":"player","type":"player","description":"The player who died."},{"name":"killer","type":"entity","description":"Entity or player who killed them (null if killed by the environment)."},{"name":"deathMessage","type":"string","description":"The default death message."},{"name":"location","type":"location","description":"Location where the player died."}],"properties":[],"notes":"Pair with Player Respawn Trigger to run logic across the full death-respawn cycle. The killer output is an entity — use the Is Player node to check whether another player was responsible and extract the Player reference.","examples":[{"title":"Broadcast death message","description":"Send a custom death message to all players.","steps":["Connect player → Player Get Name","Use String Format to compose message","Connect to Broadcast Message node"]}]},{"id":"trigger/player_respawn","name":"Player Respawn Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player respawns after death.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when a player respawns."},{"name":"player","type":"player","description":"The player who respawned."},{"name":"location","type":"location","description":"Respawn location."}],"properties":[],"notes":"Use this to give items, effects, or messages when a player respawns.","examples":[]},{"id":"trigger/player_interact","name":"Player Interact Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player clicks a block or air. Optionally filter by action type.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires on player interaction."},{"name":"player","type":"player","description":"The player who interacted."},{"name":"action","type":"string","description":"Action type: RIGHT_CLICK_BLOCK, LEFT_CLICK_BLOCK, RIGHT_CLICK_AIR, LEFT_CLICK_AIR, PHYSICAL."},{"name":"block","type":"string","description":"Material of the clicked block (empty if air)."},{"name":"item","type":"string","description":"Material of the item held in the player's main hand (empty if hand is empty)."},{"name":"location","type":"location","description":"Location of clicked block (or player location for air clicks)."}],"properties":[{"key":"action","type":"string","default":"","label":"Action Filter","description":"Leave blank for any interaction, or specify e.g. RIGHT_CLICK_BLOCK."}],"notes":"Fires twice per click in some situations due to main-hand / off-hand. Cancel with Event Cancel to prevent default behaviour.","examples":[{"title":"Custom button on right-click","description":"Trigger logic when a player right-clicks a button block.","steps":["Set Action Filter to RIGHT_CLICK_BLOCK","Use a Branch node to check block == STONE_BUTTON","Execute your custom logic on the True branch"]}]},{"id":"trigger/player_level_up","name":"Player Level Change Trigger","category":"Triggers","color":"#e74c3c","description":"Fires whenever a player's XP level changes (up or down).","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when the player's level changes."},{"name":"player","type":"player","description":"The player whose level changed."},{"name":"oldLevel","type":"number","description":"Previous XP level."},{"name":"newLevel","type":"number","description":"New XP level."}],"properties":[],"notes":"Use Compare node (oldLevel < newLevel) to distinguish level-up from level-down events.","examples":[]},{"id":"trigger/entity_death","name":"Entity Death Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when any entity (mob or player) dies. Optionally filter by entity type.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when an entity dies."},{"name":"entity","type":"entity","description":"The entity that died."},{"name":"killer","type":"entity","description":"Entity or player who landed the killing blow (null if not killed by an entity)."},{"name":"entityType","type":"string","description":"Entity type name (e.g. ZOMBIE, SKELETON)."},{"name":"location","type":"location","description":"Location where the entity died."}],"properties":[{"key":"entityType","type":"string","default":"","label":"Entity Type Filter","description":"Only fire for this entity type. Leave blank for any entity."}],"notes":"To handle player deaths specifically use the Player Death Trigger instead. The killer output is an entity — use the Is Player node to check whether it was a player and extract the Player reference.","examples":[{"title":"Reward for killing a dragon","description":"Drop an extra reward when an ENDER_DRAGON dies.","steps":["Set Entity Type Filter to ENDER_DRAGON","Connect location → Drop Item node","Add a Material node set to ELYTRA, connect name → Drop Item (material)"]},{"title":"Reward the killer if it was a player","description":"Give a diamond to the player who killed a mob, ignore kills by other mobs.","steps":["Entity Death Trigger → killer → Is Player (entity)","Is Player → isPlayer → Branch","Branch (true) → Player Give Item (use Is Player → player)","Add a Material node set to DIAMOND, connect name → Player Give Item (material)"]}]},{"id":"trigger/entity_damage","name":"Entity Damage Trigger","category":"Triggers","color":"#e74c3c","description":"Fires whenever an entity takes damage. Optionally filter by entity type.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when an entity takes damage."},{"name":"entity","type":"entity","description":"The entity that was damaged."},{"name":"damager","type":"entity","description":"Entity or player that caused the damage (null if caused by the environment, e.g. fall or fire)."},{"name":"cause","type":"string","description":"Damage cause (e.g. ENTITY_ATTACK, FALL, FIRE, PROJECTILE)."},{"name":"damage","type":"number","description":"Raw damage amount before armour reduction."},{"name":"location","type":"location","description":"Location of the entity when damaged."}],"properties":[{"key":"entityType","type":"string","default":"","label":"Entity Type Filter","description":"Only fire for this entity type. Leave blank for any."}],"notes":"Cancel this event with Event Cancel to prevent the damage from being applied. The damager output is an entity — use the Is Player node to check whether a player caused the damage and extract the Player reference.","examples":[]},{"id":"trigger/projectile_hit","name":"Projectile Hit Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a projectile (arrow, snowball, trident, etc.) hits a block or entity.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when a projectile hits something."},{"name":"shooter","type":"entity","description":"Entity (player or mob) that fired the projectile (null if fired by a block dispenser)."},{"name":"projectileType","type":"string","description":"Projectile entity type (e.g. ARROW, SNOWBALL, TRIDENT)."},{"name":"hitEntity","type":"entity","description":"Entity that was hit (null if it hit a block)."},{"name":"hitBlock","type":"string","description":"Material of the block that was hit (empty if it hit an entity)."},{"name":"location","type":"location","description":"Location of impact."}],"properties":[{"key":"projectileType","type":"string","default":"","label":"Projectile Type Filter","description":"Leave blank for any projectile, or specify e.g. ARROW."}],"notes":"hitEntity and hitBlock are mutually exclusive — only one will be set per event. The shooter output is an entity — use the Is Player node to check whether a player fired the projectile and extract the Player reference.","examples":[{"title":"Explosive arrows","description":"Create an explosion when an arrow hits something.","steps":["Set Projectile Type Filter to ARROW","Connect location → Explosion node","Set power to 2, set fire to false"]}]},{"id":"trigger/craft_item","name":"Craft Item Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player crafts an item in a crafting table or their inventory.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when a player crafts an item."},{"name":"player","type":"player","description":"The player who crafted."},{"name":"result","type":"string","description":"Material name of the crafted item."},{"name":"amount","type":"number","description":"Amount crafted in this action."}],"properties":[{"key":"resultMaterial","type":"string","default":"","label":"Result Material Filter","description":"Only fire when this material is crafted. Leave blank for any."}],"notes":"Cancel with Event Cancel to prevent the player from picking up the crafted item.","examples":[]},{"id":"trigger/furnace_smelt","name":"Furnace Smelt Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when an item finishes smelting in a furnace, blast furnace, or smoker.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when an item finishes smelting."},{"name":"source","type":"string","description":"Material of the item that was smelted."},{"name":"result","type":"string","description":"Material of the resulting item."},{"name":"location","type":"location","description":"Location of the furnace block."}],"properties":[{"key":"resultMaterial","type":"string","default":"","label":"Result Material Filter","description":"Only fire when this material is produced. Leave blank for any."}],"notes":"Cancel with Event Cancel to prevent the item from being produced.","examples":[]},{"id":"trigger/player_move","name":"Player Move Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player moves. Use BLOCK mode to avoid extremely high event rates.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires on movement."},{"name":"player","type":"player","description":"The player who moved."},{"name":"from","type":"location","description":"Location before the move."},{"name":"to","type":"location","description":"Location after the move."}],"properties":[{"key":"mode","type":"string","default":"BLOCK","label":"Mode","description":"BLOCK = only fires when crossing a block boundary; ANY = fires on any position change (very frequent)."}],"notes":"In BLOCK mode this fires at most once per block crossed, which is suitable for most use cases. ANY mode can fire dozens of times per second per player and should only be used for precision tracking.","examples":[{"title":"Detect entry into a region","description":"Check when a player walks into a specific block area.","steps":["Player Move Trigger → to → Get Block","Compare location to a specific coordinate range"]}]},{"id":"trigger/item_pickup","name":"Item Pickup Trigger","category":"Triggers","color":"#e74c3c","description":"Fires when a player picks up an item from the ground.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Fires when an item is picked up."},{"name":"player","type":"player","description":"The player who picked up the item."},{"name":"item","type":"item_stack","description":"The ItemStack that was picked up."},{"name":"material","type":"string","description":"Material name of the picked-up item."},{"name":"amount","type":"number","description":"Amount picked up."}],"properties":[{"key":"material","type":"string","default":"","label":"Material Filter","description":"Only fire for this material (empty = any). Use uppercase e.g. DIAMOND."}],"notes":"Cancel the event using Event Cancel to prevent the player from picking up the item. The material filter is case-insensitive.","examples":[{"title":"Reward a player for picking up a diamond","description":"Give a player bonus XP when they pick up a diamond.","steps":["Item Pickup Trigger (material=DIAMOND) → exec → Player Set XP","Connect player output to Player Set XP"]}]},{"id":"flow/branch","name":"Branch (If/Else)","category":"Flow","color":"#3498db","description":"Splits execution into a true or false path based on a boolean condition.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution flow."},{"name":"condition","type":"boolean","description":"The condition to evaluate."}],"outputs":[{"name":"true","type":"exec","description":"Followed when condition is true."},{"name":"false","type":"exec","description":"Followed when condition is false."}],"properties":[],"notes":"Non-boolean values are coerced: non-zero numbers are true, non-empty strings are true, null is false.","examples":[]},{"id":"flow/sequence","name":"Sequence","category":"Flow","color":"#3498db","description":"Executes up to four output branches one after another in order.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution flow."}],"outputs":[{"name":"1st","type":"exec","description":"First branch — executed first."},{"name":"2nd","type":"exec","description":"Second branch."},{"name":"3rd","type":"exec","description":"Third branch."},{"name":"4th","type":"exec","description":"Fourth branch."}],"properties":[],"notes":"All branches are executed synchronously in order. Connect only the branches you need; unconnected outputs are skipped.","examples":[]},{"id":"flow/for_each","name":"For Each","category":"Flow","color":"#3498db","description":"Iterates over every element in a list, firing the body output for each one.","inputs":[{"name":"exec","type":"exec","description":"Starts the loop."},{"name":"list","type":"list","description":"The list to iterate over."}],"outputs":[{"name":"body","type":"exec","description":"Executed for each element in the list."},{"name":"done","type":"exec","description":"Executed once after all elements have been processed."},{"name":"element","type":"any","description":"The current element."},{"name":"index","type":"number","description":"Current index (0-based)."}],"properties":[],"notes":"Use element and index outputs only from inside the body branch. They are only valid during that iteration.","examples":[{"title":"Message all online players","description":"Send a message to every online player.","steps":["Get Online Players → list","Connect list → For Each","Connect element (as player) → Player Message"]}]},{"id":"flow/while","name":"While Loop","category":"Flow","color":"#3498db","description":"Repeatedly executes the body branch while a boolean condition is true.","inputs":[{"name":"exec","type":"exec","description":"Starts the loop."},{"name":"condition","type":"boolean","description":"Loop continues while this is true."}],"outputs":[{"name":"body","type":"exec","description":"Executed on each iteration."},{"name":"done","type":"exec","description":"Executed when the condition becomes false."}],"properties":[],"notes":"Be careful to ensure the condition can eventually become false to avoid infinite loops freezing the server thread.","examples":[]},{"id":"flow/repeat","name":"Repeat","category":"Flow","color":"#3498db","description":"Executes the body branch a fixed number of times.","inputs":[{"name":"exec","type":"exec","description":"Starts the loop."},{"name":"count","type":"number","description":"Number of repetitions (overrides the property if connected)."}],"outputs":[{"name":"body","type":"exec","description":"Executed on each iteration."},{"name":"done","type":"exec","description":"Executed after all iterations complete."},{"name":"index","type":"number","description":"Current iteration index (0-based)."}],"properties":[{"key":"count","type":"number","default":1,"label":"Count","description":"Default repeat count when the input port is not connected."}],"notes":"The index output starts at 0 and ends at count - 1.","examples":[]},{"id":"flow/return","name":"Return","category":"Flow","color":"#3498db","description":"Immediately stops execution of the current graph branch.","inputs":[{"name":"exec","type":"exec","description":"Triggers the return."}],"outputs":[],"properties":[],"notes":"Use inside loops or conditional branches to exit early without following any further nodes.","examples":[]},{"id":"flow/switch","name":"Switch","category":"Flow","color":"#3498db","description":"Routes execution to one of up to four case outputs based on a value, with a default fallback.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"value","type":"any","description":"The value to compare against cases."}],"outputs":[{"name":"case0","type":"exec","description":"Fires when value equals Case 0."},{"name":"case1","type":"exec","description":"Fires when value equals Case 1."},{"name":"case2","type":"exec","description":"Fires when value equals Case 2."},{"name":"case3","type":"exec","description":"Fires when value equals Case 3."},{"name":"default","type":"exec","description":"Fires when no case matches."}],"properties":[{"key":"case0","type":"string","default":"","label":"Case 0 Value"},{"key":"case1","type":"string","default":"","label":"Case 1 Value"},{"key":"case2","type":"string","default":"","label":"Case 2 Value"},{"key":"case3","type":"string","default":"","label":"Case 3 Value"}],"notes":"Comparison is string-based (the value is converted to string and compared). Only the first matching case fires.","examples":[]},{"id":"flow/delay","name":"Delay","category":"Flow","color":"#3498db","description":"Pauses execution for a number of ticks, then continues on the main thread.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"ticks","type":"number","description":"Ticks to wait (overrides property if connected)."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the delay."}],"properties":[{"key":"ticks","type":"number","default":20,"label":"Ticks (20 = 1 second)","description":"Default delay when the input port is not connected."}],"notes":"Uses Bukkit's runTaskLater scheduler. 20 ticks = 1 second. Execution resumes on the server main thread.","examples":[]},{"id":"flow/gate","name":"Gate","category":"Flow","color":"#3498db","description":"Only allows execution to pass through when a boolean condition is true. Acts as a one-way branch with no false path.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"condition","type":"boolean","description":"When true, execution passes through."}],"outputs":[{"name":"exec","type":"exec","description":"Execution continues only if condition is true."}],"properties":[],"notes":"Equivalent to a Branch node where only the true path is connected.","examples":[]},{"id":"flow/event_gate","name":"Event Gate","category":"Flow","color":"#3498db","description":"Merges multiple execution inputs and fires the output only when the required combination of inputs have been received (AND) or any one of them fires (OR).","inputs":[{"name":"exec_in_0","type":"exec","description":"First event input."},{"name":"exec_in_1","type":"exec","description":"Second event input."},{"name":"exec_in_2","type":"exec","description":"Third event input."},{"name":"exec_in_3","type":"exec","description":"Fourth event input."}],"outputs":[{"name":"exec","type":"exec","description":"Fires when the gate condition is satisfied."}],"properties":[{"key":"mode","type":"select","options":["AND","OR"],"default":"AND","label":"Mode","description":"AND: all configured inputs must fire before the output fires. OR: any single input fires the output."},{"key":"slots","type":"select","options":["2","3","4"],"default":"2","label":"Active Input Slots","description":"Number of active input slots."}],"notes":"In AND mode the gate resets after firing so it can be triggered again.","examples":[]},{"id":"data/string_literal","name":"String Literal","category":"Data / Literals","color":"#27ae60","description":"Outputs a constant string value.","inputs":[],"outputs":[{"name":"value","type":"string","description":"The configured string."}],"properties":[{"key":"value","type":"string","default":"","label":"Value"}],"notes":"Supports & color codes when connected to nodes that accept formatted text.","examples":[]},{"id":"data/number_literal","name":"Number Literal","category":"Data / Literals","color":"#27ae60","description":"Outputs a constant numeric value.","inputs":[],"outputs":[{"name":"value","type":"number","description":"The configured number."}],"properties":[{"key":"value","type":"number","default":0,"label":"Value"}],"notes":"Internally stored as a double-precision float.","examples":[]},{"id":"data/boolean_literal","name":"Boolean Literal","category":"Data / Literals","color":"#27ae60","description":"Outputs a constant true or false value.","inputs":[],"outputs":[{"name":"value","type":"boolean","description":"The configured boolean."}],"properties":[{"key":"value","type":"boolean","default":false,"label":"Value"}],"notes":"","examples":[]},{"id":"data/string_format","name":"String Format","category":"Data / Strings","color":"#27ae60","description":"Builds a string from a format template, replacing {0}–{3} with input arguments.","inputs":[{"name":"arg0","type":"any","description":"Replaces {0} in the format string.","optional":true},{"name":"arg1","type":"any","description":"Replaces {1} in the format string.","optional":true},{"name":"arg2","type":"any","description":"Replaces {2} in the format string.","optional":true},{"name":"arg3","type":"any","description":"Replaces {3} in the format string.","optional":true}],"outputs":[{"name":"result","type":"string","description":"The formatted string."}],"properties":[{"key":"format","type":"string","default":"Hello {0}!","label":"Format String","description":"Use {0}, {1}, {2}, {3} as placeholders."}],"notes":"Any argument not connected is replaced with an empty string.","examples":[{"title":"Player coordinates","description":"Format a player's coordinates as \"X: 100 Y: 64 Z: -50\".","steps":["Connect Player Get Location to get x, y, z","Set format to \"X: {0} Y: {1} Z: {2}\"","Connect x → arg0, y → arg1, z → arg2"]}]},{"id":"data/string_ops","name":"String Ops","category":"Data / Strings","color":"#27ae60","description":"Tests a string against a value using common string operations, returning a boolean.","inputs":[{"name":"text","type":"string","description":"The string to test."},{"name":"value","type":"string","description":"The value to check against.","optional":true}],"outputs":[{"name":"result","type":"boolean","description":"Result of the operation."}],"properties":[{"key":"op","type":"select","options":["CONTAINS","STARTS_WITH","ENDS_WITH","EQUALS_IGNORE_CASE","IS_EMPTY"],"default":"CONTAINS","label":"Operator"},{"key":"value","type":"string","default":"","label":"Value (fallback)"}],"notes":"IS_EMPTY ignores the value input.","examples":[]},{"id":"data/string_split","name":"String Split","category":"Data / Strings","color":"#27ae60","description":"Splits a string by a delimiter and returns a list of parts.","inputs":[{"name":"text","type":"string","description":"The string to split."},{"name":"delimiter","type":"string","description":"The split delimiter.","optional":true}],"outputs":[{"name":"list","type":"list","description":"The resulting parts as a list."},{"name":"size","type":"number","description":"Number of parts."}],"properties":[{"key":"delimiter","type":"string","default":",","label":"Delimiter"}],"notes":"","examples":[]},{"id":"data/string_replace","name":"String Replace","category":"Data / Strings","color":"#27ae60","description":"Replaces occurrences of a search string (or regex) with a replacement string.","inputs":[{"name":"text","type":"string","description":"The source string."},{"name":"search","type":"string","description":"Text to find.","optional":true},{"name":"replacement","type":"string","description":"Replacement text.","optional":true}],"outputs":[{"name":"result","type":"string","description":"The modified string."}],"properties":[{"key":"search","type":"string","default":"","label":"Search"},{"key":"replacement","type":"string","default":"","label":"Replacement"},{"key":"useRegex","type":"boolean","default":false,"label":"Use Regex","description":"Treat the search string as a Java regular expression."}],"notes":"","examples":[]},{"id":"data/string_length","name":"String Length","category":"Data / Strings","color":"#27ae60","description":"Returns the character length of a string.","inputs":[{"name":"text","type":"string","description":"The input string."}],"outputs":[{"name":"length","type":"number","description":"Number of characters."}],"properties":[],"notes":"","examples":[]},{"id":"data/string_case","name":"String Case","category":"Data / Strings","color":"#27ae60","description":"Converts a string to uppercase, lowercase, or title case.","inputs":[{"name":"text","type":"string","description":"The string to convert."}],"outputs":[{"name":"result","type":"string","description":"The converted string."}],"properties":[{"key":"mode","type":"select","options":["UPPER","LOWER","TITLE"],"default":"UPPER","label":"Mode"}],"notes":"","examples":[]},{"id":"data/add","name":"Add","category":"Data / Math","color":"#27ae60","description":"Adds two numbers (A + B).","inputs":[{"name":"a","type":"number","description":"First number."},{"name":"b","type":"number","description":"Second number."}],"outputs":[{"name":"result","type":"number","description":"A + B."}],"properties":[],"notes":"","examples":[]},{"id":"data/subtract","name":"Subtract","category":"Data / Math","color":"#27ae60","description":"Subtracts B from A (A - B).","inputs":[{"name":"a","type":"number","description":"Number to subtract from."},{"name":"b","type":"number","description":"Amount to subtract."}],"outputs":[{"name":"result","type":"number","description":"A - B."}],"properties":[],"notes":"","examples":[]},{"id":"data/multiply","name":"Multiply","category":"Data / Math","color":"#27ae60","description":"Multiplies two numbers (A × B).","inputs":[{"name":"a","type":"number","description":"First factor."},{"name":"b","type":"number","description":"Second factor."}],"outputs":[{"name":"result","type":"number","description":"A × B."}],"properties":[],"notes":"","examples":[]},{"id":"data/divide","name":"Divide","category":"Data / Math","color":"#27ae60","description":"Divides A by B (A ÷ B). Returns 0 if B is zero.","inputs":[{"name":"a","type":"number","description":"Dividend."},{"name":"b","type":"number","description":"Divisor."}],"outputs":[{"name":"result","type":"number","description":"A ÷ B, or 0 when B is zero."}],"properties":[],"notes":"Division by zero is handled safely — returns 0 instead of throwing.","examples":[]},{"id":"data/modulo","name":"Modulo","category":"Data / Math","color":"#27ae60","description":"Returns the remainder of A ÷ B. Returns 0 if B is zero.","inputs":[{"name":"a","type":"number","description":"Dividend."},{"name":"b","type":"number","description":"Divisor."}],"outputs":[{"name":"result","type":"number","description":"Remainder of A ÷ B."}],"properties":[],"notes":"Useful for even/odd checks (a % 2) or cycling through ranges.","examples":[]},{"id":"data/math_op","name":"Math Op","category":"Data / Math","color":"#27ae60","description":"Advanced math operations: power, square root, absolute value, floor, ceil, round, min, max, log, sin, cos, tan.","inputs":[{"name":"a","type":"number","description":"Primary input."},{"name":"b","type":"number","description":"Secondary input (used for POWER, MIN, MAX)."}],"outputs":[{"name":"result","type":"number","description":"Computed result."}],"properties":[{"key":"op","type":"select","options":["POWER","SQRT","ABS","FLOOR","CEIL","ROUND","MIN","MAX","LOG","LOG10","SIN","COS","TAN"],"default":"POWER","label":"Operation"}],"notes":"Trigonometric functions expect input in radians.","examples":[]},{"id":"data/random","name":"Random","category":"Data / Math","color":"#27ae60","description":"Generates a random number between min and max (inclusive).","inputs":[{"name":"min","type":"number","description":"Minimum value.","optional":true},{"name":"max","type":"number","description":"Maximum value.","optional":true}],"outputs":[{"name":"result","type":"number","description":"Random number."}],"properties":[{"key":"min","type":"number","default":0,"label":"Min"},{"key":"max","type":"number","default":100,"label":"Max"},{"key":"integerOnly","type":"boolean","default":false,"label":"Integer Only","description":"When true, rounds the result to a whole number."}],"notes":"","examples":[]},{"id":"data/clamp","name":"Clamp","category":"Data / Math","color":"#27ae60","description":"Clamps a number between a minimum and maximum value.","inputs":[{"name":"value","type":"number","description":"The value to clamp."},{"name":"min","type":"number","description":"Minimum bound.","optional":true},{"name":"max","type":"number","description":"Maximum bound.","optional":true}],"outputs":[{"name":"result","type":"number","description":"The clamped value."}],"properties":[{"key":"min","type":"number","default":0,"label":"Min"},{"key":"max","type":"number","default":100,"label":"Max"}],"notes":"Useful for keeping health, food level, or balances within valid ranges.","examples":[]},{"id":"data/compare","name":"Compare","category":"Data / Logic","color":"#27ae60","description":"Compares two values and returns a boolean result.","inputs":[{"name":"a","type":"any","description":"Left operand."},{"name":"b","type":"any","description":"Right operand."}],"outputs":[{"name":"result","type":"boolean","description":"Result of the comparison."}],"properties":[{"key":"op","type":"select","options":["EQUALS","NOT_EQUALS","LESS_THAN","LESS_EQ","GREATER_THAN","GREATER_EQ","CONTAINS"],"default":"EQUALS","label":"Operator"}],"notes":"CONTAINS checks if string A contains string B, or if list A contains element B.","examples":[]},{"id":"data/logic_op","name":"Logic Op","category":"Data / Logic","color":"#27ae60","description":"Performs a boolean logic operation: AND, OR, NOT, or XOR.","inputs":[{"name":"a","type":"boolean","description":"First boolean."},{"name":"b","type":"boolean","description":"Second boolean (ignored for NOT)."}],"outputs":[{"name":"result","type":"boolean","description":"Result of the logic operation."}],"properties":[{"key":"op","type":"select","options":["AND","OR","NOT","XOR"],"default":"AND","label":"Operation"}],"notes":"For NOT, only input A is used.","examples":[]},{"id":"data/is_null","name":"Is Null","category":"Data / Logic","color":"#27ae60","description":"Checks whether a value is null (or optionally blank).","inputs":[{"name":"value","type":"any","description":"The value to check."}],"outputs":[{"name":"isNull","type":"boolean","description":"True when the value is null."},{"name":"notNull","type":"boolean","description":"True when the value is not null."}],"properties":[{"key":"checkBlank","type":"boolean","default":false,"label":"Also treat blank strings as null"}],"notes":"","examples":[]},{"id":"data/get_variable","name":"Get Variable","category":"Data / Variables","color":"#27ae60","description":"Reads a named variable from the execution context.","inputs":[],"outputs":[{"name":"value","type":"any","description":"The stored value, or null if not set."}],"properties":[{"key":"name","type":"string","default":"myVar","label":"Variable Name","description":"Case-sensitive variable name."}],"notes":"Variables are scoped to the current graph execution context. They do not persist between separate trigger firings unless stored externally.","examples":[]},{"id":"data/set_variable","name":"Set Variable","category":"Data / Variables","color":"#27ae60","description":"Stores a value into a named variable in the execution context.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"value","type":"any","description":"The value to store."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after storing."},{"name":"value","type":"any","description":"The stored value (pass-through)."}],"properties":[{"key":"name","type":"string","default":"myVar","label":"Variable Name"}],"notes":"Pair with Get Variable to read the stored value later in the same graph execution.","examples":[]},{"id":"data/counter","name":"Counter","category":"Data / Variables","color":"#27ae60","description":"A stateful counter node that persists its value across executions within the same graph lifecycle.","inputs":[{"name":"exec","type":"exec","description":"Triggers the operation."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"value","type":"number","description":"Current counter value after the operation."}],"properties":[{"key":"op","type":"select","options":["INCREMENT","DECREMENT","RESET","GET"],"default":"INCREMENT","label":"Operation"},{"key":"step","type":"number","default":1,"label":"Step Amount","description":"How much to increment or decrement."}],"notes":"The counter resets to 0 when the graph is reloaded. Use for things like counting how many times an event fires.","examples":[]},{"id":"data/to_string","name":"To String","category":"Data / Conversion","color":"#27ae60","description":"Converts any value to its string representation.","inputs":[{"name":"value","type":"any","description":"The value to convert."}],"outputs":[{"name":"result","type":"string","description":"String representation."}],"properties":[],"notes":"Null becomes the string \"null\".","examples":[]},{"id":"data/to_number","name":"To Number","category":"Data / Conversion","color":"#27ae60","description":"Converts a value (usually a string) to a number.","inputs":[{"name":"value","type":"any","description":"The value to convert."}],"outputs":[{"name":"number","type":"number","description":"The numeric value, or 0 on failure."},{"name":"success","type":"boolean","description":"False if conversion failed."}],"properties":[],"notes":"Check the success output before using the result if the input may not always be a valid number.","examples":[]},{"id":"data/list_create","name":"List Create","category":"Data / Lists","color":"#27ae60","description":"Creates a new empty list.","inputs":[],"outputs":[{"name":"list","type":"list","description":"A new empty list."}],"properties":[],"notes":"Use List Add to populate the list with values.","examples":[]},{"id":"data/list_add","name":"List Add","category":"Data / Lists","color":"#27ae60","description":"Adds a value to a list and returns the modified list.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"list","type":"list","description":"The list to add to."},{"name":"value","type":"any","description":"The value to add."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after adding."},{"name":"list","type":"list","description":"The modified list."}],"properties":[],"notes":"Modifies the list in-place and also returns it for chaining.","examples":[]},{"id":"data/list_get","name":"List Get","category":"Data / Lists","color":"#27ae60","description":"Returns the element at a given index in a list.","inputs":[{"name":"list","type":"list","description":"The list."},{"name":"index","type":"number","description":"0-based index."}],"outputs":[{"name":"value","type":"any","description":"The element at the given index, or null if out of range."}],"properties":[],"notes":"Indices are 0-based. Out-of-range indices return null.","examples":[]},{"id":"data/list_size","name":"List Size","category":"Data / Lists","color":"#27ae60","description":"Returns the number of elements in a list.","inputs":[{"name":"list","type":"list","description":"The list."}],"outputs":[{"name":"size","type":"number","description":"Number of elements."}],"properties":[],"notes":"","examples":[]},{"id":"data/list_remove","name":"List Remove","category":"Data / Lists","color":"#27ae60","description":"Removes an element from a list by index or by value.","inputs":[{"name":"list","type":"list","description":"The source list."},{"name":"indexValue","type":"any","description":"Index (number) or value to remove.","optional":true}],"outputs":[{"name":"list","type":"list","description":"Modified list (a copy with the element removed)."},{"name":"removed","type":"any","description":"The element that was removed, or null if not found."}],"properties":[{"key":"mode","type":"select","options":["BY_INDEX","BY_VALUE"],"default":"BY_INDEX","label":"Mode"},{"key":"index","type":"number","default":0,"label":"Index (fallback)"}],"notes":"","examples":[]},{"id":"data/list_contains","name":"List Contains","category":"Data / Lists","color":"#27ae60","description":"Checks whether a list contains a specific value.","inputs":[{"name":"list","type":"list","description":"The list to search."},{"name":"value","type":"any","description":"Value to look for."}],"outputs":[{"name":"contains","type":"boolean","description":"True if the value is found."},{"name":"index","type":"number","description":"First index of the match, or -1 if not found."}],"properties":[],"notes":"","examples":[]},{"id":"data/list_reverse","name":"List Reverse / Sort","category":"Data / Lists","color":"#27ae60","description":"Reverses, shuffles, or sorts a list.","inputs":[{"name":"list","type":"list","description":"The list to transform."}],"outputs":[{"name":"list","type":"list","description":"The transformed list."}],"properties":[{"key":"mode","type":"select","options":["REVERSE","SHUFFLE","SORT_ASC","SORT_DESC"],"default":"REVERSE","label":"Mode"}],"notes":"SORT_ASC and SORT_DESC convert elements to strings for comparison.","examples":[]},{"id":"data/map_create","name":"Create Map","category":"Data / Map","color":"#8e44ad","description":"Creates a new empty Map (key-value store).","inputs":[],"outputs":[{"name":"map","type":"any","description":"The new empty Map."}],"properties":[],"notes":"Maps use string keys and can store any value type. Use Map Set to add entries and Map Get to retrieve them.","examples":[{"title":"Build a player data map","description":"Create a map to hold player statistics.","steps":["Create Map → map → Map Set (key=\"kills\", value=0)","Map Set → map → Map Set (key=\"deaths\", value=0)"]}]},{"id":"data/map_set","name":"Map Set","category":"Data / Map","color":"#8e44ad","description":"Inserts or updates a key-value pair in a Map.","inputs":[{"name":"map","type":"any","description":"The Map to modify."},{"name":"key","type":"string","description":"The key to set.","optional":true},{"name":"value","type":"any","description":"The value to store.","optional":true}],"outputs":[{"name":"map","type":"any","description":"The Map after insertion (same reference)."}],"properties":[{"key":"key","type":"string","default":"","label":"Key (fallback)"}],"notes":"If the key already exists its value is overwritten. The map output is the same object mutated in place.","examples":[]},{"id":"data/map_get","name":"Map Get","category":"Data / Map","color":"#8e44ad","description":"Retrieves a value from a Map by key.","inputs":[{"name":"map","type":"any","description":"The Map to read from."},{"name":"key","type":"string","description":"The key to look up.","optional":true}],"outputs":[{"name":"value","type":"any","description":"The value at the key (null if absent)."},{"name":"found","type":"boolean","description":"True if the key exists in the map."}],"properties":[{"key":"key","type":"string","default":"","label":"Key (fallback)"}],"notes":"Returns null and found=false if the key does not exist. Use Is Null to handle missing values safely.","examples":[]},{"id":"data/map_remove","name":"Map Remove","category":"Data / Map","color":"#8e44ad","description":"Removes a key-value pair from a Map.","inputs":[{"name":"map","type":"any","description":"The Map to modify."},{"name":"key","type":"string","description":"The key to remove.","optional":true}],"outputs":[{"name":"map","type":"any","description":"The Map after removal (same reference)."},{"name":"removed","type":"any","description":"The value that was removed (null if the key was absent)."}],"properties":[{"key":"key","type":"string","default":"","label":"Key (fallback)"}],"notes":"No error is thrown if the key does not exist — removed will simply be null.","examples":[]},{"id":"data/map_contains","name":"Map Contains","category":"Data / Map","color":"#8e44ad","description":"Checks whether a Map contains a given key.","inputs":[{"name":"map","type":"any","description":"The Map to check."},{"name":"key","type":"string","description":"The key to look for.","optional":true}],"outputs":[{"name":"found","type":"boolean","description":"True if the key exists."},{"name":"size","type":"number","description":"Current number of entries in the map."}],"properties":[{"key":"key","type":"string","default":"","label":"Key (fallback)"}],"notes":"Does not retrieve the value — use Map Get for that. The size output is always available regardless of the key result.","examples":[]},{"id":"data/map_keys","name":"Map Keys & Values","category":"Data / Map","color":"#8e44ad","description":"Extracts all keys, all values, and the size of a Map.","inputs":[{"name":"map","type":"any","description":"The Map to decompose."}],"outputs":[{"name":"keys","type":"list","description":"List of all keys (strings), in insertion order."},{"name":"values","type":"list","description":"List of all values, in key order."},{"name":"size","type":"number","description":"Number of entries."}],"properties":[],"notes":"Pairs of keys[i] and values[i] correspond to the same entry. Use For Each on the keys list to iterate over all entries.","examples":[{"title":"Iterate over all map entries","description":"Print every key-value pair in a map.","steps":["Map Keys & Values → keys → For Each","For Each → item (key) → Map Get (retrieve corresponding value)","Player Message with formatted key+value"]}]},{"id":"data/vector","name":"Vector","category":"Data / Vectors","color":"#27ae60","description":"Creates a 3D vector from X, Y, Z components.","inputs":[{"name":"x","type":"number","description":"X component.","optional":true},{"name":"y","type":"number","description":"Y component.","optional":true},{"name":"z","type":"number","description":"Z component.","optional":true}],"outputs":[{"name":"vector","type":"vector","description":"The resulting Vector."}],"properties":[{"key":"x","type":"number","default":0,"label":"X"},{"key":"y","type":"number","default":0,"label":"Y"},{"key":"z","type":"number","default":0,"label":"Z"}],"notes":"Connected inputs override the property defaults.","examples":[]},{"id":"data/vector_components","name":"Vector Components","category":"Data / Vectors","color":"#27ae60","description":"Decomposes a vector into its X, Y, Z components and length.","inputs":[{"name":"vector","type":"vector","description":"The vector to decompose."}],"outputs":[{"name":"x","type":"number","description":"X component."},{"name":"y","type":"number","description":"Y component."},{"name":"z","type":"number","description":"Z component."},{"name":"length","type":"number","description":"Magnitude (length) of the vector."}],"properties":[],"notes":"","examples":[]},{"id":"data/vector_ops","name":"Vector Ops","category":"Data / Vectors","color":"#27ae60","description":"Performs operations on one or two vectors: ADD, SUBTRACT, SCALE, NORMALIZE, DOT, CROSS, LENGTH, DISTANCE.","inputs":[{"name":"vectorA","type":"vector","description":"Primary vector."},{"name":"vectorB","type":"vector","description":"Secondary vector (for binary operations).","optional":true},{"name":"scalar","type":"number","description":"Scale factor (for SCALE operation).","optional":true}],"outputs":[{"name":"result","type":"vector","description":"Resulting vector (for vector-output operations)."},{"name":"scalar","type":"number","description":"Scalar result (for DOT, LENGTH, DISTANCE)."}],"properties":[{"key":"op","type":"select","options":["ADD","SUBTRACT","SCALE","NORMALIZE","DOT","CROSS","LENGTH","DISTANCE"],"default":"ADD","label":"Operation"},{"key":"scalar","type":"number","default":1,"label":"Scale Factor (fallback)"}],"notes":"","examples":[]},{"id":"data/vector_between","name":"Vector Between","category":"Data / Vectors","color":"#27ae60","description":"Computes the vector from one location to another, along with distance.","inputs":[{"name":"from","type":"location","description":"Origin location."},{"name":"to","type":"location","description":"Target location."}],"outputs":[{"name":"vector","type":"vector","description":"Direction vector (to - from)."},{"name":"normalized","type":"vector","description":"Unit direction vector."},{"name":"distance","type":"number","description":"Euclidean distance."},{"name":"distanceSquared","type":"number","description":"Squared distance (cheaper to compute)."}],"properties":[],"notes":"Use the normalized output to launch a projectile or entity in a direction.","examples":[]},{"id":"data/material","name":"Material","category":"Data / Materials","color":"#27ae60","description":"Resolves and validates a Bukkit material name.","inputs":[],"outputs":[{"name":"name","type":"string","description":"Canonical Bukkit enum name (e.g. DIAMOND, STONE)."},{"name":"found","type":"boolean","description":"True if the name matched a known Bukkit Material."},{"name":"isBlock","type":"boolean","description":"True if this material can be placed as a block in the world."},{"name":"isItem","type":"boolean","description":"True if this material can exist as an item in an inventory."}],"properties":[{"key":"material","type":"string","default":"minecraft:stone","label":"Material","description":"Material name (e.g. minecraft:diamond, DIAMOND)."}],"notes":"Use minecraft: namespaced IDs (e.g. minecraft:diamond) or Bukkit enum names (e.g. DIAMOND). The name output always returns the canonical Bukkit enum name.","examples":[{"title":"Check block material before breaking","description":"Use a material constant to compare against a block-break trigger output.","steps":["Add a Material node, set name to minecraft:diamond_ore","Connect Material → name → Compare (block output from Block Break Trigger)","Execute custom logic on the true branch"]}]},{"id":"item/create","name":"Create Item","category":"Item","color":"#e67e22","description":"Creates an ItemStack from a material name and optional amount.","inputs":[{"name":"material","type":"string","description":"Material name (e.g. minecraft:diamond or DIAMOND).","optional":true},{"name":"amount","type":"number","description":"Stack size (1–64).","optional":true}],"outputs":[{"name":"item","type":"item_stack","description":"The constructed ItemStack."}],"properties":[{"key":"material","type":"string","default":"minecraft:stone","label":"Material"},{"key":"amount","type":"number","default":1,"label":"Amount"}],"notes":"Use this as the starting point for any item manipulation chain. Connect the output to Item Modify, Item Enchant, or Player Give Item.","examples":[{"title":"Give a player a diamond sword","description":"Create an item and give it to a player.","steps":["Create Item (DIAMOND_SWORD, 1) → item → Player Give Item"]}]},{"id":"item/inspect","name":"Item Inspect","category":"Item","color":"#e67e22","description":"Reads properties from an ItemStack — material, display name, lore, amount, damage, and more.","inputs":[{"name":"item","type":"item_stack","description":"The ItemStack to inspect."}],"outputs":[{"name":"material","type":"string","description":"Namespaced material key (e.g. minecraft:diamond)."},{"name":"displayName","type":"string","description":"Custom display name (empty string if not set)."},{"name":"lore","type":"list","description":"List of lore lines (empty list if none)."},{"name":"amount","type":"number","description":"Stack size."},{"name":"damage","type":"number","description":"Current durability damage taken (0 = undamaged)."},{"name":"maxDurability","type":"number","description":"Maximum durability of the item type (0 for indestructible)."},{"name":"customModelData","type":"number","description":"Custom model data value (-1 if not set)."},{"name":"isUnbreakable","type":"boolean","description":"True if the item has the unbreakable flag set."},{"name":"isAir","type":"boolean","description":"True if the item is AIR or an empty slot."}],"properties":[],"notes":"All outputs are read-only — the original ItemStack is not modified. Use Item Modify to change properties.","examples":[{"title":"Check the held item material","description":"Inspect what material a player is holding.","steps":["Held Item (GET) → item → Item Inspect","Item Inspect → material → Compare (== minecraft:diamond_sword)"]}]},{"id":"item/modify","name":"Item Modify","category":"Item","color":"#e67e22","description":"Returns a modified clone of an ItemStack. Only connected optional inputs are applied.","inputs":[{"name":"item","type":"item_stack","description":"The source ItemStack (will be cloned, not mutated)."},{"name":"displayName","type":"string","description":"New display name — supports & color codes.","optional":true},{"name":"lore","type":"list","description":"New lore lines as a list of strings.","optional":true},{"name":"amount","type":"number","description":"New stack size.","optional":true},{"name":"damage","type":"number","description":"Durability damage to apply (0 = undamaged).","optional":true},{"name":"customModelData","type":"number","description":"Custom model data value.","optional":true}],"outputs":[{"name":"item","type":"item_stack","description":"The modified ItemStack clone."}],"properties":[],"notes":"The original item is never changed. Only inputs that are connected change the clone. Chain multiple Item Modify nodes for complex transformations.","examples":[{"title":"Create a named sword","description":"Create an iron sword with a custom name and lore.","steps":["Create Item (IRON_SWORD) → Item Modify","String Literal (\"&6Excalibur\") → displayName","List Create + List Add (\"&7A legendary blade\") → lore","Item Modify → item → Player Give Item"]}]},{"id":"item/enchant","name":"Item Enchant","category":"Item","color":"#e67e22","description":"Gets, sets, checks, or removes an enchantment on an ItemStack.","inputs":[{"name":"item","type":"item_stack","description":"The source ItemStack."},{"name":"enchantment","type":"string","description":"Enchantment name (e.g. sharpness, unbreaking).","optional":true},{"name":"level","type":"number","description":"Enchantment level (SET only).","optional":true}],"outputs":[{"name":"item","type":"item_stack","description":"Modified clone (SET/REMOVE) or unchanged item (GET/HAS)."},{"name":"level","type":"number","description":"Current enchantment level (GET), or 0 if not present."},{"name":"has","type":"boolean","description":"True if the enchantment is present (HAS)."}],"properties":[{"key":"op","type":"string","default":"GET","label":"Operation","description":"GET, SET, REMOVE, or HAS."},{"key":"enchantment","type":"string","default":"sharpness","label":"Enchantment"},{"key":"level","type":"number","default":1,"label":"Level"}],"notes":"Uses the Paper Registry API — enchantment names are lowercase (e.g. \"sharpness\", \"protection\", \"unbreaking\"). SET and REMOVE return a cloned item; GET and HAS return the original unchanged.","examples":[{"title":"Give a Sharpness V sword","description":"Create a sword and enchant it.","steps":["Create Item (DIAMOND_SWORD) → Item Enchant","Set op=SET, enchantment=sharpness, level=5","Item Enchant → item → Player Give Item"]}]},{"id":"item/compare","name":"Item Compare","category":"Item","color":"#e67e22","description":"Compares two ItemStacks for similarity or full equality.","inputs":[{"name":"item_a","type":"item_stack","description":"First ItemStack."},{"name":"item_b","type":"item_stack","description":"Second ItemStack."}],"outputs":[{"name":"similar","type":"boolean","description":"True if both items are the same type and metadata (ignoring stack size)."},{"name":"identical","type":"boolean","description":"True if both items are exactly equal including stack size."}],"properties":[],"notes":"\"Similar\" uses Bukkit's isSimilar() — matching material, display name, lore, enchantments, and NBT but not amount. \"Identical\" uses equals() which also checks amount.","examples":[{"title":"Check if held item matches a required item","description":"Verify a player is holding the correct item type.","steps":["Held Item (GET) → item_a → Item Compare","Create Item (IRON_SWORD) → item_b → Item Compare","Item Compare → similar → Branch"]}]},{"id":"item/pdc","name":"Item PDC","category":"Item","color":"#e67e22","description":"Reads or writes a PersistentDataContainer value on an ItemStack.","inputs":[{"name":"item","type":"item_stack","description":"The source ItemStack (will be cloned on SET/REMOVE)."},{"name":"key","type":"string","description":"PDC key name (namespaced as \"pnode:key\").","optional":true},{"name":"value","type":"string","description":"Value to store (SET only).","optional":true}],"outputs":[{"name":"item","type":"item_stack","description":"Modified clone (SET/REMOVE) or unchanged item (GET/HAS)."},{"name":"value","type":"string","description":"Retrieved value as string (GET), or empty string if not found."},{"name":"has","type":"boolean","description":"True if the key exists (HAS)."}],"properties":[{"key":"op","type":"string","default":"GET","label":"Operation","description":"GET, SET, HAS, or REMOVE."},{"key":"key","type":"string","default":"my_key","label":"Key"},{"key":"value","type":"string","default":"","label":"Value"},{"key":"valueType","type":"string","default":"STRING","label":"Value Type","description":"STRING, INTEGER, DOUBLE, or BOOLEAN."}],"notes":"PDC values are stored inside the ItemMeta — SET and REMOVE must return a cloned ItemStack with the updated meta. Always pass the returned item output to the next node. Keys use the \"pnode\" namespace (e.g. \"pnode:my_key\").","examples":[{"title":"Tag an item with custom data","description":"Mark an item as a quest item using PDC.","steps":["Create Item (COMPASS) → Item PDC","Set op=SET, key=quest_id, value=dragon_quest, valueType=STRING","Item PDC → item → Player Give Item"]}]},{"id":"paper/player_message","name":"Send Message","category":"Player","color":"#2ecc71","description":"Sends a chat message to a player or command sender. Supports & color codes.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"target","type":"sender","description":"Player or CommandSender to message."},{"name":"message","type":"string","description":"Message text (& color codes supported).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after sending."}],"properties":[{"key":"message","type":"string","default":"Hello {player}!","label":"Default Message"}],"notes":"If the message input is not connected, the property value is used. Supports legacy & color codes (e.g. &6Gold, &cRed).","examples":[]},{"id":"paper/broadcast_message","name":"Broadcast Message","category":"Player","color":"#2ecc71","description":"Sends a message to all players on the server.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"message","type":"string","description":"Message to broadcast."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after broadcasting."}],"properties":[{"key":"message","type":"string","default":"Server announcement!","label":"Default Message"}],"notes":"Supports & color codes.","examples":[]},{"id":"paper/player_teleport","name":"Player Teleport","category":"Player","color":"#2ecc71","description":"Teleports a player to a location.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player to teleport."},{"name":"location","type":"location","description":"The destination location."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after teleporting."}],"properties":[],"notes":"Uses Paper's async teleport. Cross-world teleportation is supported. To teleport a non-player entity, use the Entity Teleport node instead.","examples":[]},{"id":"paper/player_get_name","name":"Get Player Name","category":"Player","color":"#2ecc71","description":"Gets the username and display name of a player.","inputs":[{"name":"player","type":"player","description":"The player."}],"outputs":[{"name":"name","type":"string","description":"The player's username."},{"name":"displayName","type":"string","description":"The player's display name (may include colour codes from prefix plugins)."}],"properties":[],"notes":"","examples":[]},{"id":"paper/player_get_health","name":"Get Player Health","category":"Player","color":"#2ecc71","description":"Returns the player's current health, max health, and food level.","inputs":[{"name":"player","type":"player","description":"The player."}],"outputs":[{"name":"health","type":"number","description":"Current health (0–20 by default)."},{"name":"maxHealth","type":"number","description":"Maximum health."},{"name":"food","type":"number","description":"Current food level (0–20)."}],"properties":[],"notes":"","examples":[]},{"id":"paper/player_set_health","name":"Set Player Health","category":"Player","color":"#2ecc71","description":"Sets a player's health to a specific value.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."},{"name":"health","type":"number","description":"New health value.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after setting."}],"properties":[{"key":"health","type":"number","default":20,"label":"Health"}],"notes":"Value is clamped between 0 and the player's max health. Setting to 0 kills the player.","examples":[]},{"id":"paper/player_get_location","name":"Get Player Location","category":"Player","color":"#2ecc71","description":"Returns the player's current location and coordinates.","inputs":[{"name":"player","type":"player","description":"The player."}],"outputs":[{"name":"location","type":"location","description":"Full location object."},{"name":"x","type":"number","description":"X coordinate."},{"name":"y","type":"number","description":"Y coordinate."},{"name":"z","type":"number","description":"Z coordinate."},{"name":"world","type":"string","description":"World name."}],"properties":[],"notes":"","examples":[]},{"id":"paper/player_give_item","name":"Player Give Item","category":"Player","color":"#2ecc71","description":"Gives an item to a player's inventory. Accepts an ItemStack or a material name.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."},{"name":"item","type":"item_stack","description":"ItemStack to give — takes priority over material/amount.","optional":true},{"name":"material","type":"string","description":"Material name (used when no item is connected).","optional":true},{"name":"amount","type":"number","description":"Stack size (used when no item is connected).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after giving."}],"properties":[{"key":"material","type":"string","default":"DIAMOND","label":"Material"},{"key":"amount","type":"number","default":1,"label":"Amount"}],"notes":"If the player's inventory is full, items are dropped at their location. Connect an item_stack from Create Item or Item Modify for full control over the item, or use the material/amount fallback for simple cases.","examples":[]},{"id":"paper/player_kick","name":"Player Kick","category":"Player","color":"#2ecc71","description":"Kicks a player from the server with an optional reason.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player to kick."},{"name":"reason","type":"string","description":"Kick reason shown to the player.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after kicking."}],"properties":[{"key":"reason","type":"string","default":"You have been kicked.","label":"Default Reason"}],"notes":"Supports & color codes in the reason.","examples":[]},{"id":"paper/player_xp","name":"Get Player XP","category":"Player","color":"#2ecc71","description":"Returns a player's experience level, total experience, and progress within the current level.","inputs":[{"name":"player","type":"player","description":"The player."}],"outputs":[{"name":"level","type":"number","description":"Current XP level."},{"name":"totalExp","type":"number","description":"Total experience points."},{"name":"expProgress","type":"number","description":"Progress within the current level (0.0–1.0)."}],"properties":[],"notes":"","examples":[]},{"id":"paper/player_set_xp","name":"Set Player XP","category":"Player","color":"#2ecc71","description":"Sets or modifies a player's experience.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."},{"name":"value","type":"number","description":"Amount to set or add.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after setting."}],"properties":[{"key":"mode","type":"select","options":["LEVEL","TOTAL_EXP","ADD_EXP"],"default":"LEVEL","label":"Mode","description":"LEVEL: set level directly. TOTAL_EXP: set total exp. ADD_EXP: add exp points."},{"key":"value","type":"number","default":0,"label":"Value (fallback)"}],"notes":"","examples":[]},{"id":"paper/player_gamemode","name":"Player Game Mode","category":"Player","color":"#2ecc71","description":"Gets or sets a player's game mode.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."},{"name":"gameMode","type":"string","description":"New game mode (for SET operation).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"gameMode","type":"string","description":"Current game mode name."}],"properties":[{"key":"op","type":"select","options":["GET","SET"],"default":"GET","label":"Operation"},{"key":"gameMode","type":"select","options":["SURVIVAL","CREATIVE","ADVENTURE","SPECTATOR"],"default":"SURVIVAL","label":"Game Mode"}],"notes":"","examples":[]},{"id":"paper/player_has_permission","name":"Player Has Permission","category":"Player","color":"#2ecc71","description":"Checks whether a player has a specific permission node.","inputs":[{"name":"player","type":"player","description":"The player."},{"name":"permission","type":"string","description":"Permission node to check.","optional":true}],"outputs":[{"name":"result","type":"boolean","description":"True if the player has the permission."}],"properties":[{"key":"permission","type":"string","default":"","label":"Permission"}],"notes":"","examples":[]},{"id":"paper/player_is_online","name":"Player Is Online","category":"Player","color":"#2ecc71","description":"Checks whether a player is currently online by name.","inputs":[{"name":"name","type":"string","description":"Player name.","optional":true}],"outputs":[{"name":"online","type":"boolean","description":"True if the player is online."},{"name":"player","type":"player","description":"The online player object (null if offline)."}],"properties":[{"key":"name","type":"string","default":"","label":"Player Name (fallback)"}],"notes":"","examples":[]},{"id":"paper/player_set_food","name":"Set Player Food","category":"Player","color":"#2ecc71","description":"Sets a player's food level and saturation.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."},{"name":"food","type":"number","description":"Food level (0–20).","optional":true},{"name":"saturation","type":"number","description":"Saturation (0–20).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after setting."}],"properties":[{"key":"food","type":"number","default":20,"label":"Food Level (0–20)"},{"key":"saturation","type":"number","default":20,"label":"Saturation (0.0–20.0)"}],"notes":"","examples":[]},{"id":"paper/player_get_food","name":"Get Food","category":"Player","color":"#2ecc71","description":"Gets the food level and saturation of a player.","inputs":[{"name":"player","type":"player","description":"The player to read food from."}],"outputs":[{"name":"food","type":"number","description":"Current food level (0–20)."},{"name":"saturation","type":"number","description":"Current saturation (0.0–20.0)."}],"properties":[],"notes":"Food level 20 is full, 0 is starving. Saturation drains before food level, acting as a buffer. Use Set Food to modify these values.","examples":[{"title":"Check if a player is hungry","description":"Trigger logic when food drops below 6.","steps":["Get Food → food → Compare (< 6) → Branch"]}]},{"id":"paper/player_uuid","name":"Player UUID","category":"Player","color":"#2ecc71","description":"Gets the UUID string of a player.","inputs":[{"name":"player","type":"player","description":"The player."}],"outputs":[{"name":"uuid","type":"string","description":"UUID string (e.g. 069a79f4-44e9-4726-a5be-fca90e38aaf5)."}],"properties":[],"notes":"UUIDs are stable player identifiers that do not change even if a player renames their account. Use Get Player by UUID to look up a player from a stored UUID.","examples":[]},{"id":"paper/player_fly","name":"Player Flight","category":"Player","color":"#2ecc71","description":"Gets or sets the flight state of a player.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."},{"name":"allowFlight","type":"boolean","description":"Enable or disable the ability to fly (SET only).","optional":true},{"name":"flying","type":"boolean","description":"Set whether the player is currently flying (SET only).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"allowFlight","type":"boolean","description":"Whether the player is allowed to fly."},{"name":"isFlying","type":"boolean","description":"Whether the player is currently flying."}],"properties":[{"key":"op","type":"string","default":"GET","label":"Operation","description":"GET or SET."}],"notes":"Setting flying to true on a player who does not have allowFlight will automatically grant it first. Players in survival/adventure mode cannot normally fly.","examples":[{"title":"Toggle flight on command","description":"Allow a player to toggle their flight mode with a command.","steps":["Command Trigger → exec → Player Flight (GET)","Player Flight → isFlying → Logic Op (NOT) → Player Flight (SET, flying input)"]}]},{"id":"paper/get_player_by_uuid","name":"Get Player by UUID","category":"Player","color":"#2ecc71","description":"Finds an online player by their UUID string.","inputs":[{"name":"uuid","type":"string","description":"UUID string of the player.","optional":true}],"outputs":[{"name":"player","type":"player","description":"The found player (null if offline or UUID invalid)."},{"name":"found","type":"boolean","description":"True if the player is currently online."}],"properties":[{"key":"uuid","type":"string","default":"","label":"UUID (fallback)"}],"notes":"Only works for currently online players. If the UUID is malformed a warning is logged and found is false. Use Player UUID to retrieve a UUID from a player object.","examples":[{"title":"Look up a stored player","description":"Retrieve a player using a UUID saved in a variable.","steps":["Get Variable (player_uuid) → uuid → Get Player by UUID","Get Player by UUID → found → Branch","true → Get Player by UUID → player → Player Message"]}]},{"id":"paper/get_online_players","name":"Get Online Players","category":"Player","color":"#2ecc71","description":"Returns a list of all currently online players.","inputs":[],"outputs":[{"name":"players","type":"list","description":"List of all online Player objects."},{"name":"count","type":"number","description":"Number of online players."}],"properties":[],"notes":"Combine with For Each to iterate over all players.","examples":[]},{"id":"paper/get_player_by_name","name":"Get Player By Name","category":"Player","color":"#2ecc71","description":"Looks up an online player by their username.","inputs":[{"name":"name","type":"string","description":"The player's name.","optional":true}],"outputs":[{"name":"player","type":"player","description":"The found player (null if offline)."},{"name":"found","type":"boolean","description":"True if the player is online."}],"properties":[{"key":"name","type":"string","default":"","label":"Player Name (fallback)"}],"notes":"Only works for online players. Use an Is Null check on the player output before using it.","examples":[]},{"id":"paper/event_get_player","name":"Event Get Player","category":"Player","color":"#2ecc71","description":"Extracts the player from a Bukkit event object.","inputs":[{"name":"event","type":"event","description":"The event object."}],"outputs":[{"name":"player","type":"player","description":"The player associated with the event."},{"name":"found","type":"boolean","description":"True if a player was found in the event."}],"properties":[],"notes":"Not all events have a player. Use the found output to guard against null players.","examples":[]},{"id":"paper/send_title","name":"Send Title","category":"Player","color":"#2ecc71","description":"Shows a title and subtitle on a player's screen.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."},{"name":"title","type":"string","description":"Main title text.","optional":true},{"name":"subtitle","type":"string","description":"Subtitle text.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after sending."}],"properties":[{"key":"title","type":"string","default":"&6Welcome!","label":"Title"},{"key":"subtitle","type":"string","default":"&7Enjoy your stay","label":"Subtitle"},{"key":"fadeIn","type":"number","default":10,"label":"Fade In (ticks)"},{"key":"stay","type":"number","default":70,"label":"Stay (ticks)"},{"key":"fadeOut","type":"number","default":20,"label":"Fade Out (ticks)"}],"notes":"Supports & color codes. 20 ticks = 1 second.","examples":[]},{"id":"paper/send_action_bar","name":"Send Action Bar","category":"Player","color":"#2ecc71","description":"Displays a message in the action bar (above the hotbar) for a player.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."},{"name":"message","type":"string","description":"Action bar text (& color codes).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after sending."}],"properties":[{"key":"message","type":"string","default":"","label":"Message"}],"notes":"Action bar messages disappear after ~3 seconds. Send repeatedly with a timer to keep them visible.","examples":[]},{"id":"paper/play_sound","name":"Play Sound","category":"Player","color":"#2ecc71","description":"Plays a sound for a specific player.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player who hears the sound."},{"name":"sound","type":"string","description":"Sound name (e.g. ENTITY_PLAYER_LEVELUP).","optional":true},{"name":"volume","type":"number","description":"Volume (0.0–1.0).","optional":true},{"name":"pitch","type":"number","description":"Pitch (0.5–2.0).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after playing."}],"properties":[{"key":"sound","type":"string","default":"ENTITY_PLAYER_LEVELUP","label":"Sound"},{"key":"volume","type":"number","default":1,"label":"Volume"},{"key":"pitch","type":"number","default":1,"label":"Pitch"}],"notes":"Use Bukkit Sound enum names (e.g. ENTITY_EXPLODE) or namespaced keys (minecraft:entity.explode).","examples":[]},{"id":"paper/console_command","name":"Console Command","category":"World / Server","color":"#2ecc71","description":"Runs a command as the server console (with full permissions).","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"command","type":"string","description":"Command without leading /."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after running."}],"properties":[{"key":"command","type":"string","default":"say Hello!","label":"Default Command"}],"notes":"Runs on the main server thread. Do not use with commands that return large amounts of output.","examples":[]},{"id":"paper/run_command_as","name":"Run Command As","category":"World / Server","color":"#2ecc71","description":"Runs a command as a specific player or command sender.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"sender","type":"sender","description":"Player or CommandSender to run the command as."},{"name":"command","type":"string","description":"Command without leading /."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after running."}],"properties":[{"key":"command","type":"string","default":"spawn","label":"Default Command"}],"notes":"The command runs with the permissions of the provided sender.","examples":[]},{"id":"paper/get_world","name":"Get World","category":"World / Server","color":"#2ecc71","description":"Retrieves a world object by name.","inputs":[{"name":"name","type":"string","description":"World name."}],"outputs":[{"name":"world","type":"world","description":"The world object."},{"name":"found","type":"boolean","description":"True if the world exists."}],"properties":[{"key":"name","type":"string","default":"world","label":"Default World Name"}],"notes":"","examples":[]},{"id":"paper/spawn_entity","name":"Spawn Entity","category":"World / Server","color":"#2ecc71","description":"Spawns an entity at a given location.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"location","type":"location","description":"Spawn location."},{"name":"entityType","type":"string","description":"Entity type name (e.g. ZOMBIE).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after spawning."},{"name":"entity","type":"entity","description":"The spawned entity."}],"properties":[{"key":"entityType","type":"string","default":"ZOMBIE","label":"Entity Type"}],"notes":"Entity type names are Bukkit EntityType enum values (e.g. ZOMBIE, CREEPER, VILLAGER).","examples":[]},{"id":"paper/get_block","name":"Get Block","category":"World / Server","color":"#2ecc71","description":"Gets the material and state of a block at a given location.","inputs":[{"name":"location","type":"location","description":"Block location."}],"outputs":[{"name":"material","type":"string","description":"Material name (e.g. STONE)."},{"name":"isAir","type":"boolean","description":"True if the block is air."}],"properties":[],"notes":"Compare the material output to the name output of a Material node to check for a specific block type.","examples":[]},{"id":"paper/set_block","name":"Set Block","category":"World / Server","color":"#2ecc71","description":"Sets the block at a location to a specific material.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"location","type":"location","description":"Block location."},{"name":"material","type":"string","description":"Material name (e.g. STONE).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after setting."}],"properties":[{"key":"material","type":"string","default":"STONE","label":"Material"}],"notes":"Connect the name output of a Material node to the material input to use a validated block material.","examples":[]},{"id":"paper/create_location","name":"Create Location","category":"World / Server","color":"#2ecc71","description":"Constructs a Location object from world name and XYZ coordinates.","inputs":[{"name":"world","type":"string","description":"World name.","optional":true},{"name":"x","type":"number","optional":true},{"name":"y","type":"number","optional":true},{"name":"z","type":"number","optional":true},{"name":"yaw","type":"number","description":"Horizontal rotation (0–360).","optional":true},{"name":"pitch","type":"number","description":"Vertical rotation (-90 to 90).","optional":true}],"outputs":[{"name":"location","type":"location","description":"The constructed location."}],"properties":[{"key":"world","type":"string","default":"world","label":"World Name"},{"key":"x","type":"number","default":0,"label":"X"},{"key":"y","type":"number","default":64,"label":"Y"},{"key":"z","type":"number","default":0,"label":"Z"},{"key":"yaw","type":"number","default":0,"label":"Yaw"},{"key":"pitch","type":"number","default":0,"label":"Pitch"}],"notes":"Connected inputs override the property defaults.","examples":[]},{"id":"paper/location_offset","name":"Location Offset","category":"World / Server","color":"#2ecc71","description":"Offsets a location by dx, dy, dz.","inputs":[{"name":"location","type":"location","description":"The base location."},{"name":"dx","type":"number","description":"X offset.","optional":true},{"name":"dy","type":"number","description":"Y offset.","optional":true},{"name":"dz","type":"number","description":"Z offset.","optional":true}],"outputs":[{"name":"location","type":"location","description":"The offset location."}],"properties":[{"key":"dx","type":"number","default":0,"label":"X Offset"},{"key":"dy","type":"number","default":0,"label":"Y Offset"},{"key":"dz","type":"number","default":0,"label":"Z Offset"}],"notes":"","examples":[]},{"id":"paper/distance","name":"Distance","category":"World / Server","color":"#2ecc71","description":"Calculates the distance between two locations.","inputs":[{"name":"locationA","type":"location","description":"First location."},{"name":"locationB","type":"location","description":"Second location."}],"outputs":[{"name":"distance","type":"number","description":"Euclidean distance."},{"name":"distanceSquared","type":"number","description":"Squared distance (cheaper to compute)."}],"properties":[],"notes":"Locations must be in the same world. Cross-world distance returns 0.","examples":[]},{"id":"paper/get_nearby_entities","name":"Get Nearby Entities","category":"World / Server","color":"#2ecc71","description":"Returns all entities within a radius of a location.","inputs":[{"name":"location","type":"location","description":"Centre location."},{"name":"radius","type":"number","description":"Search radius.","optional":true}],"outputs":[{"name":"entities","type":"list","description":"List of nearby entities."},{"name":"count","type":"number","description":"Number of entities found."}],"properties":[{"key":"radius","type":"number","default":10,"label":"Radius"},{"key":"typeFilter","type":"string","default":"","label":"Entity Type Filter (empty = all)","description":"Filter by entity type name, e.g. ZOMBIE."}],"notes":"","examples":[]},{"id":"paper/drop_material","name":"Drop Material","category":"World / Server","color":"#3498db","description":"Drops a material at a world location.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"location","type":"location","description":"Drop location."},{"name":"item","type":"item_stack","description":"ItemStack to drop (takes priority over material).","optional":true},{"name":"material","type":"string","description":"Material name to drop (used when no item is connected).","optional":true},{"name":"amount","type":"number","description":"Stack size (used when no item is connected).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after dropping."}],"properties":[{"key":"material","type":"string","default":"minecraft:diamond","label":"Material"},{"key":"amount","type":"number","default":1,"label":"Amount"}],"notes":"Connect the name output of a Material node to the material input for a validated material name.","examples":[]},{"id":"paper/explosion","name":"Explosion","category":"World / Server","color":"#2ecc71","description":"Creates an explosion at a location.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"location","type":"location","description":"Explosion centre."},{"name":"power","type":"number","description":"Explosion power.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after explosion."}],"properties":[{"key":"power","type":"number","default":4,"label":"Power (TNT = 4)"},{"key":"setFire","type":"boolean","default":false,"label":"Set Fire"},{"key":"breakBlocks","type":"boolean","default":true,"label":"Break Blocks"}],"notes":"TNT has a power of 4, creepers range from 3 (normal) to 6 (charged).","examples":[]},{"id":"paper/lightning","name":"Lightning","category":"World / Server","color":"#2ecc71","description":"Strikes lightning at a location.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"location","type":"location","description":"Strike location."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after striking."}],"properties":[{"key":"mode","type":"select","options":["STRIKE","EFFECT"],"default":"STRIKE","label":"Mode","description":"STRIKE causes damage; EFFECT is visual only."}],"notes":"","examples":[]},{"id":"paper/world_time","name":"World Time","category":"World / Server","color":"#2ecc71","description":"Gets or sets the time of a world.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"world","type":"any","description":"World object or world name string."},{"name":"time","type":"number","description":"New time in ticks (for SET).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"time","type":"number","description":"Current world time in ticks."}],"properties":[{"key":"op","type":"select","options":["GET","SET"],"default":"GET","label":"Operation"},{"key":"time","type":"number","default":6000,"label":"Time (ticks)"}],"notes":"0 = dawn, 6000 = noon, 12000 = dusk, 18000 = midnight.","examples":[]},{"id":"paper/world_weather","name":"World Weather","category":"World / Server","color":"#2ecc71","description":"Gets or sets the weather of a world.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"world","type":"any","description":"World object or world name string."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"isRaining","type":"boolean","description":"True if it is currently raining."},{"name":"isThundering","type":"boolean","description":"True if it is thundering."}],"properties":[{"key":"op","type":"select","options":["GET","SET"],"default":"GET","label":"Operation"},{"key":"rain","type":"boolean","default":false,"label":"Rain (for SET)"},{"key":"thunder","type":"boolean","default":false,"label":"Thunder (for SET)"},{"key":"duration","type":"number","default":6000,"label":"Duration in ticks (for SET)"}],"notes":"","examples":[]},{"id":"paper/vector_to_location","name":"Vector To Location","category":"World / Server","color":"#2ecc71","description":"Combines a location and vector into a new location.","inputs":[{"name":"location","type":"location","description":"Base location."},{"name":"vector","type":"vector","description":"Vector to apply."}],"outputs":[{"name":"location","type":"location","description":"Resulting location."}],"properties":[{"key":"mode","type":"select","options":["ADD","SET_DIRECTION","TO_LOCATION"],"default":"ADD","label":"Mode","description":"ADD: offset the location. SET_DIRECTION: use as facing direction. TO_LOCATION: treat vector as absolute XYZ."}],"notes":"","examples":[]},{"id":"paper/location_to_vector","name":"Location To Vector","category":"World / Server","color":"#2ecc71","description":"Extracts position and direction vectors from a location.","inputs":[{"name":"location","type":"location","description":"The location."}],"outputs":[{"name":"position","type":"vector","description":"XYZ position as a Vector."},{"name":"direction","type":"vector","description":"Unit facing direction vector (derived from yaw/pitch)."},{"name":"x","type":"number"},{"name":"y","type":"number"},{"name":"z","type":"number"}],"properties":[],"notes":"","examples":[]},{"id":"paper/entity_health","name":"Get Entity Health","category":"Entity","color":"#2ecc71","description":"Returns an entity's health, max health, and dead state.","inputs":[{"name":"entity","type":"entity","description":"The entity."}],"outputs":[{"name":"health","type":"number","description":"Current health."},{"name":"maxHealth","type":"number","description":"Max health."},{"name":"isDead","type":"boolean","description":"True if health is 0."}],"properties":[],"notes":"","examples":[]},{"id":"paper/entity_set_health","name":"Set Entity Health","category":"Entity","color":"#2ecc71","description":"Sets, kills, or damages an entity.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"entity","type":"entity","description":"The entity."},{"name":"health","type":"number","description":"Health value or damage amount.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."}],"properties":[{"key":"mode","type":"select","options":["SET","KILL","DAMAGE"],"default":"SET","label":"Mode"},{"key":"health","type":"number","default":20,"label":"Health / Damage (fallback)"}],"notes":"","examples":[]},{"id":"paper/entity_type","name":"Entity Type","category":"Entity","color":"#2ecc71","description":"Returns information about an entity's type and name.","inputs":[{"name":"entity","type":"entity","description":"The entity."}],"outputs":[{"name":"typeName","type":"string","description":"Entity type name (e.g. ZOMBIE)."},{"name":"isPlayer","type":"boolean","description":"True if the entity is a player."},{"name":"isLiving","type":"boolean","description":"True if the entity is a living entity."},{"name":"name","type":"string","description":"Custom name or default entity type name."}],"properties":[],"notes":"","examples":[]},{"id":"paper/entity_location","name":"Entity Location","category":"Entity","color":"#2ecc71","description":"Returns an entity's current location and coordinates.","inputs":[{"name":"entity","type":"entity","description":"The entity."}],"outputs":[{"name":"location","type":"location","description":"Full location object."},{"name":"x","type":"number"},{"name":"y","type":"number"},{"name":"z","type":"number"},{"name":"world","type":"string","description":"World name."}],"properties":[],"notes":"","examples":[]},{"id":"paper/entity_velocity","name":"Entity Velocity","category":"Entity","color":"#2ecc71","description":"Gets or sets an entity's velocity vector.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"entity","type":"entity","description":"The entity."},{"name":"velocity","type":"vector","description":"New velocity vector (for SET).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"velocity","type":"vector","description":"Current velocity of the entity."}],"properties":[{"key":"op","type":"select","options":["GET","SET","ADD"],"default":"GET","label":"Operation"}],"notes":"Velocity is in blocks/tick. 1 block/tick = 20 blocks/second.","examples":[]},{"id":"paper/entity_name","name":"Entity Name","category":"Entity","color":"#e74c3c","description":"Gets or sets the custom display name of an entity. Supports & colour codes.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"entity","type":"entity","description":"The entity to operate on."},{"name":"name","type":"string","description":"New custom name to set (leave disconnected to only read).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"name","type":"string","description":"Current custom name of the entity (empty if none)."}],"properties":[{"key":"name","type":"string","default":"","label":"Custom Name","description":"Name to set. Leave blank to only read."},{"key":"visible","type":"boolean","default":"true","label":"Show Name Tag","description":"Whether the name tag is always visible."}],"notes":"Supports & colour codes (e.g. &cRed Boss). Connect a name input to override the property.","examples":[{"title":"Name a spawned zombie","description":"Spawn a zombie and give it a red custom name.","steps":["Spawn Entity → entity → Entity Name","Set Custom Name to \"&cZombie King\"","Enable Show Name Tag"]}]},{"id":"paper/entity_damage","name":"Damage Entity","category":"Entity","color":"#e74c3c","description":"Deals a specified amount of damage to a living entity.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"entity","type":"entity","description":"The living entity to damage."},{"name":"amount","type":"number","description":"Damage amount.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after dealing damage."},{"name":"newHealth","type":"number","description":"Health of the entity after damage."}],"properties":[{"key":"amount","type":"number","default":"1","label":"Damage Amount","description":"How much damage to deal (half-hearts)."}],"notes":"Damage is affected by armour, enchantments, and the entity's damage modifier. The entity may die if health reaches 0.","examples":[]},{"id":"paper/entity_remove","name":"Remove Entity","category":"Entity","color":"#e74c3c","description":"Removes (despawns) an entity from the world without triggering death drops or death events.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"entity","type":"entity","description":"The entity to remove."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after removal."}],"properties":[],"notes":"Does not fire EntityDeathEvent and does not drop items. Use Damage Entity to kill an entity naturally.","examples":[]},{"id":"paper/entity_effect","name":"Apply Effect","category":"Entity","color":"#e74c3c","description":"Applies a potion effect to a living entity for a given duration.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"entity","type":"entity","description":"The living entity."},{"name":"effect","type":"string","description":"Potion effect type name (e.g. SPEED, POISON, REGENERATION).","optional":true},{"name":"duration","type":"number","description":"Duration in seconds.","optional":true},{"name":"amplifier","type":"number","description":"Amplifier level (0 = level I, 1 = level II, etc.).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after applying the effect."}],"properties":[{"key":"effect","type":"string","default":"SPEED","label":"Effect Type","description":"Bukkit PotionEffectType name."},{"key":"duration","type":"number","default":"10","label":"Duration (seconds)","description":"How long the effect lasts."},{"key":"amplifier","type":"number","default":"0","label":"Amplifier","description":"0 = Level I, 1 = Level II, etc."}],"notes":"Common effect names: SPEED, SLOWNESS, HASTE, MINING_FATIGUE, STRENGTH, INSTANT_HEALTH, INSTANT_DAMAGE, JUMP_BOOST, NAUSEA, REGENERATION, RESISTANCE, FIRE_RESISTANCE, WATER_BREATHING, INVISIBILITY, BLINDNESS, NIGHT_VISION, HUNGER, WEAKNESS, POISON, WITHER, HEALTH_BOOST, ABSORPTION, SATURATION, GLOWING, LEVITATION.","examples":[{"title":"Give player Speed II for 30s","description":"Apply Speed II to a player when they join.","steps":["Player Join Trigger → player → Apply Effect","Set Effect Type to SPEED, Duration to 30, Amplifier to 1"]}]},{"id":"paper/entity_ai","name":"Entity AI","category":"Entity","color":"#e74c3c","description":"Enables or disables the AI of a living entity. Entities with AI disabled stand still and do not attack.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"entity","type":"entity","description":"The living entity."},{"name":"enabled","type":"boolean","description":"Enable AI? Leave disconnected to only read the current state.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"hasAI","type":"boolean","description":"Whether the entity currently has AI enabled."}],"properties":[{"key":"enabled","type":"boolean","default":"true","label":"Enable AI","description":"Whether to enable the AI."}],"notes":"Useful for creating stationary display mobs or boss arenas.","examples":[]},{"id":"paper/entity_equipment","name":"Entity Equipment","category":"Entity","color":"#e74c3c","description":"Gets or sets an equipment slot on a living entity (armour, held item, etc.).","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"entity","type":"entity","description":"The living entity."},{"name":"item","type":"item_stack","description":"Item to equip (leave disconnected to only get).","optional":true},{"name":"slot","type":"string","description":"Slot name override.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"item","type":"item_stack","description":"Item currently in the slot."}],"properties":[{"key":"slot","type":"string","default":"HAND","label":"Equipment Slot","description":"HAND, OFF_HAND, HEAD, CHEST, LEGS, or FEET."}],"notes":"Use the Create Item node to build an ItemStack to equip. Both the input and output use the item_stack type for full item data (name, lore, enchantments, etc.).","examples":[{"title":"Equip zombie with iron sword","description":"Give a spawned zombie an iron sword.","steps":["Spawn Entity → entity → Entity Equipment","Create Item (IRON_SWORD) → item → Entity Equipment","Set Slot to HAND"]}]},{"id":"paper/entity_teleport","name":"Entity Teleport","category":"Entity","color":"#2ecc71","description":"Teleports any entity (including players) to a location.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"entity","type":"entity","description":"The entity to teleport. Accepts both entities and players."},{"name":"location","type":"location","description":"The destination location."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after teleporting."},{"name":"entity","type":"entity","description":"The entity that was teleported."}],"properties":[],"notes":"Works for any entity type including players. For player-specific teleportation (e.g. using Paper async teleport) use Player Teleport instead.","examples":[{"title":"Teleport a killer entity to a spawn point","description":"After an entity dies, teleport whatever killed it to a set location.","steps":["Entity Death Trigger → killer → Entity Teleport (entity)","Create Location → Entity Teleport (location)"]}]},{"id":"paper/entity_uuid","name":"Entity UUID","category":"Entity","color":"#e74c3c","description":"Gets the UUID string and type name of any entity.","inputs":[{"name":"entity","type":"entity","description":"The entity."}],"outputs":[{"name":"uuid","type":"string","description":"UUID string of the entity."},{"name":"entityType","type":"string","description":"Entity type name (e.g. ZOMBIE, CREEPER)."}],"properties":[],"notes":"Entity UUIDs persist as long as the entity exists (they reset on respawn for non-persistent entities). Works for all entity types including players.","examples":[]},{"id":"paper/entity_pdc","name":"Entity Persistent Data","category":"Entity","color":"#e74c3c","description":"Reads or writes custom persistent data stored on an entity (survives server restarts).","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"entity","type":"entity","description":"The entity to read or write data on."},{"name":"key","type":"string","description":"Data key (stored under the \"pnode\" namespace).","optional":true},{"name":"value","type":"any","description":"Value to store (SET only).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"value","type":"any","description":"Retrieved value (GET only)."},{"name":"has","type":"boolean","description":"True if the key exists."}],"properties":[{"key":"op","type":"string","default":"GET","label":"Operation","description":"GET, SET, HAS, or REMOVE."},{"key":"key","type":"string","default":"my_key","label":"Key"},{"key":"type","type":"string","default":"STRING","label":"Data Type (GET only)","description":"STRING, INTEGER, DOUBLE, or BOOLEAN."}],"notes":"Entity PDC is mutated in-place — no new entity is returned. Data persists across restarts as long as the entity exists. Keys use the \"pnode\" namespace automatically.","examples":[{"title":"Tag a custom mob","description":"Mark a spawned entity as a boss mob using PDC.","steps":["Spawn Entity → entity → Entity Persistent Data","Set op=SET, key=boss_type, value=\"dragon_boss\""]},{"title":"Check if an entity is a custom mob","description":"Read a PDC tag on entity death.","steps":["Entity Death Trigger → entity → Entity Persistent Data","Set op=HAS, key=boss_type","Entity Persistent Data → has → Branch"]}]},{"id":"paper/is_player","name":"Is Player","category":"Entity","color":"#2ecc71","description":"Checks whether an entity is a player and extracts the Player reference if so.","inputs":[{"name":"entity","type":"entity","description":"The entity to check."}],"outputs":[{"name":"isPlayer","type":"boolean","description":"True if the entity is a player."},{"name":"player","type":"player","description":"The entity cast to a Player (null if not a player)."}],"properties":[],"notes":"Use this after receiving an entity output that might be a player (e.g. the killer output of Entity Death Trigger or Player Death Trigger). Connect isPlayer to a Branch node before using the player output to avoid null errors.","examples":[{"title":"Reward player killers only","description":"Give a reward only when the killer of an entity is a player, not another mob.","steps":["Entity Death Trigger → killer → Is Player (entity)","Is Player → isPlayer → Branch","Branch (true) → Player Give Item (use Is Player → player as the player input)"]}]},{"id":"paper/event_cancel","name":"Event Cancel","category":"Events","color":"#2ecc71","description":"Cancels a Bukkit event, preventing its default action.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"event","type":"event","description":"The event to cancel."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after cancelling."}],"properties":[],"notes":"Only works on cancellable events (those that implement Cancellable). Has no effect on non-cancellable events.","examples":[]},{"id":"paper/inventory_contains","name":"Inventory Contains","category":"Inventory","color":"#2ecc71","description":"Checks whether a player's inventory has at least a specified amount of a material.","inputs":[{"name":"player","type":"player","description":"The player."},{"name":"item","type":"item_stack","description":"ItemStack to check for (takes priority over material).","optional":true},{"name":"material","type":"string","description":"Material name (used when no item is connected).","optional":true},{"name":"amount","type":"number","description":"Minimum required amount.","optional":true}],"outputs":[{"name":"contains","type":"boolean","description":"True if the player has at least the required amount."},{"name":"count","type":"number","description":"Total count of that material in the inventory."}],"properties":[{"key":"material","type":"string","default":"DIAMOND","label":"Material"},{"key":"amount","type":"number","default":1,"label":"Min Amount"}],"notes":"Connect the name output of a Material node to the material input for a validated material name. Works with any Bukkit material.","examples":[]},{"id":"paper/inventory_remove","name":"Inventory Remove","category":"Inventory","color":"#2ecc71","description":"Removes a specified amount of a material from a player's inventory.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."},{"name":"item","type":"item_stack","description":"ItemStack to remove (takes priority over material).","optional":true},{"name":"material","type":"string","description":"Material name (used when no item is connected).","optional":true},{"name":"amount","type":"number","description":"Amount to remove.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after removing."},{"name":"removed","type":"number","description":"Actual amount removed."}],"properties":[{"key":"material","type":"string","default":"DIAMOND","label":"Material"},{"key":"amount","type":"number","default":1,"label":"Amount"}],"notes":"If the player doesn't have enough items, as many as possible are removed. Connect the name output of a Material node to the material input for a validated material name.","examples":[]},{"id":"paper/inventory_clear","name":"Inventory Clear","category":"Inventory","color":"#2ecc71","description":"Clears some or all of a player's inventory.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."}],"outputs":[{"name":"exec","type":"exec","description":"Continues after clearing."}],"properties":[{"key":"mode","type":"select","options":["ALL","MAIN_HAND","OFF_HAND","ARMOR"],"default":"ALL","label":"Clear Mode"}],"notes":"","examples":[]},{"id":"paper/inventory_slot","name":"Inventory Slot","category":"Inventory","color":"#9b59b6","description":"Gets or sets the item in a specific inventory slot of a player.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player whose inventory to access."},{"name":"slot","type":"number","description":"Slot index (0–35 for main inventory; 36–39 armour; 40 off-hand).","optional":true},{"name":"item","type":"item_stack","description":"Item to place in the slot (SET only).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"item","type":"item_stack","description":"Item currently (or previously) in the slot."}],"properties":[{"key":"op","type":"string","default":"GET","label":"Operation","description":"GET or SET."},{"key":"slot","type":"number","default":0,"label":"Slot Index"}],"notes":"Slots 0–8 are the hotbar, 9–35 are the main storage, 36–39 are armour (boots→helmet), and 40 is the off-hand. Out-of-range slot indices are silently ignored.","examples":[{"title":"Clear a specific hotbar slot","description":"Remove the item in hotbar slot 0.","steps":["Set op=SET, slot=0","Do not connect an item — the slot will be set to AIR."]}]},{"id":"paper/inventory_held","name":"Held Item","category":"Inventory","color":"#9b59b6","description":"Gets or sets the item in the player's main hand.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"The player."},{"name":"item","type":"item_stack","description":"Item to place in the main hand (SET only).","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the operation."},{"name":"item","type":"item_stack","description":"Item currently (or previously) held in the main hand."}],"properties":[{"key":"op","type":"string","default":"GET","label":"Operation","description":"GET or SET."}],"notes":"The item output reflects the state before any SET operation. To check the off-hand, use Inventory Slot with slot index 40.","examples":[{"title":"Replace the held item on interact","description":"Swap a player's held item for a different one.","steps":["Player Interact Trigger → player → Held Item","Create Item (GOLDEN_SWORD) → item → Held Item (SET)"]}]},{"id":"paper/parse_placeholders","name":"Parse Placeholders","category":"PlaceholderAPI","color":"#2ecc71","description":"Processes a string through PlaceholderAPI, replacing %placeholder% tokens.","inputs":[{"name":"player","type":"player","description":"Player for context (e.g. %player_name%).","optional":true},{"name":"text","type":"string","description":"Text containing %placeholders%."}],"outputs":[{"name":"result","type":"string","description":"Fully parsed string."}],"properties":[{"key":"text","type":"string","default":"%player_name%","label":"Text"}],"notes":"Requires PlaceholderAPI to be installed. If PlaceholderAPI is not present, returns the original text unchanged.","examples":[]},{"id":"vault/balance","name":"Get Balance","category":"Vault / Economy","color":"#f39c12","description":"Returns a player's current economy balance. Requires Vault and an economy plugin.","inputs":[{"name":"player","type":"player","description":"Player to check."}],"outputs":[{"name":"balance","type":"number","description":"Current balance."}],"properties":[],"notes":"Returns 0 if Vault or an economy plugin is not installed.","examples":[]},{"id":"vault/deposit","name":"Deposit","category":"Vault / Economy","color":"#f39c12","description":"Deposits money into a player's economy account.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"Player to deposit to."},{"name":"amount","type":"number","description":"Amount to deposit.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after deposit."},{"name":"success","type":"boolean","description":"True if the deposit succeeded."}],"properties":[{"key":"amount","type":"number","default":100,"label":"Amount"}],"notes":"Requires Vault and an economy plugin.","examples":[]},{"id":"vault/withdraw","name":"Withdraw","category":"Vault / Economy","color":"#f39c12","description":"Withdraws money from a player's economy account.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"Player to withdraw from."},{"name":"amount","type":"number","description":"Amount to withdraw.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after withdrawal."},{"name":"success","type":"boolean","description":"True if the withdrawal succeeded (i.e. player had enough funds)."}],"properties":[{"key":"amount","type":"number","default":100,"label":"Amount"}],"notes":"Use the Has Money node before withdrawing to avoid overdraft.","examples":[]},{"id":"vault/has_money","name":"Has Money","category":"Vault / Economy","color":"#f39c12","description":"Checks whether a player has at least a specified amount of money.","inputs":[{"name":"player","type":"player","description":"Player to check."},{"name":"amount","type":"number","description":"Amount to check for.","optional":true}],"outputs":[{"name":"result","type":"boolean","description":"True if the player has enough."}],"properties":[{"key":"amount","type":"number","default":100,"label":"Amount"}],"notes":"","examples":[]},{"id":"vault/perm_add","name":"Add Permission","category":"Vault / Permissions","color":"#f39c12","description":"Grants a permission node to a player via Vault's permission API.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"Player to grant permission to."},{"name":"permission","type":"string","description":"Permission node to add.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after adding."}],"properties":[{"key":"permission","type":"string","default":"","label":"Permission"}],"notes":"Requires Vault and a permissions plugin (e.g. LuckPerms).","examples":[]},{"id":"vault/perm_remove","name":"Remove Permission","category":"Vault / Permissions","color":"#f39c12","description":"Revokes a permission node from a player via Vault's permission API.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"Player to revoke permission from."},{"name":"permission","type":"string","description":"Permission node to remove.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after removing."}],"properties":[{"key":"permission","type":"string","default":"","label":"Permission"}],"notes":"Requires Vault and a permissions plugin.","examples":[]},{"id":"luckperms/has_permission","name":"LP Has Permission","category":"LuckPerms","color":"#9b59b6","description":"Checks whether a player has a specific permission node using the LuckPerms API.","inputs":[{"name":"player","type":"player","description":"Player to check."},{"name":"permission","type":"string","description":"Permission node to check.","optional":true}],"outputs":[{"name":"result","type":"boolean","description":"True if the player has the permission."}],"properties":[{"key":"permission","type":"string","default":"","label":"Permission","description":"Permission node (e.g. myplugin.use)."}],"notes":"Requires LuckPerms to be installed. Falls back to Bukkit's hasPermission() if LuckPerms is unavailable.","examples":[]},{"id":"luckperms/add_permission","name":"LP Add Permission","category":"LuckPerms","color":"#9b59b6","description":"Grants a permission node to a player persistently via the LuckPerms API.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"Player to grant permission to."},{"name":"permission","type":"string","description":"Permission node to add.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after adding the permission."}],"properties":[{"key":"permission","type":"string","default":"","label":"Permission","description":"Permission node to add (e.g. myplugin.vip)."}],"notes":"Changes are saved persistently to LuckPerms storage. Requires LuckPerms.","examples":[]},{"id":"luckperms/remove_permission","name":"LP Remove Permission","category":"LuckPerms","color":"#9b59b6","description":"Revokes a permission node from a player persistently via the LuckPerms API.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"Player to revoke permission from."},{"name":"permission","type":"string","description":"Permission node to remove.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after removing the permission."}],"properties":[{"key":"permission","type":"string","default":"","label":"Permission","description":"Permission node to remove."}],"notes":"Only removes directly-set permissions. Group-inherited permissions must be managed via group membership. Requires LuckPerms.","examples":[]},{"id":"luckperms/get_group","name":"LP Get Group","category":"LuckPerms","color":"#9b59b6","description":"Returns the primary LuckPerms group name of a player.","inputs":[{"name":"player","type":"player","description":"Player to check."}],"outputs":[{"name":"group","type":"string","description":"Primary group name (e.g. \"vip\", \"admin\")."}],"properties":[],"notes":"Returns the primary group only. Use with Branch or Switch nodes to create rank-based logic.","examples":[{"title":"VIP welcome message","description":"Send a special welcome to VIP players on join.","steps":["Player Join Trigger → player → LP Get Group","Compare group == \"vip\" → Branch","True branch → Send Message with VIP welcome text"]}]},{"id":"luckperms/set_group","name":"LP Set Group","category":"LuckPerms","color":"#9b59b6","description":"Sets the primary LuckPerms group of a player and ensures they are a member of that group.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"Player to update."},{"name":"group","type":"string","description":"Group name to set as primary.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after the update."}],"properties":[{"key":"group","type":"string","default":"default","label":"Group Name","description":"The group to set as primary."}],"notes":"Also adds the player to the group if they are not already a member. Requires LuckPerms.","examples":[]},{"id":"luckperms/add_group","name":"LP Add to Group","category":"LuckPerms","color":"#9b59b6","description":"Adds a player to a LuckPerms group (adds an inheritance node).","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"Player to add to the group."},{"name":"group","type":"string","description":"Group name.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after adding."}],"properties":[{"key":"group","type":"string","default":"default","label":"Group Name","description":"The group to add the player to."}],"notes":"Does not change the player's primary group. Use LP Set Group to update the primary group. Requires LuckPerms.","examples":[]},{"id":"luckperms/remove_group","name":"LP Remove from Group","category":"LuckPerms","color":"#9b59b6","description":"Removes a player from a LuckPerms group (removes the inheritance node).","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"player","type":"player","description":"Player to remove from the group."},{"name":"group","type":"string","description":"Group name.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after removal."}],"properties":[{"key":"group","type":"string","default":"default","label":"Group Name","description":"The group to remove the player from."}],"notes":"If this was the player's primary group, their primary group may become \"default\". Requires LuckPerms.","examples":[]},{"id":"voicechat/is_connected","name":"SVC Is Connected","category":"Simple Voice Chat","color":"#1abc9c","description":"Returns true if a player has Simple Voice Chat connected and active.","inputs":[{"name":"player","type":"player","description":"Player to check."}],"outputs":[{"name":"connected","type":"boolean","description":"True if the player has an active SVC connection."}],"properties":[],"notes":"Requires Simple Voice Chat to be installed. Returns false if SVC is not present or the player has not connected their voice client.","examples":[{"title":"Require SVC for a channel","description":"Kick players from a region if they do not have SVC connected.","steps":["SVC Is Connected → connected → Branch","False branch → Player Kick with message \"Please connect Simple Voice Chat\""]}]},{"id":"voicechat/get_group","name":"SVC Get Group","category":"Simple Voice Chat","color":"#1abc9c","description":"Returns the name of the voice group a player is currently in.","inputs":[{"name":"player","type":"player","description":"Player to check."}],"outputs":[{"name":"groupName","type":"string","description":"Voice group name (empty if not in any group)."},{"name":"inGroup","type":"boolean","description":"True if the player is in a voice group."}],"properties":[],"notes":"Requires Simple Voice Chat to be installed. Returns empty string and false if SVC is not present.","examples":[]},{"id":"voicechat/is_speaking","name":"SVC Is Speaking","category":"Simple Voice Chat","color":"#1abc9c","description":"Returns true if the player spoke into Simple Voice Chat within the last 500 ms.","inputs":[{"name":"player","type":"player","description":"Player to check."}],"outputs":[{"name":"speaking","type":"boolean","description":"True if the player is currently speaking (audio above -40 dB received within the last 500 ms)."},{"name":"decibels","type":"number","description":"Last measured audio level in dB. Returns -127 if no audio has been received yet."},{"name":"volume","type":"number","description":"Last measured normalised volume from 0.0 to 1.0."}],"properties":[],"notes":"Requires Simple Voice Chat to be installed and running.\nThis is a **polling** node — it reads the most recently cached audio level. Use it inside timer loops or after other event triggers.\nFor an **event-driven** approach (fire once when speaking starts) use **SVC Speaking Trigger** instead.\nA player is considered speaking if audio above -40 dB was received within the last 500 ms.\nReturns false and -127 dB if SVC is not present or the player has never connected their voice client.","examples":[{"title":"Deny an action if a player is not speaking","description":"Require players to speak before activating a pressure plate.","steps":["Player Interact Trigger → exec → SVC Is Speaking (via Get Trigger Player)","SVC Is Speaking → speaking → Branch","false branch → Send Message \"You must be speaking to activate this!\"","true branch → <your activate logic>"]},{"title":"Display current volume in action bar","description":"Show a real-time volume meter using a timer loop.","steps":["Timer Trigger (1 s) → exec → For Each Online Player","For Each Online Player → player → SVC Is Speaking","SVC Is Speaking → volume → Number to String → Set Action Bar"]}]},{"id":"voicechat/speaking_trigger","name":"SVC Speaking Trigger","category":"Simple Voice Chat","color":"#1abc9c","description":"Fires when a player speaks into Simple Voice Chat. Debounced to at most once every 250 ms per player so graphs are not flooded with audio packets.","inputs":[],"outputs":[{"name":"exec","type":"exec","description":"Execution flow out."},{"name":"player","type":"player","description":"The player who is speaking."},{"name":"decibels","type":"number","description":"Audio level in dB. Range: -127 (silence) to 0 (maximum)."},{"name":"volume","type":"number","description":"Normalised volume from 0.0 (silence) to 1.0 (maximum)."}],"properties":[],"notes":"Requires Simple Voice Chat to be installed and running.\nOnly fires when the audio level exceeds -40 dB — background noise / silence is ignored.\nThe trigger fires at most once every 250 ms per player (debounced). For a polled check use **SVC Is Speaking** instead.\nUse the `decibels` or `volume` outputs to drive volume-dependent logic such as range scaling.","examples":[{"title":"Play a sound when a player starts talking","description":"Trigger a visual or audio cue whenever someone starts speaking.","steps":["SVC Speaking Trigger → exec → Play Sound At Player","SVC Speaking Trigger → player → Play Sound At Player (player input)"]},{"title":"Volume-based range check","description":"Combine with SVC Voice Range to react only when someone speaks loudly enough to be heard from a distance.","steps":["SVC Speaking Trigger → decibels → SVC Voice Range (decibels)","SVC Voice Range → effectiveRange → Compare Number (≥ threshold)","Compare Number → true branch → <your logic>"]}]},{"id":"voicechat/detection_chance","name":"SVC Detection Chance","category":"Simple Voice Chat","color":"#1abc9c","description":"Calculates the probability (0.0 – 1.0) that a voice is audible at a given distance, with configurable min/max range and a falloff curve.","inputs":[{"name":"distance","type":"number","description":"Distance in blocks between the listener and the speaker."},{"name":"minRange","type":"number","description":"Distance within which detection is guaranteed (100 %)."},{"name":"maxRange","type":"number","description":"Distance beyond which detection is impossible (0 %)."}],"outputs":[{"name":"detectionChance","type":"number","description":"Probability from 0.0 (cannot hear) to 1.0 (guaranteed)."},{"name":"canHear","type":"boolean","description":"True if detectionChance is greater than 0."}],"properties":[{"key":"falloffCurve","type":"number","default":1,"label":"Falloff Curve (0.5 – 2.0)","description":"Controls how quickly detection chance falls off between minRange and maxRange."}],"notes":"Formula: chance = (1 − normalised_distance) ^ falloffCurve, where normalised_distance = (distance − minRange) / (maxRange − minRange)\n\nFalloff curve guide (chance at the midpoint between minRange and maxRange):\n  • 0.5 → sharp drop-off (~29 % at midpoint)\n  • 1.0 → linear drop-off (50 % at midpoint)  ← default\n  • 1.5 → gradual drop-off (~65 % at midpoint)\n  • 2.0 → very gradual drop-off (~75 % at midpoint)\n\nTip: use **SVC Voice Range** to compute a volume-scaled maxRange and feed it here for dynamic detection.","examples":[{"title":"Probabilistic mob detection","description":"Give mobs a realistic chance of detecting a nearby speaking player based on distance.","steps":["SVC Speaking Trigger → player → Get Player Location","Get Player Location + Mob Location → Distance Between Locations → SVC Detection Chance (distance)","Constant (5) → SVC Detection Chance (minRange)","Constant (30) → SVC Detection Chance (maxRange)","SVC Detection Chance → detectionChance → Random Number Check (0–1)","Random Number Check → pass branch → Trigger mob alert"]},{"title":"Combine with volume-scaled range","description":"Louder voices are detectable from further away.","steps":["SVC Speaking Trigger → decibels → SVC Voice Range (decibels)","Constant (48) → SVC Voice Range (baseRange)","SVC Voice Range → effectiveRange → SVC Detection Chance (maxRange)","Constant (5) → SVC Detection Chance (minRange)","Distance Between Locations → SVC Detection Chance (distance)","SVC Detection Chance → detectionChance → <use as probability>"]}]},{"id":"voicechat/voice_range","name":"SVC Voice Range","category":"Simple Voice Chat","color":"#1abc9c","description":"Calculates the effective voice hearing range in blocks based on the current audio level. Louder voices carry further.","inputs":[{"name":"decibels","type":"number","description":"Audio level in dB. Connect from SVC Is Speaking or SVC Speaking Trigger."},{"name":"baseRange","type":"number","description":"Base voice range in blocks (e.g. the value configured in the SVC server settings, typically 30–48)."}],"outputs":[{"name":"effectiveRange","type":"number","description":"Effective hearing range in blocks after volume scaling."}],"properties":[{"key":"threshold","type":"number","default":-40,"label":"Volume Threshold (dB)","description":"Audio at or below this level is treated as the baseline (1× range). Default: -40 dB."}],"notes":"Formula: multiplier = clamp(1.0 + (dB − threshold) / 25, 0.5, 2.5)\nExamples with base range 30 blocks and threshold -40 dB:\n  • -40 dB (at threshold) → 30 blocks (1.0×)\n  • -15 dB (+25 dB) → 60 blocks (2.0×)\n  •   0 dB (maximum) → 75 blocks (2.5×)\n  • -65 dB (very quiet) → 15 blocks (0.5× minimum)\nPair with **SVC Detection Chance** to compute a probability from the effective range.","examples":[{"title":"Alert mobs in effective range","description":"When a player speaks, alert nearby mobs scaled to how loud they were.","steps":["SVC Speaking Trigger → decibels → SVC Voice Range (decibels)","Constant (30) → SVC Voice Range (baseRange)","SVC Voice Range → effectiveRange → Get Nearby Entities (radius)","Get Nearby Entities → entities → For Each Entity → <trigger aggro>"]}]},{"id":"custom/code","name":"Custom Code","category":"Custom","color":"#2c3e50","description":"Executes user-written Groovy code. Provides up to 4 typed inputs (in0–in3) and 4 outputs (out0–out3), plus bindings for the Bukkit server, logger, plugin, and execution context.","inputs":[{"name":"exec","type":"exec","description":"Incoming execution."},{"name":"in0","type":"any","description":"Input 0 — accessible as in0 in the script.","optional":true},{"name":"in1","type":"any","description":"Input 1 — accessible as in1 in the script.","optional":true},{"name":"in2","type":"any","description":"Input 2 — accessible as in2 in the script.","optional":true},{"name":"in3","type":"any","description":"Input 3 — accessible as in3 in the script.","optional":true}],"outputs":[{"name":"exec","type":"exec","description":"Continues after execution."},{"name":"out0","type":"any","description":"Output 0 — set as out0 in the script."},{"name":"out1","type":"any","description":"Output 1 — set as out1 in the script."},{"name":"out2","type":"any","description":"Output 2 — set as out2 in the script."},{"name":"out3","type":"any","description":"Output 3 — set as out3 in the script."}],"properties":[{"key":"code","type":"textarea","default":"// Inputs: in0, in1, in2, in3\n// Set outputs: out0 = ...\n// Bindings: server, logger, ctx, plugin\n\nout0 = in0","label":"Groovy Code"},{"key":"async","type":"boolean","default":false,"label":"Run Asynchronously","description":"Run off the main thread. Outputs are not forwarded in async mode."}],"notes":"The script has access to the full Apache Groovy runtime and can call any Bukkit/Paper API. When async is enabled, the graph continues immediately without waiting for the script to finish and outputs are not emitted.","groovyBindings":[{"name":"in0–in3","type":"Object","description":"Resolved input values."},{"name":"out0–out3","type":"Object","description":"Must be set by the script to pass data to output ports."},{"name":"server","type":"org.bukkit.Server","description":"The Bukkit server instance."},{"name":"logger","type":"java.util.logging.Logger","description":"The PNode plugin logger."},{"name":"ctx","type":"dev.pnode.node.ExecutionContext","description":"The current graph execution context."},{"name":"plugin","type":"dev.pnode.PNodePlugin","description":"The PNode plugin instance."}],"examples":[{"title":"Hello World","description":"Set out0 to a greeting.","code":"out0 = \"Hello, \" + in0 + \"!\""},{"title":"Get player UUID","description":"Get the UUID of a player passed as in0.","code":"out0 = in0?.getUniqueId()?.toString()"},{"title":"Format balance","description":"Format a number as a currency string.","code":"out0 = String.format(\"$%,.2f\", (double) in0)"},{"title":"List all online player names","description":"Collect all online player names into a list.","code":"out0 = server.onlinePlayers.collect { it.name }"},{"title":"Check time of day","description":"Return whether it is daytime in a world.","code":"def world = server.getWorld(\"world\")\ndef time = world?.time ?: 0\nout0 = (time >= 0 && time < 12000) ? \"day\" : \"night\""},{"title":"Send title with custom colours","description":"Build and send a title using Adventure API.","code":"import net.kyori.adventure.text.Component\nimport net.kyori.adventure.text.format.NamedTextColor\n\ndef player = in0\ndef title = Component.text(\"Welcome!\").color(NamedTextColor.GOLD)\ndef sub   = Component.text(\"Enjoy your stay\").color(NamedTextColor.GRAY)\nplayer?.showTitle(\n  net.kyori.adventure.title.Title.title(title, sub)\n)"},{"title":"Simple HTTP request (async)","description":"Fetch data from an API asynchronously (enable async mode).","code":"import groovy.json.JsonSlurper\n\ndef url = new URL(\"https://api.example.com/data\")\ndef response = new JsonSlurper().parse(url)\nlogger.info(\"Got response: ${response}\")"},{"title":"Math and conditions","description":"Compute a tax amount and decide a category.","code":"def income = (double) in0\ndef tax = income > 1000 ? income * 0.2 : income * 0.1\nout0 = tax\nout1 = tax > 200 ? \"high\" : \"low\""}]},{"id":"misc/note","name":"Note","category":"Misc","color":"#f1c40f","description":"A comment/annotation node. Has no effect on execution — purely for documentation within the graph canvas.","inputs":[],"outputs":[],"properties":[{"key":"text","type":"textarea","default":"","label":"Note Text"}],"notes":"Use notes to explain complex sections of your graph, leave TODO comments, or mark areas that need attention.","examples":[]}]}