Skip to content

Network Variables

Ahmad Saleem edited this page Sep 5, 2026 · 7 revisions

A network variable is a normal Skript variable with a ? in front of the name.

set {?coins::%player%} to 100

That value now exists on every server. Any server can read it or change it.

Variables without the ? stay on the server they were written on.

set {coins::%player%} to 100   # only this server
set {?coins::%player%} to 100  # the whole network

Reading is free

Your server answers reads from its own copy in memory. Nothing goes over the network.

send "You have %{?coins::%player%}% coins"

It's as fast as a normal variable. Use it in a loop, in on damage, anywhere.

Writing goes to the proxy

Your server sends the change to the proxy. The proxy stores it and tells every other server.

set {?rank::%player%} to "vip"

Every write is one message. A script that writes every tick for every player will slow the whole network down.

What you can store

skNetwork uses Skript's own serialiser. If Skript can save it to variables.csv, it can travel the network.

set {?name::1} to "eult"               # text
set {?score::1} to 42                  # whole number
set {?rate::1} to 1.5                  # decimal
set {?vip::1} to true                  # true or false
set {?seen::1} to now                  # date
set {?kit::1} to diamond sword         # item
set {?home::1} to location of player   # location

Lists of any of these work too.

Two things can go wrong. The receiving server has to understand the type, so a value written by a plugin only one server has is unreadable everywhere else. And a few types don't survive being serialised at all. Test anything unusual before you rely on it.

When a server can't read a value, it logs a warning and that one variable is missing there. Every other server is fine. See Limitations.

Checking if something is set

if {?coins::%player%} is not set:
	send "No account yet."

Careful at startup. Before the first sync your copy is empty, so this says yes for everyone. Read Sync and events first.

A default value is usually simpler:

send "You have %{?coins::%player%} ? 0% coins"

Lists

Lists work how you'd expect.

add "alpha" to {?team::red::*}
add "bravo" to {?team::red::*}

send "%size of {?team::red::*}% players"

loop {?team::red::*}:
	send "- %loop-value%"

remove "bravo" from {?team::red::*}

Skript stores each entry under its own name, so each add is one normal write.

Deleting a list

delete {?team::red::*}

This removes every entry under team::red and nothing else, not even names that start the same way:

set {?team::redstone} to "safe"
delete {?team::red::*}
# {?team::redstone} is still there

Deleting a big list is the slowest thing you can ask the proxy to do, because it has to check every variable it holds. Don't do it to huge lists while players are online.

You can't set a list name

set {?team::red::*} to "x"   # refused

A name ending in ::* can only be deleted. Add entries one by one instead.

Deleting a single variable

delete {?coins::%player%}

The variable disappears everywhere.

Naming

Use :: to group related values, same as normal Skript.

{?eco::bal::%player%}
{?eco::joins::%player%}
{?online::lobby::*}

Groups help with /sknetproxy dump on the proxy, because you can look up a whole group at once:

/sknetproxy dump eco::bal::*

Names are not case sensitive. {?Coins::Notch} and {?coins::notch} are the same variable, and both show up as coins::notch in /sknetproxy dump.

%player% is the player's UUID

Skript's use player UUIDs in variable names is on by default, and network variables follow it exactly like normal ones. %player% inside a name becomes the player's UUID, so {?coins::%player%} is stored as coins::e5240337-a4a2-39dd-8ed9-e5ce729a8522.

set {?coins::%player%} to 100

send "%{?coins::%uuid of player%}%"   # 100, it's the same variable
send "%{?coins::%name of player%}%"   # not set, the name isn't the key

That holds on every path: plain writes, atomically ..., deletes, the change event, and what the proxy stores and shows in /sknetproxy dump. %player% and %uuid of player% are interchangeable, so pick one and stay with it.

Two things follow from the key being a UUID. /sknetproxy dump coins::* lists UUIDs, not names, so looking a player up means knowing their UUID. And if you ever turn that Skript setting off, old variables keep their old names: Skript doesn't rename them, and neither does skNetwork.

Whichever way you set it, set it the same on every server. A backend that disagrees writes to different names than the rest of the network and silently stops sharing per-player values. See Setup.

Changing the prefix

? is the default. Change it in plugins/skNetwork/config.yml:

prefix: "$"

You also have to change the pattern in plugins/Skript/config.sk to match. skNetwork does that for you when force-skript-config is on. See Configuration.

You can't use #. It starts a comment in Skript's config file.

The prefix is stripped before a name is sent to the proxy, so two servers using different prefixes still share the same data.

When two servers write at the same time

# WRONG on a network
if {?coins::%player%} >= 100:
	remove 100 from {?coins::%player%}

If two servers run this at the same moment, both read the old number and both subtract. One subtraction is lost and the balance can go below zero.

Use Atomic changes for anything you count:

atomically remove 100 from {?coins::%player%} without going below 0 and wait
if the atomic change succeeded:
	give player a diamond

Reacting to a change

Every server can run something the moment a variable changes, whichever server changed it:

on network variable change of "coins::*":
	send "%the changed variable% is now %the new value%" to console

See Sync and events.

See also

Clone this wiki locally