How It Works
MythicProxy has two plugins. The Velocity plugin on the proxy is the hub: it saves the data and passes changes between your backends. The Paper plugin on each backend keeps the data that backend needs in memory, so the proxy's database is the only permanent copy.
Connections and Security
Each backend connects to the hub port of every proxy it knows. The proxy never connects to a backend, so backends need no open port. See Hub Port and Firewall for the port and who should be able to reach it.
- Backends ping every 15 seconds, and a link that stays silent for 45 seconds is closed.
- A backend retries a lost link every 5 seconds, for as long as it runs.
- When a link opens, both sides prove that they know the same secret. The secret itself never crosses the network, and a backend with the wrong secret is refused.
- After that, nothing is encrypted or signed. Anyone on the network path can read, change or inject messages, and a backend that knows the secret is fully trusted.
- Nothing confirms that a change or a signal arrived. A message lost on the way is not sent again, and the sender is not told.
Reading and Writing
Skills, conditions and placeholders read the backend's own copy, so reading never waits and keeps working while the proxy is down.
When a skill sets or unsets a variable:
- The backend changes its own copy at once.
- It sends the change to one proxy, see Multiple Proxies.
- The proxy saves it and passes it to the other backends connected to it.
- Each backend applies it unless it already holds a newer value, see Conflicts and Clocks.
The mechanic reports success once the change is sent or queued. It is not told if the change was outdated, lost or not saved.
networkVariableAdd sends the amount, not the new total. The backend shows its own estimate at once. The proxy adds the amount to the saved value, saves the result and sends the new total to every backend connected to it, including the one that added.
When Data Loads
- Global variables load when a backend connects to a proxy, and again after every reconnect.
- Player variables load when the player joins the backend and are dropped when the player leaves it, also when switching to another server. Players who were online before MythicProxy started have none until they rejoin.
- Profile variables load with the player's MythicRPG profile, see MythicRPG Profile Variables.
Until the proxy answers, a joining player's variables read as not set. Join and switch triggers wait for them (Missed Events), other skills do not. A load only adds and updates values, it never removes one. Which variables a load brings back is described under Persistence and Expiry.
Conflicts and Clocks
When two changes to the same variable collide, the one with the newer timestamp wins, no matter which arrives first. Each change is stamped with the clock of the backend that makes it. Backends and the proxy's database ignore a change that is older than the one they hold. Nothing is logged, and the mechanic that made the change reported success anyway.
Clocks also decide when variables expire. A duration ends at a fixed time on the clock of the backend that cast the mechanic, and the proxy uses its own clock to check whether a saved variable has expired.
Keep every clock in sync, for example with NTP on the proxy and on every backend.
- A backend whose clock runs behind cannot change variables that other servers changed more recently.
- A backend whose clock runs ahead wins every collision. A clock set far ahead, such as a wrong date, blocks every other server from changing those variables until real time catches up. To recover, fix the clock, correct or delete the variable's row in the
mythicproxy_variablestable, and restart the backends.
Lost adds. The proxy saves a new total only if the add is not older than the saved value. If two backends add to the same variable at almost the same moment and the adds reach the proxy in the opposite order of their timestamps, one add is lost and nothing is logged. An add that waited in the queue while the proxy was down is lost the same way if the variable changed meanwhile. If an exact total matters, add to that variable from one server only.
When a Proxy Is Down
A backend that loses its proxy (a restart, a crash or a network problem) keeps running on its own copy and reconnects by itself. The saved data stays in the proxy's database.
Queued. While no proxy is connected, a backend queues its variable changes, its signals and the requests that load joining players' variables, up to queue-size messages (backend options). When the queue is full, the oldest message is dropped and nothing is logged. The queue is kept in memory and is lost when the backend stops. Queued changes keep their original timestamp, so they can lose to newer changes.
Lost.
- Signals from other servers, and join, switch and quit events (Missed Events), that happen while the backend is disconnected never reach it.
- Messages sent while a backend has not yet noticed a broken link. A proxy that stops closes its links, so backends notice at once, but a link that breaks silently, for example through a pulled cable, takes up to 45 seconds to notice.
- Plugin API calls return
falseat once.
Reconnecting. On every reconnect, the backend sends its queue, then loads the global variables and the player directory again. It does not catch up on:
- a global variable that another server unset meanwhile, which stays until it changes again or the backend restarts
- the player and profile variables of players who stayed online, which load again when the player rejoins
Multiple Proxies
You can run several Velocity proxies in one network. The proxies never talk to each other: every backend connects to every proxy, and one shared database holds the saved data.
- One MySQL database for all proxies. Set
storagetoMYSQLon every proxy and use the same database, see Storage. A SQLite file belongs to one proxy, so each proxy would only keep what passed through it. - The same secret, and a different
proxy-id, on every proxy. Proxies with the same id overwrite each other's players in the player directory. - Every backend connects to every proxy. A change reaches only the backends connected to the proxy that received it, and a join, switch or quit reaches only the backends connected to the player's proxy. List all proxies in
proxieson every backend, see How Backends Find the Proxy. - Changes go to one proxy: the first connected one in the backend's list, which holds the
proxiesentries in order, then the proxies learned from announcements. If it drops, the next one takes over at once, and when an earlier one comes back it is used again. - The same server names on every proxy. If two proxies name a backend differently, one of them drops its messages, see A Backend Is Known Under Two Names.
- Synced clocks, see Conflicts and Clocks.
Player Directory
Every backend keeps a list of everyone on the network: name, UUID and current server. The proxies' join, switch and quit events keep it up to date, and when a backend connects to a proxy, it replaces that proxy's part of the list with a full copy. The network placeholders read this list.
The list is only as fresh as the last message. It is never refreshed on a timer, a disconnected backend keeps its old list, and when a proxy crashes, its players stay listed until that proxy sends a new list. <network.online> can then be too high.
Limits
- A message between a backend and a proxy can be at most 1 MiB (1,048,576 bytes), counting the whole message and not only the value. A larger message is dropped, see Messages Over the Size Limit.
- With MySQL storage, a saved value can be at most 65,535 bytes and a server name at most 64 characters. For variable names, see Variable Names.