Variables and Globals - jojodmo/CustomItems GitHub Wiki

Variables allow you to store information, like a number or text, on items. Variables are unique to each item, so a player could have several of the same CustomItems, each with different variables with different values!

[Globals] allow you to store information globally for the entire server. You can use placeholders like {player.uuid} in the name of global variables to make them only affect certain players, or {player.location.world} to make them only affect certain worlds.

Not sure whether you should use variables or globals? Read Should I use Variables or Globals below.

As of right now, most of what you do with variables and globals is done within triggers and actions. You can store any number (including decimals) in globals and variables, as well as "strings of text"

handlers:
  rightClick:
    actions:
      -
        action: addToGlobal
        name: "myGlobalVariable"
        amount: 10.2
      -
        action: setGlobal
        name: "myPerPlayerGlobal_{player.uuid}"
        value: -3827.11
      -
        action: setVariable
        name: "myCustomVariableDoubled"
        value: "{{variable.myCustomVariable} * 2}"
      -
        action: setVariable
        name: "lastUUIDUsed"
        value: "{player.uuid}"

Should I use Variables or Globals?

Store values on items

Use normal variables

Use this if you want to make something like an item that "stores" certain things that can later be retrieved (like a stick that stores diamond blocks when right-clicked, and places them when left-clicked).

BE CAREFUL: variables apply to ALL ITEMS in a stack. So, a player could take a single action with a stack of 64 items, and it would be as if they had taken that same action on 64 individual items.

If a player drops an item with certain variables on it, and another player picks up the item, that item will still have the same variables on it!

ifVariable:
  "myVariable": ">= 0"
action: setVariable
variable: "myVariableName"
value: "{variable.myVariableName * 2}"

Store values on players

Use global variables with {player.uuid} somewhere in the name

ifGlobal:
  "myPlayerVariable_{player.uuid}": ">= 0"
action: setGlobal
name: "myPlayerVariable_{player.uuid}"
value: "{2 * {global.myPlayerVariable_{player.uuid}}}"

Because each player has a different UUID, the global will be named something different for each player, and each player will get their own individual global!

Store values per world

Use global variables with {player.location.world} somewhere in the name

ifGlobal:
  "myWorldVariable_{player.location.world}": ">= 0"
action: setGlobal
name: "myWorldVariable_{player.location.world}"
value: "{2 + {global.myWorldVariable_{player.location.world}}}"

Store values globally

Use a unique global variable name

ifGlobal:
  "myGlobalValue": ">= 0"
action: setGlobal
name: "myGlobalValue"
value: "{global.myGlobalValue + 2}"

Combinations

You can add as many placeholders as you want in global variable names! So, for example, if you wanted to store something on each player for the number of times they did something with a certain target mod type in a certain world, you should use {player.uuid}, {target.type}, and {player.location.world} in the name of the variable.

For example, to store the number of times a certain player slays a certain type of mob in a certain world

handlers:
  slayMob:
    actions:
      -
        action: addToGlobal
        name: "{target.type}_slays_by_{player.uuid}_in_{player.location.world}"
        value: 1
      -
        action: sendMessage
        message: "You've slayed a total of {global.{target.type}_slays_by_{player.uuid}_in_{player.location.world}} mobs of the type {target.type} in the world {player.location.world}. Good job!"

Formatting names

Variables and globals should only contain letters, numbers, dashes and underscores. For example, "myVariable_number-1" is a valid variable name, but "my first variable.name" is not valid! Invalid variable and global names will simply be ignored

Modifying variables and globals

To set a variable on an item, you can use the setVariable action, and to set a global, use setGlobal:

# set myVariableName to whatever `value` is
action: setVariable # use "setGlobal" to set a global rather than per-item variable
name: "myVariableOrGlobalName"

# You can use placeholders like {player.location.x}, {variable.anotherVariable}, or {global.anotherGlobal} here
value: [some value — either a number or "text"]

You can also use the actions addToVariable and subtractFromVariable to add or subtract a certain amount from a number variable (and similarly, addToGlobal and subtractFromGlobal for globals). This will only work if the variable/global is a number:

# add 10 to the variable myNumberVariable
action: addToVariable # use addToGlobal to add to a global
name: "myNumberVariableOrGlobal"
amount: 10

Lastly, you can use the action deleteVariable to delete a variable, and deleteGlobal to delete a global

action: deleteVariable # you can also use deleteGlobal
name: "aVariableOrGlobalIDontWant"

Placeholders

You can use {placeholders} for variables and globals, too! Just use {variable.myVariableName}. For a global, the placeholder is {global.myGlobalName}

{{variable.test} round 0} gets rid of any decimal point

Checking the value of a variable or global

You can check the value of a variable using the ifVariables condition, and globals using ifGlobals. You can use {placeholders} and operations like <= and > here, too!

ifVariables:
  # if myFirstVariable is 10, and...
  "myFirstVariable": "= 10"

  # if mySecondVariable is less than 15, and...
  "mySecondVariable": "< 15"

  # if myThirdVariable is greater than the player's current health, and...
  "myThirdVariable": "> {player.health}"

  # if myFourthVariable is less than or equal to myFirstVariable, and...
  "myFourthVariable": "<= {variable.myFirstVariable}"

  # if myLastVariable is greater than myThirdVariable + myFourthVariable
  "myLastVariable": "> {{variable.myThirdVariable} + {variable.myFourthVariable}}"

ifGlobals:
  # if the global "myFirstGlobal" is greater than 20
  "myFirstGlobal": "> 20"

action: sendMessage
message: "This message will only be sent if all of my variable conditions were met!"
elseActions:
  -
    action: sendMessage
    message: "One or more of my variable or global conditions wasn't met!"

Variables vs Globals

This example illustrates the difference between variables and globals. If you're having trouble, try using these handlers on an item and playing around!

handlers:
  rightClick:
    actions:
      -
        action: addToGlobal
        name: "totalNumberOfRightClicksOnServer"
        value: 1
     -
        action: addToGlobal
        name: "totalNumberOfRightClicksIn_{player.location.world}"
        value: 1
      -
        action: addToGlobal
        name: "totalNumberOfRightClicksBy_{player.uuid}"
        value: 1
      -
        action: addToGlobal
        name: "totalNumberOfRightClicksBy_{player.uuid}_in_{player.location.world}"
        value: 1
      -
        action: addToVariable
        name: "numberOfRightClicksWithThisItem"
        variable: 1
      -
        action: sendMessage
        messages:
          - "Total Server Right Clicks: {global.totalNumberOfRightClicksOnServer}"
          - "Total Right Clicks in {player.location.world}: {totalNumberOfRightClicksIn_{player.location.world}}"
          - "Total Right Clicks by {player.uuid}: {global.totalNumberOfRightClicksBy_{player.uuid}}"
          - "Total Right Clicks by {player.uuid} in {player.location.world}: {global.totalNumberOfRightClicksBy_{player.uuid}_in_{player.location.world}}"
          - "Number of Right-Clicks on this item {variable.numberOfRightClicksWithThisItem}"

Per-player globals

You can use {placeholders} in the names of global variables!

Example

Here's an example of a variable that allows a player to "store" a diamond blocks by right-clicking them, and then allows the player to "place" the diamond block by hitting a dirt block.

In this example, every time a player hits a diamond block, it gets removed and the stick's variable "diamondBlocks" goes up by one. Then, when they hit a dirt block, if "diamondBlocks" is greater than zero, the dirt block turns into a diamondBlock. Otherwise, they get a message.

Lastly, the item also uses global variables to count the total number of times each player has used the diamondBlockStoringStick — the global variable "diamondBlockStoringStickTotalUses_{player.uuid}" goes up every time a player right-clicks a diamond block (but it never goes down)

# in items/diamondBlockStoringStick.yml

name: "diamondBlockStoringStick"
item:
  material: "minecraft:DIAMOND_HOE"
  displayName: "&bDiamond Block Storing Stick"
  lore:
    - "Right-click a diamond block to store it"
    - "Hit a dirt block to place it"

handlers:
  # When the player right-clicks a block with this item, run these actions
  rightClickBlock:
    actions:
      -
        # if the block is a diamond block...
        ifBlockType: "minecraft:DIAMOND_BLOCK"
        action: runActions

        # run these actions
        actions:
          -
            # add one to the variable "diamondBlocks"
            action: addToVariable
            variable: "diamondBlocks"
            amount: 1
          -
            # add one to the global "diamondBlockStoringStickTotalUses" for the player
            # because we want to store a different number for each player, we'll need to
            # use the {player.uuid} placeholder in the variable name
            action: addToVariable
            variable: "diamondBlockStoringStickTotalUses_{player.uuid}"
            amount: 1
          -
            # set the clicked block to air
            action: setBlockType
            type: "minecraft:AIR"
          -
            # send the player a message telling them how many diamond blocks they have stored
            action: sendMessage
            message: "&aYou stored a diamond block!&b You now have&l {variable.diamondBlocks} &bdiamond blocks stored! Hit a dirt block to place it."

  # when the player left-clicks (hits) a block with this item, run these actions
  leftClickBlock:
    actions:
      -
        # if the block hit was dirt...
        ifBlockType: "minecraft:DIRT"
        action: runActions

        # run these actions
        actions:
          -
            # if the value of the "diamondBlocks" is greater than zero...
            ifVariable:
              "diamondBlocks": "> 0"
            action: runActions

            # run these actions. Otherwise, run "elseActions below"
            actions:
              -
                # subtract one from the variable "diamondBlocks"
                action: subtractFromVariable
                variable: "diamondBlocks"
                amount: 1
              -
                # set the hit block to a diamond block
                action: setBlockType
                type: "minecraft:DIAMOND_BLOCK"
              -
                # send the player a message telling them how many diamond blocks they now have stored
                action: sendMessage
                message: "&cYou placed a diamond block! &bYou now have&l {variable.diamondBlocks} &bdiamond blocks stored!"

            # Otherwise (else), if the variable diamondBlocks is NOT greater than zero, run these actions
            elseActions:
              -
                # send the player a message!
                action: sendMessage
                message: "&eYou don't have any diamond blocks stored! &bright-click a diamond block with this stick to store it!"
  
  # when the player right clicks air, tell them how many times they've used the diamond block storing stick in total
  rightClickAir:
    actions:
      -
        action: sendMessage
        message: "You've used the diamond block storing stick a total of {global.diamondBlockStoringStickTotalUses_{player.uuid}} times"            
⚠️ **GitHub.com Fallback** ⚠️