-
Notifications
You must be signed in to change notification settings - Fork 0
Limitations
What skNetwork can't do, and the rules your scripts have to follow.
Read this before you write anything important. Most of these look fine when you test alone and only go wrong when two servers act at the same moment.
The proxy holds the real data. Game servers only hold copies.
If the proxy stops, every game server keeps its copy. Reading still works. Writing doesn't, and each refused write is counted and logged.
Servers reconnect by themselves. The wait starts at 1 second and grows to 30 seconds.
on network disconnect:
broadcast "Lost the proxy. Money is read only for now."A proxy that vanishes without closing the connection, which is what a cable pull or a machine hard rebooting looks like, is noticed by its silence. Each game server pings it every five seconds and gives up after six unanswered pings. It then drops the connection and, once the proxy is back, pulls everything again instead of resuming, because anything written during the silence may never have arrived. The console says so when it happens. A proxy frozen for more than half a minute, by a very long garbage collection pause for example, gets the same treatment.
When a server starts, its copy is empty and stays empty until the proxy sends everything.
An empty copy isn't the same as an empty network. Before the first sync, every
is not set check says yes, even for players who already have money elsewhere. So
skNetwork refuses writes during that time rather than let you overwrite good data.
Guard anything that runs early with network is synced, or do the work in
on network sync. See Sync and events.
Your server answers reads from its own copy. When another server writes, the change goes to the proxy, comes back to you, and your server applies it on its next tick. A few milliseconds on one machine, never instant.
So this shows the old number:
atomically add 50 to {?coins::%uuid of player%}
send "You now have %{?coins::%uuid of player%}% coins"Use and wait and read the proxy's answer instead:
atomically add 50 to {?coins::%uuid of player%} and wait
send "You now have %the atomic result% coins"This is the most common mistake, and the reason skNetwork exists.
# WRONG
if {?coins::%uuid of player%} >= 100:
remove 100 from {?coins::%uuid of player%}If two servers run this at the same moment, both read 100, both think there's enough, and both take 100 away. Use Atomic changes so the proxy does the check and the subtraction together.
A plain remove has no floor and will go negative. Always add without going below 0
when you're spending money.
atomically only works on a single network variable. Not on:
- local variables like
{_x}, because they never leave the server - lists like
{?coins::*} - normal variables like
{coins}with no prefix
add and remove need numbers. The set ... if it is ... forms take any type.
A list name ending in ::* can only be deleted over the network:
delete {?online::lobby::*}You can't set {?online::lobby::*} to something directly. The proxy refuses it.
Normal list use is fine, because Skript turns it into single writes:
add player's name to {?online::%network server name%::*}
remove player's name from {?online::%network server name%::*}Deleting a large list is slow. See Speed below.
send network message and send network action bar go to whichever server holds
that player at that moment. Someone who logs off, or switches server, in the same
instant misses it. There is no queue and no retry.
The list of who is where changes one tick after a join or quit. Inside on join,
network players doesn't include the joining player yet.
See Network players.
skNetwork uses Skript's own serialiser, so anything Skript can save to variables.csv
moves between servers. Text, numbers, booleans, dates, items, and locations all travel.
It goes wrong two ways. The receiving server may not understand the type, usually because its Skript version or its plugins differ. Or the type may not survive being serialised at all, in which case Skript can't save it locally either.
When a server can't read a value, that variable is missing from its copy and a warning appears in its console. Other servers aren't affected.
All servers must run the same skNetwork jar. The proxy checks this when a server connects and refuses it with a clear message if the versions differ.
Skript has to be 2.16.0 or newer. On an older Skript, skNetwork registers its storage
so Skript still loads normally, then refuses to start the network half and says so in
the console. Your variables stay where they were, every write to a ? variable is
refused, and none of the network syntax loads until Skript is updated.
They should also run the same Skript version and the same plugins. If one server has a plugin the others don't, values from that plugin can't be read anywhere else.
atomically ... and wait has three answers, not two:
| Answer | Meaning |
|---|---|
| succeeded | The proxy applied the change. |
| refused | The proxy did not apply it. Nothing happened. |
| timed out | No answer came back. It may or may not have been applied. |
Only a refusal proves nothing happened. On a timeout you don't know, so don't give the
reward and don't tell the player they weren't charged. The default wait is 5 seconds and
can be changed with atomic-timeout in the config.
and wait stops your trigger and continues it later, exactly like Skript's own wait
effect. The normal delay rules apply:
- you can't cancel the event after that line
- it doesn't belong inside a function
-
on deathand similar events are already over by the time it continues
Network variables never touch a game server's disk. They aren't in variables.csv and
they aren't backed up there.
When a game server restarts, its copy is empty until the proxy fills it again. That's normal and takes a moment.
The proxy writes every change to plugins/skNetwork/network.csv and reads it back on
restart. If you set log: none it keeps nothing, so every restart starts empty and all
network variables are lost. Testing only.
The file grows as you write. The proxy rewrites it now and then to drop old lines,
keeping one backup as network.csv.bak.
skNetwork isn't a database. It stores and shares values, that's all. For something like the top 10 balances, your script has to loop the whole list and work it out.
Variable names are not case sensitive. {?Coins::Notch} and {?coins::notch} are the
same variable, the same as in Skript itself. Names travel lowercased, so that is how
/sknetproxy dump and the changed variable show them.
Server names are case sensitive. "Survival" and "survival" are two different
servers to network server ... is online and to execute command ... on network server.
Player names are not, so network server of "notch" finds Notch.
The prefix in skNetwork's config and the pattern in Skript's config.sk have to agree.
If they don't, Skript would take skNetwork's writes and then save every change the
network sends back into variables.csv through the catch-all database. skNetwork
checks for this at startup and switches network variables off on that server rather
than let it happen, with a console message saying which line to fix.
You can't use # as a prefix. It starts a comment in config.sk, so the pattern line
would be cut in half and Skript would send skNetwork every variable on the server. When
skNetwork sees a # it switches network variables off on that server, keeps writing to
local disk, and tells you to change the prefix.
The prefix is stripped before a name is sent, so two servers using different prefixes still share the same data.
Every game server needs its own server-name. If two share one:
- both get the same pushed scripts
- both write to the same names, so
{?online::lobby::*}gets entries from both -
network players on "lobby"shows whichever of the two reported last
The proxy warns you when it notices, but it can't fix it.
You may see that same warning once after a game server crashes hard or loses its network. The proxy is still holding the dead connection when the server comes back, because nothing ever told it the old one was gone. That is harmless: the old connection drops on its own, and the live server keeps its place on the network.
plugins/Skript/scripts/network/ on a game server belongs to skNetwork. Every push
overwrites it, and any file the proxy no longer has is deleted. Edit the copy on the
proxy instead. See Script sharing.
A single file above 512 KB is skipped, and the whole library stops at 16 MB. Both can be changed in the proxy config.
Reading is free, so read as much as you like.
Writing isn't. Every write is a message to the proxy, and the proxy handles writes one at a time so they can't conflict. A script that writes in a loop every tick slows the whole network down, not just its own server.
# bad: one message per player per tick
every tick:
loop all players:
set {?last::%uuid of loop-player%} to nowDeleting a large list is the slowest single thing you can do. The proxy has to check every variable it holds, and no other write happens while it does. Avoid it on lists with thousands of entries during busy times.
A large first sync is spread over several ticks so it doesn't freeze the server, but it still takes time.
A game server that stops reading what the proxy sends, because it is frozen or hopelessly behind, is dropped once 64 MB is waiting for it. The proxy says so in its console. The server reconnects and catches up by itself. This is what stops one stuck server from running the proxy out of memory and taking the whole network down.
broadcast ... across the network is one message per server, not one per player, so it
is cheap. Sending a separate network message to each player in a loop is not.
The connection between the game servers and the proxy is plain TCP. No encryption. The token is sent as normal text.
Anyone who can reach the port and knows the token can read and change every network
variable you have. That's why bind: 127.0.0.1 is the default: it only allows
connections from the same machine.
If your servers are on different machines, put them on a private network or a VPN. Don't open port 25580 to the internet.
Anyone who can put files in plugins/skNetwork/scripts/ on the proxy can run code on
every game server. Treat that folder like console access.
There are no per variable permissions. Any script on any connected server can read and write any network variable.
Any script on any connected server can also message, move, and look up any player on
the network. With remote-commands: true in the proxy config, any script can run
console commands on every server too. That is why it is off by default. Leave it off
unless every person who can write a script on any server is someone you would give
console on all of them.
skNetwork never checks who a player is. It works the same with online-mode=false,
and was tested that way.
Two things follow from that. Player features match by name, so a message to "Notch"
reaches whoever currently holds that name, and on a cracked network that is not
guaranteed to be the same person every time. And variables keyed by UUID only line up
across servers if every server derives the same UUID, which is the case when the proxy
forwards player data (ip_forward on BungeeCord, player-info-forwarding-mode on
Velocity) and not when each server makes up its own offline UUID.
- queue a message for a player who is offline
- share anything other than variables, network state, and
.skfiles - work without a proxy
- work with variables that have no prefix
- encrypt the connection between the proxy and the game servers
- Setup for installing and configuring both halves.
Guides
Reference