Skip to content

Commit ef72508

Browse files
authored
Merge pull request #70 from objz/dev-api
Dev api
2 parents ede1a38 + 2bfeb1b commit ef72508

50 files changed

Lines changed: 1467 additions & 75 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/build.gradle.kts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
plugins {
2+
`java-library`
3+
`checkstyle`
4+
}
5+
6+
java {
7+
toolchain { languageVersion.set(JavaLanguageVersion.of(21)) }
8+
withSourcesJar()
9+
withJavadocJar()
10+
}
11+
12+
repositories {
13+
mavenCentral()
14+
}
15+
16+
dependencies {
17+
testImplementation(libs.junit.jupiter)
18+
}
19+
20+
tasks.test {
21+
useJUnitPlatform()
22+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package dev.objz.commandbridge.api;
2+
3+
import dev.objz.commandbridge.api.channel.ChannelPayload;
4+
import dev.objz.commandbridge.api.channel.ChannelType;
5+
import dev.objz.commandbridge.api.channel.MessageChannel;
6+
import dev.objz.commandbridge.api.message.ServerEventListener;
7+
import dev.objz.commandbridge.api.message.Subscription;
8+
import dev.objz.commandbridge.api.platform.ConnectionState;
9+
import dev.objz.commandbridge.api.platform.Platform;
10+
import dev.objz.commandbridge.api.platform.PlayerLocator;
11+
12+
import java.util.Optional;
13+
import java.util.Set;
14+
import java.util.concurrent.CompletableFuture;
15+
import java.util.function.Consumer;
16+
17+
/** Main entry point for interacting with the CommandBridge network. */
18+
public interface CommandBridgeAPI {
19+
20+
/**
21+
* Obtains a {@link MessageChannel} for the given {@link ChannelType}.
22+
*
23+
* @param type the channel type identity
24+
* @param <T> the payload type
25+
* @param <C> the channel interface type
26+
* @return the message channel
27+
*/
28+
<T extends ChannelPayload, C extends MessageChannel<T>> C channel(ChannelType<T, C> type);
29+
30+
/**
31+
* Broadcasts a payload to all connected servers on a specific channel.
32+
*
33+
* @param channel the channel to broadcast on
34+
* @param payload the data to send
35+
* @return a future that completes when the broadcast is dispatched
36+
*/
37+
<P extends ChannelPayload> CompletableFuture<Void> broadcast(MessageChannel<P> channel, P payload);
38+
39+
/** @return the identity of the current server */
40+
Platform.ServerTarget server();
41+
42+
/** @return the current connection state to the bridge network */
43+
ConnectionState connectionState();
44+
45+
/** @return the IDs of all currently connected servers, if available */
46+
Optional<Set<String>> connectedServers();
47+
48+
/** @return the player location lookup service, if available */
49+
Optional<PlayerLocator> playerLocator();
50+
51+
/**
52+
* Subscribes to server connection events.
53+
*
54+
* @param listener the listener to call when a server connects
55+
* @return a subscription handle to cancel the listener
56+
*/
57+
Subscription onServerConnected(ServerEventListener listener);
58+
59+
/**
60+
* Subscribes to server disconnection events.
61+
*
62+
* @param listener the listener to call when a server disconnects
63+
* @return a subscription handle to cancel the listener
64+
*/
65+
Subscription onServerDisconnected(ServerEventListener listener);
66+
67+
/**
68+
* Subscribes to connection state changes.
69+
*
70+
* @param listener the listener to call when the state changes
71+
* @return a subscription handle to cancel the listener
72+
*/
73+
Subscription onConnectionStateChanged(Consumer<ConnectionState> listener);
74+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package dev.objz.commandbridge.api;
2+
3+
import java.util.Objects;
4+
5+
/** Static provider for accessing the {@link CommandBridgeAPI} instance. */
6+
public final class CommandBridgeProvider {
7+
8+
private static volatile CommandBridgeAPI instance;
9+
10+
private CommandBridgeProvider() {
11+
throw new UnsupportedOperationException("Provider can't be instanced");
12+
}
13+
14+
/**
15+
* @return the registered API instance
16+
* @throws IllegalStateException if the API is not registered
17+
*/
18+
public static CommandBridgeAPI get() {
19+
if (instance == null) {
20+
throw new IllegalStateException("CommandBridge is not available. Is it installed and running?");
21+
}
22+
return instance;
23+
}
24+
25+
/**
26+
* Obtains the API instance cast to a specific type.
27+
*
28+
* @param type the API class type
29+
* @param <T> the API type
30+
* @return the cast API instance
31+
* @throws IllegalStateException if the instance is not available or compatible
32+
*/
33+
public static <T extends CommandBridgeAPI> T get(Class<T> type) {
34+
CommandBridgeAPI api = get();
35+
if (!type.isInstance(api)) {
36+
throw new IllegalStateException(type.getSimpleName() + " is not available on this platform");
37+
}
38+
return type.cast(api);
39+
}
40+
41+
/**
42+
* Registers the API implementation.
43+
*
44+
* @param impl the implementation to register
45+
* @throws IllegalStateException if an implementation is already registered
46+
*/
47+
public static void register(CommandBridgeAPI impl) {
48+
Objects.requireNonNull(impl);
49+
if (instance != null) {
50+
throw new IllegalStateException("CommandBridge already registered");
51+
}
52+
instance = impl;
53+
}
54+
55+
/** Unregisters the current API implementation. */
56+
public static void unregister() {
57+
instance = null;
58+
}
59+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package dev.objz.commandbridge.api.channel;
2+
3+
/** Marker interface for data sent over a {@link MessageChannel}. */
4+
public interface ChannelPayload {
5+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package dev.objz.commandbridge.api.channel;
2+
3+
import java.util.Objects;
4+
5+
/**
6+
* Identity and type information for a {@link MessageChannel}.
7+
*
8+
* @param <T> the payload type
9+
* @param <C> the channel interface type
10+
*/
11+
public abstract class ChannelType<T extends ChannelPayload, C extends MessageChannel<T>> {
12+
13+
private final Class<T> type;
14+
15+
protected ChannelType(Class<T> type) {
16+
this.type = Objects.requireNonNull(type);
17+
}
18+
19+
/** @return the class of the payload handled by this channel */
20+
public Class<T> type() {
21+
return type;
22+
}
23+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package dev.objz.commandbridge.api.channel;
2+
3+
import dev.objz.commandbridge.api.channel.command.CommandChannelType;
4+
5+
/** Registry of built-in {@link ChannelType}s. */
6+
public final class Channels {
7+
8+
/** The default channel for executing commands. */
9+
public static final CommandChannelType COMMAND = new CommandChannelType();
10+
11+
private Channels() {
12+
throw new UnsupportedOperationException("Channels can't be instanced");
13+
}
14+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package dev.objz.commandbridge.api.channel;
2+
3+
import dev.objz.commandbridge.api.message.MessageListener;
4+
import dev.objz.commandbridge.api.message.Subscription;
5+
import dev.objz.commandbridge.api.platform.Platform;
6+
7+
import java.time.Duration;
8+
import java.util.concurrent.CompletableFuture;
9+
10+
/**
11+
* Communication pipe for sending and receiving {@link ChannelPayload}s.
12+
*
13+
* @param <P> the type of payload handled by this channel
14+
*/
15+
public interface MessageChannel<P extends ChannelPayload> {
16+
17+
/**
18+
* Sends a payload to a target server without expecting a response.
19+
*
20+
* @param target the destination server
21+
* @param payload the data to send
22+
* @return a future that completes when the message is sent
23+
*/
24+
CompletableFuture<Void> send(Platform.ServerTarget target, P payload);
25+
26+
/**
27+
* Sends a request to a target server and waits for a response.
28+
*
29+
* @param target the destination server
30+
* @param payload the request data
31+
* @return a future containing the response payload
32+
*/
33+
CompletableFuture<P> request(Platform.ServerTarget target, P payload);
34+
35+
/**
36+
* Sends a request to a target server with a custom timeout.
37+
*
38+
* @param target the destination server
39+
* @param payload the request data
40+
* @param timeout the maximum time to wait for a response
41+
* @return a future containing the response payload
42+
*/
43+
CompletableFuture<P> request(Platform.ServerTarget target, P payload, Duration timeout);
44+
45+
/**
46+
* Subscribes a listener to messages received on this channel.
47+
*
48+
* @param listener the listener to call for incoming messages
49+
* @return a subscription handle to cancel the listener
50+
*/
51+
Subscription listen(MessageListener<P> listener);
52+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package dev.objz.commandbridge.api.channel.command;
2+
3+
import dev.objz.commandbridge.api.channel.MessageChannel;
4+
import dev.objz.commandbridge.api.platform.Platform;
5+
6+
import java.util.UUID;
7+
import java.util.concurrent.CompletableFuture;
8+
9+
/** Specialized channel for dispatching commands to servers. */
10+
public interface CommandChannel extends MessageChannel<CommandPayload> {
11+
12+
/**
13+
* Executes a command as the console.
14+
*
15+
* @param target the destination server
16+
* @param command the command string to run
17+
* @return a future that completes when the command is sent
18+
*/
19+
default CompletableFuture<Void> console(Platform.ServerTarget target, String command) {
20+
return send(target, CommandPayload.console(command));
21+
}
22+
23+
/**
24+
* Executes a command as a specific player.
25+
*
26+
* @param target the destination server
27+
* @param command the command string to run
28+
* @param player the UUID of the player to run as
29+
* @return a future that completes when the command is sent
30+
*/
31+
default CompletableFuture<Void> player(Platform.ServerTarget target, String command, UUID player) {
32+
return send(target, CommandPayload.player(command, player));
33+
}
34+
35+
/**
36+
* Executes a command with operator permissions, bypassing standard checks.
37+
*
38+
* @param target the destination server
39+
* @param command the command string to run
40+
* @param player the UUID of the player to run as
41+
* @return a future that completes when the command is sent
42+
*/
43+
default CompletableFuture<Void> operator(Platform.ServerTarget target, String command, UUID player) {
44+
return send(target, CommandPayload.operator(command, player));
45+
}
46+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package dev.objz.commandbridge.api.channel.command;
2+
3+
import dev.objz.commandbridge.api.channel.ChannelType;
4+
5+
/** Identity for the {@link CommandChannel}. */
6+
public final class CommandChannelType extends ChannelType<CommandPayload, CommandChannel> {
7+
8+
/** Creates a new command channel type. */
9+
public CommandChannelType() {
10+
super(CommandPayload.class);
11+
}
12+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package dev.objz.commandbridge.api.channel.command;
2+
3+
import dev.objz.commandbridge.api.channel.ChannelPayload;
4+
5+
import java.util.UUID;
6+
7+
/**
8+
* Payload for command execution.
9+
*
10+
* @param command the command string to run
11+
* @param runAs the execution mode
12+
* @param player the optional player context
13+
*/
14+
public record CommandPayload(String command, RunAs runAs, UUID player) implements ChannelPayload {
15+
16+
/** Creates a payload for console execution. */
17+
public static CommandPayload console(String command) {
18+
return new CommandPayload(command, RunAs.CONSOLE, null);
19+
}
20+
21+
/** Creates a payload for player execution. */
22+
public static CommandPayload player(String command, UUID player) {
23+
return new CommandPayload(command, RunAs.PLAYER, player);
24+
}
25+
26+
/** Creates a payload for operator execution. */
27+
public static CommandPayload operator(String command, UUID player) {
28+
return new CommandPayload(command, RunAs.OPERATOR, player);
29+
}
30+
}

0 commit comments

Comments
 (0)