Remote Java SDK · 2.0.0

Your bot platform, from anywhere.

A type-safe client for control panels, orchestration services and automation running outside Paper. Authenticate once, call the Remote API and subscribe to resilient live event streams.

ControlService.java
try (UltimateBotClient client =
        UltimateBotClient.builder()
            .baseUri("http://server:8765/ultimatebot/api/v1/")
            .token(token)
            .build()) {
    client.spawnBot(request)
        .requireSuccess();
}
01Java 21+
02Bearer authentication
03Immutable request models
04Reconnecting SSE

Remote integration

A Java client, not a Minecraft plugin dependency.

The SDK wraps UltimateBot’s authenticated HTTP endpoints and live event stream. It is designed for standalone Java applications, dashboards, network services and test automation.

01 / Command

Typed operations

Replace raw routes and JSON maps with validated builders, enums, records and consistent operation responses.

Client Javadocs
02 / Observe

Live event stream

Receive structured SSE envelopes with automatic reconnection, exponential retry and Last-Event-ID resume support.

EventBus Javadocs
03 / Discover

Dynamic platform data

List the combat modes, custom brains and hosted addons installed on the target UltimateBot server.

Platform discovery

The SDK is included in your application

Unlike the server API, the SDK is an implementation dependency. It contains the HTTP client, Jackson integration, event-stream handling and shared model contracts needed by the remote application.

Server setup

Enable one authenticated endpoint.

Remote access is disabled by default. Configure a strong token, choose the network interface deliberately and restart or reload the supported UltimateBot configuration before connecting.

plugins/UltimateBot/config.yml
remote-api:
  enabled: true
  host: "127.0.0.1"
  port: 8765
  base-path: "/ultimatebot/api/v1"
  token: "replace-with-a-long-random-secret"
Local service

Keep the default bind

Use 127.0.0.1 when the Java application runs on the same machine. The API is not exposed to the public network.

Remote service

Protect the route

When binding beyond localhost, restrict the port with a firewall or private network and place TLS termination in front of the endpoint.

Treat the token as a server credential

Never commit it to source control, expose it in browser-side JavaScript or log it. Supply it through your application’s secret or environment configuration.

Installation

Add the SDK to a Java 21 application.

The published artifact brings its shared UltimateBot models and JSON runtime transitively. No Paper or Minecraft dependency is required.

build.gradle.kts
repositories {
    maven("https://repo.monkeymoon104.it/releases")
}

dependencies {
    implementation("com.monkey.ultimatebot:sdk:2.0.0")
}

Client lifecycle

Build once, close once.

UltimateBotClient owns the remote event bus and may use a supplied HTTP client or ObjectMapper. Prefer one long-lived instance and close it during application shutdown.

Create and verify a client
UltimateBotClient client = UltimateBotClient.builder()
    .baseUri("https://minecraft.example.com/ultimatebot/api/v1/")
    .token(System.getenv("ULTIMATEBOT_TOKEN"))
    .timeout(Duration.ofSeconds(8))
    .build();

client.health().requireSuccess();

Runtime.getRuntime().addShutdownHook(Thread.ofPlatform().unstarted(client::close));
  • baseUri(String|URI) selects the versioned Remote API root
  • token(String) is required and validated before construction
  • timeout(Duration) controls normal request timeouts
  • httpClient(HttpClient) allows managed transport reuse
  • objectMapper(ObjectMapper) allows compatible JSON customization
  • close() terminates active event subscriptions and workers

Bot requests

Safe defaults, fluent specialization.

Start with an owner-bound or independent factory, override only what the scenario needs, then build an immutable request. Cross-field validation catches invalid modes, ranges and behavior combinations locally.

Spawn a configurable training opponent
BotSpawnRequest request = BotSpawnRequest.ownedBy(playerUuid)
    .botNameTemplate("Remote-Trainer")
    .botUUID(customBotUuid)
    .difficulty(DifficultyTier.HARD)
    .combatMode(CombatMode.MACE)
    .targetMode(BotTargetMode.PLAYERS)
    .armor(BotArmorTier.NETHERITE)
    .totemCount(8)
    .autoTargetRange(24.0D)
    .healing(true)
    .explosionBlockDamage(false)
    .emptyEquipmentSlot(SdkBotEquipmentSlot.OFF_HAND)
    .build();

BotOperationResponse response = client.spawnBot(request).requireSuccess();
BotSnapshotResponse spawned = Objects.requireNonNull(
    response.snapshot(), "Successful spawn did not return a snapshot");
UUID botUuid = Objects.requireNonNull(spawned.botUUID(), "Spawned bot UUID is unavailable");
ownedBy(uuid)

Single opponent

Starts from SINGLE mode and supplies the required owner UUID automatically.

independent()

Event bot

Starts without an owner and accepts explicit target UUIDs for controlled scenarios.

builder()

Any lifecycle mode

Configure EVENT, ALLY or TEAM_ALLY, including shared team owners.

Convenience profiles

Builder methodEffect
stationary()Disables movement-oriented behavior for controlled stationary scenarios.
wander(radius, distance, delay)Enables idle wandering and configures its return-to-spawn behavior in one call.
disableExplosiveCombat()Disables Crystal PvP, explosions and related destructive combat options together.
equipmentItem(slot, material, amount)Keeps a specific material in a main-hand, off-hand or armor slot.
emptyEquipmentSlot(slot)Prevents UltimateBot from placing anything into the selected slot.
brain(BrainKey)Assigns a registered full custom AI independently of the selected mode.

Remote operations

Manage the complete runtime surface.

Read operations return immutable response models. Mutation operations return BotOperationResponse with a success flag, message, optional latest snapshot and optional bulk-removal count.

Operation familyClient methods
Health and discoveryhealth, listBots, activeBotCount, getBot, listCombatModes, getCombatMode, listBrains, getBrain, listAddons.
LifecyclespawnBot, remove, removeByBotUUID, removeAll and removeBySource.
BehaviorTotems, follow, combat, difficulty, armor, auto-target, targets, team owners, WorldGuard respect, idle wander and owner-death persistence.
CombatTarget mode, combat mode, custom brain, tuning, healing, Crystal PvP, explosions, terrain damage, Ender Pearls and bot-vs-bot attacks.
PresentationKill messages and persistent main-hand, off-hand or armor equipment-slot policies.
Discover, update and remove
BotSnapshotResponse bot = client.getBot(ownerOrBotUuid);

client.updateCombatModeByBotUUID(bot.botUUID(), CombatMode.CRYSTAL).requireSuccess();
client.updateTargetModeByBotUUID(bot.botUUID(), BotTargetMode.PLAYERS_AND_MOBS).requireSuccess();
client.updateBrain(bot.botUUID(), BrainKey.of("myaddon", "adaptive-ai")).requireSuccess();

client.resetBrain(bot.botUUID()).requireSuccess();
client.removeByBotUUID(bot.botUUID()).requireSuccess();

Owner-or-bot UUID methods

Most modern SDK updates resolve either identity. Explicit ByBotUUID variants remain available where owner and bot routes have distinct server semantics. Consult each Javadoc method before choosing the identifier.

Server-Sent Events

Live bot events that recover automatically.

The SDK opens a background SSE connection per subscription, reconnects with exponential delay and resumes from the last delivered event ID when the server supports replay.

Filtered event subscription
BotEventSubscription subscription = client.events().subscribeForBot(
    botUuid,
    Set.of(
        SdkBotEventType.ATTACK_STARTED,
        SdkBotEventType.DIED,
        SdkBotEventType.TARGET_CHANGED),
    event -> {
        System.out.printf("%s #%d at %s%n",
            event.type(), event.sequence(), event.occurredAt());

        event.payloadValue("targetUUID", String.class)
            .ifPresent(target -> System.out.println("Target: " + target));
    });

// Later: subscription.close();
subscribe

All bots

Receive all event types or filter with a set of SdkBotEventType values.

subscribeForOwner

One owner

Filter the server stream by owner UUID and optionally by event type.

subscribeForBot

One bot entity

Follow a specific runtime bot UUID even in multi-bot environments.

  • Spawn accepted and completed
  • Despawn accepted and completed
  • Death and entity kill outcomes
  • Target changes and setting acceptance
  • Attack, damage and prepared explosions
  • Healing, teleport and totem use
  • Unknown future types preserved as strings
  • Per-bot sequence, event ID and occurrence timestamp

Close every retained subscription

A subscription owns a virtual-thread worker and network stream. Use try/finally, application lifecycle hooks or another deterministic owner; closing the client closes all remaining subscriptions.

Models and failures

Immutable data with explicit failure paths.

Requests validate before transport, responses are records, optional values are annotated, and protocol/HTTP failures use a dedicated client exception.

BotOperationResponse

Operation outcome

Inspect success, message, snapshot and removedCount, or call requireSuccess() for fail-fast flows.

Response Javadocs
BotSnapshotResponse

Current bot state

Identity, owners, targets, settings, selected mode/brain and runtime state returned as an immutable snapshot.

Snapshot Javadocs
BotEventEnvelope

Forward-compatible event

Known metadata remains typed while event-specific payload values can be accessed safely by name and runtime type.

Envelope Javadocs
UltimateBotClientException

Transport or protocol error

Authentication failures, non-success HTTP status, malformed responses and connection problems do not masquerade as bot operation failures.

Exception Javadocs
Separate remote and operation failures
try {
    BotOperationResponse response = client.updateDifficulty(botUuid, DifficultyTier.GOD);
    if (!response.success()) {
        logger.warn("Server rejected update: {}", response.message());
    }
} catch (UltimateBotClientException transportFailure) {
    logger.error("UltimateBot endpoint unavailable", transportFailure);
}

Dynamic combat platform

Discover what this server can run.

Combat modes and brains are namespaced values, not a hardcoded remote list. Query the server before presenting choices in a control panel.

Populate a remote control panel
List<CombatModeDefinition> modes = client.listCombatModes();
List<BrainDefinition> brains = client.listBrains();
List<AddonInfo> addons = client.listAddons();

modes.stream()
    .filter(CombatModeDefinition::enabled)
    .forEach(mode -> ui.addMode(mode.mode(), mode.displayName()));

client.updateCombatModeByBotUUID(botUuid, CombatMode.of("myaddon", "adaptive-duels"));
client.updateBrain(botUuid, BrainKey.of("myaddon", "adaptive-ai"));
Combat modes

Metadata and profiles

Receive namespaced identity, display name, description, permission, capabilities and server-defined difficulty profiles.

Brains

Full AI choices

List registered custom brains, inspect capabilities and assign or reset them independently of a mode.

Addons

Runtime status

Inspect installed hosted addons and their lifecycle state. The SDK intentionally cannot upload or execute jars.

Generated from source

Complete SDK reference.

Search every public SDK type generated for version 2.0.0. Open a result for its constructor, builder methods, fields, response contract and nullability details.

Loading public types…

Loading the generated Javadoc index…