-
Notifications
You must be signed in to change notification settings - Fork 0
Sync and Events
A server doesn't have the network data the moment it starts. It has to connect to the proxy and receive everything first. That gap is short, but scripts that ignore it break in ways that are hard to find later.
This page covers the startup rule, the three events, and network server name.
When a server starts, its copy of the network variables is empty.
Empty isn't the same as "the network has nothing". During that gap this says yes even for players who already have data:
if {?coins::%player%} is not set:
set {?coins::%player%} to 500 # about to wipe a real balanceSo skNetwork refuses every write until the first sync finishes. Refused writes are counted and logged:
refused a write to {?coins::abc}: not synced with the proxy (SYNCING).
3 write(s) dropped so far. Guard writes with 'network is synced'
Reads still work. They just answer from an empty copy.

if network is synced:
# safe to read and writeif network is not synced:
# still starting upGuard anything that runs early:
on join:
if network is not synced:
kick player due to "The network is still starting. Try again in a moment."
stop
atomically set {?coins::%player%} to 500 if it is not setIt also tells you whether the proxy is reachable right now:
command /netstatus:
trigger:
if network is synced:
send "Network is up."
else:
send "Network is down. Balances are read only."Fires once the copy is filled in and writes are accepted.
on network sync:
send "Network ready on %network server name%" to consoleIt fires again after every reconnect, not only at startup. That makes it the right place to rebuild anything this server owns.
The usual case is a cross-server player list. A server that crashes never runs
on quit, so its players would stay in the list forever. Clearing and rebuilding on
every sync fixes that:
on network sync:
delete {?online::%network server name%::*}
loop all players:
add loop-player's name to {?online::%network server name%::*}A crash now only leaves stale names until that server comes back.
Fires when the server loses the proxy.
on network disconnect:
broadcast "&cLost the network. Money is read only for now."Reads keep working from the copy the server already holds. Writes are refused until it reconnects.
Reconnecting is automatic. The wait starts at 1 second and doubles up to 30 seconds.

A proxy that goes quiet without closing the connection is noticed after six unanswered pings, half a minute. The server drops the connection itself and the next sync pulls everything, in case writes sent into the silence never arrived.
Both events were checked by running /sknet reconnect on a live server:
EVENT: network disconnect fired on lobby
EVENT: network sync fired on lobby
They arrived one second apart.
Fires on every server the moment a network variable changes, including the server that wrote it.
on network variable change:
broadcast "%the changed variable% is now %the new value%"Give it a name to listen to one branch instead of every write on the network. A *
is a wildcard, the same as /sknetproxy dump:
on network variable change of "coins::*":
send "%the changed variable% went from %the old value% to %the new value%" to consoleThree expressions work inside it:
| Expression | Holds |
|---|---|
the changed variable |
The name, without the prefix, the way it travels between servers. |
the new value |
The value now. Unset when the variable was deleted. |
the old value |
The value before the change. Unset when there was none, and for a list delete. |
The old value comes from the proxy, not from this server's copy. That matters on the server that made the change, because Skript updates its own copy before the change comes back, so a local read would already show the new number.
Names are lowercased, both the one you write after of and the one in
the changed variable, because Skript treats variable names that way.

Nothing fires while a snapshot is arriving, so a server joining doesn't replay the whole map as changes. A reconnect that only catches up on what it missed is quiet in the same way.
A common use is a cross-server inbox: write to a variable named after the player, and whichever server has them delivers it.
command /msg <text> <text>:
trigger:
set {?inbox::%arg-1%} to "%player%: %arg-2%"
on network variable change of "inbox::*":
set {_name} to the last element of the changed variable split at "::"
set {_who} to {_name} parsed as player
if {_who} is online:
send "&d[mail] %the new value%" to {_who}Deleting a list fires once, with the list name, not once per entry:
delete {?team::red::*}
# fires with the changed variable = "team::red::*" and no new valueThe name of the server the script is running on. It comes from server-name in that
server's plugins/skNetwork/config.yml.
send "This server is %network server name%"name of this network server means the same thing.
This is what lets one script go to every server and still behave differently on each:
on join:
add player's name to {?online::%network server name%::*}
set {?stats::server::%player%} to network server name
on quit:
remove player's name from {?online::%network server name%::*}Every server runs the same file and writes to its own list. Read the lists back for a network wide view:
command /netonline:
trigger:
send "lobby: %size of {?online::lobby::*}%"
send "lobby2: %size of {?online::lobby2::*}%"
send "survival: %size of {?online::survival::*}%"If server-name is blank, the name becomes server- plus the port, like
server-25567. Set it properly. Two servers sharing a name causes real problems, see
Limitations.
A starting balance given once for the whole network, on whichever server sees the player first:
on join:
if network is not synced:
stop
atomically set {?eco::bal::%player%} to 500 if it is not set
atomically add 1 to {?eco::joins::%player%}
set {?stats::server::%player%} to network server nameThe if it is not set form means it doesn't matter that this runs on three servers.
Only the first one wins.
- Examples for complete scripts.
- Network players for who is online where, without keeping a list yourself.
-
Atomic changes for the
if it is not setform. - Limitations on the startup gap.
Guides
Reference