Origins: Powerful Powers
» Global storePage 12 of 17

Global store

The global store holds values shared by any number of entities: a faction's score, a world-puzzle flag, a bond between two players. Variables and lists give each holder its own copy.

  • Addressed by a key like mypack:bond/alice. A key without a namespace gets origins-powerful-powers:, so "score" is origins-powerful-powers:score. Keys use lowercase letters, digits and _ - . /.
  • Typed like variables: int, long, float, double, boolean or String, or a list of one of those. A key's type is fixed when it's created, and later writes follow Java's assignment rules.
  • Saved with the world (data/origins-powerful-powers_global.dat), like scoreboards. It's shared across dimensions and never resets itself. Put the dimension or the day in the key when you need that.
  • Server only. A client-checked condition such as a hud_render condition counts globals as false and logs an error.

Ways in:

WayUse it for
Global.* in codeany key, including keys built while the code runs
global_variables powerfixed, declared fields that every holder uses by plain name
modify_global and delete_global actionsJSON, like modify_variable
/opp globallooking at and fixing the store as an operator

In code

Global works everywhere code runs: execute, expression, modify_variable values, for_each, and ${…} in with_variables and /opp with.

MethodReturns
Global.has(key)booleanwhether the key exists
Global.get(key)the valuean error if the key is missing or is a list
Global.set(key, value)the valuecreates the key with the value's type, or sets an existing one
Global.delete(key)booleanremoves the key. true if it existed
Global.bind(key, self) / Global.bind(key, other)ties the key to an entity. See cleanup
Global.lock(key, owner) / Global.unlock(key)see locking
Global.list(key)a listan existing global list, used with list methods: Global.list(key).size()
Global.list(key, type)a listthe same, and creates an empty list of type ("int", "String", …) if it's missing
  • set, delete, bind, lock, unlock, list(key, type) and list methods that change a list only work in actions (execute, for_each).
  • Keys are Strings, so they can be built from variables: Global.set("mypack:kills/" + team, Global.get("mypack:kills/" + team) + 1).
  • Global is a reserved name.
  • Global lists hold at most 1024 elements. Adding past that is an error.

Example: count every zombie kill on the server.

json
{
  "type": "origins:self_action_on_kill",
  "target_condition": {
    "type": "origins:entity_type",
    "entity_type": "minecraft:zombie"
  },
  "entity_action": {
    "type": "origins-powerful-powers:execute",
    "code": "Global.set(\"mypack:zombie_kills\", Global.has(\"mypack:zombie_kills\") ? Global.get(\"mypack:zombie_kills\") + 1 : 1);"
  },
  "cooldown": 1
}

Loops: for_each and for_each_read take a global list as their list:

json
{
  "type": "origins-powerful-powers:for_each_read",
  "list": "Global.list(\"mypack:members\")",
  "action": {
    "type": "origins:heal",
    "amount": 1
  }
}

Global variables

origins-powerful-powers:global_variablespower type

Declares fields like variables, with one copy in the global store shared by every holder. Code on a holder uses them by plain name.

FieldTypeDefaultDescription
fieldsString or array of StringsrequiredJava field declarations: int faction_score = 0; boolean gate_open;
lockBooleanfalseWhen true, keys this power creates are locked to its namespace.
  • The key for field name in power mypack:whatever is mypack:name, in lowercase. Any power in the mypack namespace declaring the same name shares it. Global.get("mypack:name") reads it from anywhere.
  • The initial value is only used to create the key.
  • If the key already exists with another type, using the field is an error.
  • A name must be unique across the variables and global_variables powers an entity holds.
  • variable_bar and client-side checks can't read global fields.

Example: a shared faction score. Every member has this power, and a member's kill adds to everyone's total.

json
{
  "type": "origins-powerful-powers:global_variables",
  "fields": "int faction_score = 0;"
}
json
{
  "type": "origins:self_action_on_kill",
  "entity_action": {
    "type": "origins-powerful-powers:execute",
    "code": "faction_score += 1;"
  },
  "cooldown": 1
}

Modify global

origins-powerful-powers:modify_globalentity action and bi-entity action

The JSON form of changing one global, like modify_variable.

FieldTypeDefaultDescription
keyStringrequiredThe key.
operationString"set"set, add, subtract, multiply, divide, modulo, min, max, and, or, xor, shift_left, shift_right, unsigned_shift_right
valueStringrequiredAn expression, like "1" or "coins / 10". It can read variables and globals.
bindString"none"After the change, bind the key to self, other (bi-entity only), or both.
  • set creates a missing key. Any other operation needs the key to exist already.

Delete global

origins-powerful-powers:delete_globalentity action and bi-entity action

FieldTypeDefaultDescription
keyStringrequiredThe key to remove. A missing key does nothing.

Example: turn on a world flag the first time anyone enters the Nether.

json
{
  "type": "origins:action_over_time",
  "interval": 20,
  "condition": {
    "type": "origins:dimension",
    "dimension": "minecraft:the_nether"
  },
  "entity_action": {
    "type": "origins-powerful-powers:modify_global",
    "key": "mypack:nether_opened",
    "value": "true"
  }
}

Locking

By default any pack can change any key. Locking keeps several packs, or several copies of one origin, on the same server from changing each other's keys.

  • A locked key has an owner: a namespace (mypack) or a single power id (mypack:bond).
  • Only an entity that holds a power in that namespace, or that exact power, can set, delete, bind, change list contents, lock or unlock the key. Anything else gets an error naming the owner.
  • Anyone can read a locked key.
  • Lock with Global.lock(key, owner). The entity doing it must hold the owner. global_variables with "lock": true locks the keys it creates to its namespace.
  • /opp global commands ignore locks.

Cleanup

Globals stay until something deletes them:

  • Explicit delete: Global.delete, delete_global, or /opp global delete.
  • Binding. Global.bind(key, self) (or bind on modify_global) ties the key to an entity. A key can be bound to several entities, and it's deleted once all of them are gone:

    • a non-player is gone when it's killed or removed. Chunk unloading keeps it.
    • a player is gone after being offline longer than the gamerule oppPlayerExpiryDays (real days, default 30, 0 = never). Death keeps them.
  • Admin pruning: /opp global prune, run by an operator.

Example: a bond between two players that disappears once both have been away for good. See the cookbook.


/opp global

mcfunction
opp global get <key>
opp global set <key> <value>
opp global delete <key>
opp global list [<prefix>]
opp global prune <prefix>
opp global prune --older-than <ticks>
opp global lock <key> <owner>
opp global unlock <key>
SubcommandWhat it doesResult
getprints the valuethe value if it's a whole number, 1/0 for booleans, the size for a list, and 1 for anything else
setsets or creates a key. The value is a Java literal: 5, 2.5, 10L, true, "text"the new value if it's a number, and 1 for anything else
deleteremoves a key1
listevery key, or those starting with <prefix>, with type, value, how long since it was written, its lock owner and how many entities it's bound tothe number listed
prune <prefix>deletes every key starting with <prefix>how many were deleted
prune --older-than <ticks>deletes every key last written at least that many ticks agohow many were deleted
lock / unlocklocks a key to an owner, or removes the lock1
  • Commands need permission level 2 and ignore locks.
  • A key or prefix without a namespace gets origins-powerful-powers:.