Servers and addons
A server naming what it uses, and why it can never name where to get it
這一頁還沒有翻譯,以下顯示英文原文。
A server can say which addons it runs. They appear on your Addons tab under "This server uses", with an install button for anything you are missing.
addons:
uses:
- cinema
- walkie-talkie/ssvc-server reload applies a change without reconnecting anybody; /ssvc-server status lists what is being advertised. See server configuration.
Ids only
A server names an addon. It can never say where to download it from
This is the rule the whole feature rests on. A server sends an id; your client looks that id up in the index you configured and downloads from there.
A server handing your game a jar location would be remote code execution with a progress bar — so the message a server sends is a space-separated list of ids, and an id cannot contain / or :. There is nowhere in the format to put a URL, which is a stronger guarantee than a promise not to read one.
An id a server asks for that your index does not offer shows as Not in your index, rather than as a button that cannot work. Where to get it is not the server's to say.
Nothing is required
Voice works whether or not you install any of it. The only thing you miss is whatever those addons do.
Required addons
A server can go one step further and mark an addon as required:
addons:
required:
- cinemaWhen you connect without it, your client downloads it from your own index, switches it on, and tells you in chat. If you have it but your index has a newer build, it is updated the same way, so a required addon keeps up with the server. If you already have it but switched it off, it is switched back on, and chat says that too. On the Addons tab the row reads required by this server.
Nothing about where the code comes from changes: it is still your index, and an id your index does not offer is reported in chat rather than fetched from anywhere else. If you would rather press the button yourself, turn off Install what a server requires on the Addons tab — chat then tells you what the server wants and leaves the rest to you.
There is still no switch that refuses you for lacking an addon. Refusing players is what require-client is for, and it is about the voice mod itself.
A mod cannot arrive in time
An addon a server asks for can be switched on as soon as it downloads.
A mod cannot load until you restart, so the session that offered it goes without — and the row says so rather than implying otherwise. Install it, finish playing, and it is there next time.
Removing one a server uses
Allowed, at any time. That feature stops working for you and nothing else changes; the next time you join you are offered it again.
Addons that run on the server
Some features have a server half as well. Those ship as server addon jars: plain Java against com.socketsvc.api.addon, dropped in SocketSVC's own addons/ folder.
plugins/SocketSVC/addons/socketsvc-addon-cinema-server-0.2.0.jar
plugins/SocketSVC/addons/cinema.ymlOne jar for every platform. A server addon never touches a Bukkit type, a Minecraft type or a loader type, so the same file runs on Paper, Fabric, NeoForge and Forge. That is the whole reason SocketSVC has a loader for them rather than four plugins that do the same thing.
They load at startup and again on /ssvc-server reload, which re-reads the folder — so adding or deleting one needs no restart. They are deliberately not hot-swapped mid-session the way client addons are: the client can toggle an addon because the only thing watching is that player, while a server addon holds state other people are connected to.
An addon that fails to load is reported and skipped, and /ssvc-server status names it along with why. The server still starts and the other addons still load: nothing dropped in that folder can stop players getting in.
What one is handed
public final class ExampleServerAddon implements SocketSvcServerAddon {
@Override public void onEnable(ServerAddonContext context) {
String greeting = context.config().getString("greeting", "hello");
context.command((caller, args) -> List.of(greeting + " " + caller.name()
+ (caller.isPlayer() ? " at " + caller.x() + "," + caller.z() : "")));
}
@Override public void onDisable() { }
}config() | The addon's own addons/<id>.yml, as typed getters. Its own file rather than a block in config.yml: an addon you delete should take its settings with it. |
dataDirectory() | A directory of its own, for anything that is not configuration. |
command(handler) | Reached as /ssvc-server addon <id> ..., behind socketsvc.admin.addon. Words in, lines out — SocketSVC owns the command and dispatches into it, because a plain jar cannot register one with Bukkit or Brigadier. The handler is also given who ran it and where they are standing, so a command can mean "here" instead of asking for three numbers off the debug overlay. Implement complete on it for tab completion past your id. |
configFile() | The addons/<id>.yml your config came from. Commands that change what a config file describes have to write them back, or every change is lost on restart. |
screens() | The screen and timecode sync. It lives in SocketSVC because the screens ride the voice status channel and the playhead has to be re-sent on the relay's own schedule; defining screens and driving them is what an addon does with it. See Cinema. |
log(message) | The server log, prefixed with the addon's id. |
The manifest is the same socketsvc.addon.json a client addon carries, with "side": "server":
{
"kind": "addon",
"side": "server",
"id": "example",
"name": "Example",
"version": "1.0.0",
"main": "com.example.ExampleServerAddon"
}Compile against com.socketsvc:socketsvc-server-mod-api with compileOnly and never shade it. SocketSVC's own classloader is the addon's parent and already has the API; a shipped copy would load a second one inside the addon's loader and fail every cast across the boundary.