Contracts and handlers
Define a shared request descriptor and register its platform implementation.
This example creates an operation that returns echo: followed by the supplied string. Use two
artifacts at the same Anvil version as the host:
| Artifact | Anvil compile dependency |
|---|---|
echo-operations | me.whereareiam.anvil:agent-api for shared request descriptors |
echo-agent | me.whereareiam.anvil:agent-server-api for native handler registration |
The echo-operations library exports agent-api with an api dependency so host wiring can use
its descriptor types. The handler depends on echo-operations and uses compileOnly for
agent-server-api: the installed platform agent supplies Anvil APIs. Keep those parent-provided
APIs out of the packaged handler JAR, including transitive dependencies. The server API includes
the shared contracts and does not depend on the client API or global api artifact.
Define the shared operation
Place this in echo-operations/src/main/java/com/example/echo/operation/EchoOperations.java:
package com.example.echo.operation;
import me.whereareiam.anvil.agent.api.model.AgentOperation;
/**
* Shared host and agent descriptors for the echo extension.
*/
public final class EchoOperations {
/**
* Returns the handler's echo response for a string request.
*/
public static final AgentOperation<String, String> ECHO = AgentOperation.<String, String>builder()
.name("com.example.echo.message")
.requestType(String.class)
.responseType(String.class)
.build();
}Use a name beginning with the provider ID followed by a dot. Request and response types must be
supported by the selected transport. The bundled transport uses Jackson; immutable custom models
can use Lombok @Builder with @Jacksonized. Keep platform types out of serialized models.
Register a handler
Place this in echo-agent/src/main/java/com/example/echo/agent/EchoAgentOperations.java:
package com.example.echo.agent;
import com.example.echo.operation.EchoOperations;
import me.whereareiam.anvil.agent.server.api.PlatformAgent;
import me.whereareiam.anvil.agent.server.api.operation.AgentOperationProvider;
import me.whereareiam.anvil.agent.server.api.operation.AgentOperationRegistry;
import org.jetbrains.annotations.NotNull;
/**
* Installs the echo operation into a platform agent.
*/
public final class EchoAgentOperations implements AgentOperationProvider {
@Override
public @NotNull String id() {
return "com.example.echo";
}
@Override
public void install(@NotNull PlatformAgent platform, @NotNull AgentOperationRegistry registry) {
registry.register(EchoOperations.ECHO,
(agent, request) -> agent.call(() -> "echo:" + request));
}
}Create src/main/resources/META-INF/services/me.whereareiam.anvil.agent.server.api.operation.AgentOperationProvider
in the handler artifact containing:
com.example.echo.agent.EchoAgentOperationsRegistration is limited to install. Duplicate provider IDs, duplicate operation names, and names
outside the provider's namespace fail registration. The platform agent itself answers only ping, command
and player-events, the general facts every process capability can read through
ProcessCapabilityContext.platform(); everything else comes from extensions like yours.
Call native APIs
A native handler can resolve a service with platform.requireService(...). For example, the Bukkit
agent exposes org.bukkit.Server and itself as the org.bukkit.plugin.Plugin, and the Velocity agent the
ProxyServer and itself as the plugin instance. install receives the same platform, so a provider can
resolve them once and register a native listener there, before the platform's players join. Execute native
work through platform.call(...) and obey any additional threading rules of the API you invoke. Compile platform SDKs as compileOnly dependencies.
The handler runs in the server's or proxy's own JVM. agent-api and agent-server-api target Java
11, the Java of the oldest supported servers, Paper and Spigot 1.16.5. Compile echo-operations and
echo-agent for the oldest Java of the processes you install them into, for example with
options.release.set(11) on compileJava, and against the oldest platform API you support, such as
spigot-api 1.16.5-R0.1-SNAPSHOT for Bukkit servers. Anvil's own in-server code is built this way.
Override supports(AgentInfo) for handlers restricted to a platform or role. Install platform-specific
JARs only into compatible processes so their classes can link against the expected native SDK.
The generic Echo handler above uses no platform-specific types.