.
This commit is contained in:
parent
0b0b650f83
commit
e4fd6a8c5f
12 changed files with 236 additions and 46 deletions
23
README.md
23
README.md
|
|
@ -8,20 +8,23 @@ docker run -d --network scrow -e ME_CONFIG_MONGODB_SERVER=mongo -e ME_CONFIG_MON
|
||||||
docker run -d --network scrow -p 4222:4222 --name nats nats
|
docker run -d --network scrow -p 4222:4222 --name nats nats
|
||||||
```
|
```
|
||||||
|
|
||||||
acce**ss the mongo-db web interface at http://localhost:8081; username `a`, password `1234`**
|
access the mongo-db web interface at http://localhost:8081; username `a`, password `1234`**
|
||||||
|
|
||||||
modules
|
## ENV
|
||||||
-------
|
|
||||||
|
|
||||||
* APIs
|
- HOST_NATS e.g `nats://127.17.0.1:4222`
|
||||||
----
|
- HOST_MONGO e.g `mongodb://localhost:27017/scrow`
|
||||||
|
|
||||||
|
## modules
|
||||||
|
|
||||||
|
### APIs
|
||||||
|
|
||||||
* core-api contains api for all java development
|
* core-api contains api for all java development
|
||||||
* core-bukkit-api contains api for bukkit development
|
* core-bukkit-api contains api for bukkit development
|
||||||
* depends on core-api
|
* depends on core-api
|
||||||
|
|
||||||
* implementations
|
### implementations
|
||||||
---------------
|
|
||||||
the `-impl` suffix indicates that this module implements the API with the same prefix.
|
the `-impl` suffix indicates that this module implements the API with the same prefix.
|
||||||
So `core-impl` implements `core-api`.
|
So `core-impl` implements `core-api`.
|
||||||
* core-bukkit-impl is a spigot plugin. It shades core-impl.
|
* core-bukkit-impl is a spigot plugin. It shades core-impl.
|
||||||
|
|
@ -39,9 +39,9 @@ dependencies {
|
||||||
implementation("io.nats:jnats:2.25.2")
|
implementation("io.nats:jnats:2.25.2")
|
||||||
api("io.nats:jnats:2.25.2")
|
api("io.nats:jnats:2.25.2")
|
||||||
|
|
||||||
api("de.kentoj.scrow:kencommandapi-core:0.2")
|
api("de.kentoj.scrow:kencommandapi-core:0.4")
|
||||||
implementation("de.kentoj.scrow:kencommandapi-bukkit:0.2")
|
implementation("de.kentoj.scrow:kencommandapi-bukkit:0.4")
|
||||||
api("de.kentoj.scrow:kencommandapi-bukkit:0.2")
|
api("de.kentoj.scrow:kencommandapi-bukkit:0.4")
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import com.mongodb.reactivestreams.client.MongoDatabase;
|
||||||
import de.kentoj.kencommandapi.BukkitKenCommandApi;
|
import de.kentoj.kencommandapi.BukkitKenCommandApi;
|
||||||
import de.kentoj.scrow.bukkit.friends.FriendRequestService;
|
import de.kentoj.scrow.bukkit.friends.FriendRequestService;
|
||||||
import de.kentoj.scrow.bukkit.friends.FriendshipService;
|
import de.kentoj.scrow.bukkit.friends.FriendshipService;
|
||||||
import de.kentoj.scrow.bukkit.message.NatsDocumentRepository;
|
|
||||||
import io.nats.client.Connection;
|
import io.nats.client.Connection;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
@ -31,7 +30,7 @@ public class ScrowAPI {
|
||||||
@Getter
|
@Getter
|
||||||
private static Connection nats;
|
private static Connection nats;
|
||||||
@Getter
|
@Getter
|
||||||
private static NatsDocumentRepository natsRepository;
|
private static ServerManager serverManager;
|
||||||
|
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
public static void setDatabase(@Nullable MongoDatabase database) {
|
public static void setDatabase(@Nullable MongoDatabase database) {
|
||||||
|
|
@ -69,8 +68,8 @@ public class ScrowAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
public static void setNatsRepository(NatsDocumentRepository natsRepository) {
|
public static void setServerManager(ServerManager serverManager) {
|
||||||
ScrowAPI.natsRepository = natsRepository;
|
ScrowAPI.serverManager = serverManager;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package de.kentoj.scrow.bukkit;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
public interface ServerManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Mono with handle of deployed server
|
||||||
|
*/
|
||||||
|
Mono<@NotNull String> deployServer(String template);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Flux with handles of running servers
|
||||||
|
*/
|
||||||
|
Flux<@NotNull String> getRunningServers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts a clean shutdown, if that doesn't succeed, kills the server.
|
||||||
|
*/
|
||||||
|
Mono<@NotNull Void> destroyServer(String handle);
|
||||||
|
|
||||||
|
Mono<@NotNull Void> updateState(String handle, String state);
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
package de.kentoj.scrow.bukkit;
|
package de.kentoj.scrow.bukkit;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.crown.command.CrownCommand;
|
||||||
import de.kentoj.scrow.bukkit.economy.CoinsCommand;
|
import de.kentoj.scrow.bukkit.economy.CoinsCommand;
|
||||||
import de.kentoj.scrow.bukkit.friends.command.FriendCommand;
|
import de.kentoj.scrow.bukkit.friends.command.FriendCommand;
|
||||||
import io.nats.client.Message;
|
|
||||||
import io.nats.client.Nats;
|
|
||||||
import org.bson.Document;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
|
@ -21,33 +19,14 @@ public class CoreImplPlugin extends JavaPlugin {
|
||||||
{
|
{
|
||||||
ScrowAPI.getCommandManager().register(new FriendCommand().getRootNode());
|
ScrowAPI.getCommandManager().register(new FriendCommand().getRootNode());
|
||||||
ScrowAPI.getCommandManager().register(new CoinsCommand().getRootNode());
|
ScrowAPI.getCommandManager().register(new CoinsCommand().getRootNode());
|
||||||
|
ScrowAPI.getCommandManager().register(new CrownCommand().getRootNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
registerServer();
|
||||||
var playerId = UUID.randomUUID();
|
|
||||||
var economyService = ScrowAPI.getEconomyService();
|
|
||||||
Mono.when(
|
|
||||||
economyService.setCoins(playerId, 120),
|
|
||||||
economyService.depositCoins(playerId, 100)
|
|
||||||
)
|
|
||||||
.then(economyService.tryWithdrawCoins(playerId, 300))
|
|
||||||
.doOnNext(a -> System.out.println("withdraw 1 success " + a))
|
|
||||||
.then(economyService.tryWithdrawCoins(playerId, 50))
|
|
||||||
.doOnNext(a -> System.out.println("withdraw 2 success " + a))
|
|
||||||
.then(economyService.getCoins(playerId))
|
|
||||||
.doOnNext(a -> System.out.println("coins: " + a))
|
|
||||||
.block();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerServer() {
|
private void registerServer() {
|
||||||
ScrowAPI.getNatsRepository().publish("crown.status", new Document()
|
ScrowAPI.getServerManager().updateState(System.getenv("SERVER_HANDLE"), "UP");
|
||||||
.append("state", "up"));
|
|
||||||
ScrowAPI.getNatsRepository().subscribe("crown.status", doc -> {
|
|
||||||
doc.
|
|
||||||
});
|
|
||||||
ScrowAPI.getNats().reqpublish("crown.status", new Document()
|
|
||||||
.append("state", "up").toJson());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.mongodb.MongoClientSettings;
|
||||||
import com.mongodb.reactivestreams.client.MongoClient;
|
import com.mongodb.reactivestreams.client.MongoClient;
|
||||||
import com.mongodb.reactivestreams.client.MongoClients;
|
import com.mongodb.reactivestreams.client.MongoClients;
|
||||||
import de.kentoj.kencommandapi.BukkitKenCommandApi;
|
import de.kentoj.kencommandapi.BukkitKenCommandApi;
|
||||||
|
import de.kentoj.scrow.bukkit.crown.CrownServerManager;
|
||||||
import de.kentoj.scrow.bukkit.economy.InMemoryEconomyService;
|
import de.kentoj.scrow.bukkit.economy.InMemoryEconomyService;
|
||||||
import de.kentoj.scrow.bukkit.economy.MongoEconomyService;
|
import de.kentoj.scrow.bukkit.economy.MongoEconomyService;
|
||||||
import de.kentoj.scrow.bukkit.friends.friendship.InMemoryFriendshipService;
|
import de.kentoj.scrow.bukkit.friends.friendship.InMemoryFriendshipService;
|
||||||
|
|
@ -12,6 +13,7 @@ import de.kentoj.scrow.bukkit.friends.friendship.MongoFriendshipService;
|
||||||
import de.kentoj.scrow.bukkit.friends.request.InMemoryFriendRequestService;
|
import de.kentoj.scrow.bukkit.friends.request.InMemoryFriendRequestService;
|
||||||
import de.kentoj.scrow.bukkit.friends.request.MongoFriendRequestService;
|
import de.kentoj.scrow.bukkit.friends.request.MongoFriendRequestService;
|
||||||
import io.nats.client.Nats;
|
import io.nats.client.Nats;
|
||||||
|
import io.nats.client.Options;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.bson.UuidRepresentation;
|
import org.bson.UuidRepresentation;
|
||||||
|
|
@ -35,7 +37,12 @@ public class ScrowAPISurface {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ScrowAPI.setMessageBroker(Nats.connect());
|
String natsHost = System.getenv("HOST_NATS");
|
||||||
|
var options = Options.builder()
|
||||||
|
.server(natsHost)
|
||||||
|
.pedantic()
|
||||||
|
.build();
|
||||||
|
ScrowAPI.setNats(Nats.connect(options));
|
||||||
} catch (IOException | InterruptedException e) {
|
} catch (IOException | InterruptedException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
@ -46,18 +53,21 @@ public class ScrowAPISurface {
|
||||||
MongoClientSettings.getDefaultCodecRegistry(),
|
MongoClientSettings.getDefaultCodecRegistry(),
|
||||||
CodecRegistries.fromProviders(pojoCodecProvider)
|
CodecRegistries.fromProviders(pojoCodecProvider)
|
||||||
);
|
);
|
||||||
|
String mongoHost = System.getenv("HOST_MONGO");
|
||||||
var settings = MongoClientSettings.builder()
|
var settings = MongoClientSettings.builder()
|
||||||
.codecRegistry(codecRegistry)
|
.codecRegistry(codecRegistry)
|
||||||
.uuidRepresentation(UuidRepresentation.STANDARD)
|
.uuidRepresentation(UuidRepresentation.STANDARD)
|
||||||
.applyConnectionString(new ConnectionString("mongodb://localhost:27017/scrow"))
|
.applyConnectionString(new ConnectionString(mongoHost))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
mongoClient = MongoClients.create(settings);
|
mongoClient = MongoClients.create(settings);
|
||||||
ScrowAPI.setDatabase(mongoClient.getDatabase("scrow"));
|
ScrowAPI.setDatabase(mongoClient.getDatabase("scrow"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScrowAPI.setServerManager(new CrownServerManager(ScrowAPI.getNats()));
|
||||||
|
|
||||||
ScrowAPI.setEconomyService(ScrowAPI.getDatabase() != null ?
|
ScrowAPI.setEconomyService(ScrowAPI.getDatabase() != null ?
|
||||||
new MongoEconomyService(ScrowAPI.getDatabase()) : new InMemoryEconomyService());
|
new MongoEconomyService(ScrowAPI.getDatabase()) : new InMemoryEconomyService());
|
||||||
|
|
||||||
ScrowAPI.setFriendRequestService(ScrowAPI.getDatabase() != null ?
|
ScrowAPI.setFriendRequestService(ScrowAPI.getDatabase() != null ?
|
||||||
new MongoFriendRequestService(ScrowAPI.getDatabase()) : new InMemoryFriendRequestService());
|
new MongoFriendRequestService(ScrowAPI.getDatabase()) : new InMemoryFriendRequestService());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
package de.kentoj.scrow.bukkit.crown;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import de.kentoj.scrow.bukkit.ScrowAPI;
|
||||||
|
import de.kentoj.scrow.bukkit.ServerManager;
|
||||||
|
import io.nats.client.Connection;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CrownServerManager implements ServerManager {
|
||||||
|
|
||||||
|
private final Connection nats;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<@NotNull String> deployServer(String template) {
|
||||||
|
return Mono.fromFuture(nats.request("crown.deploy-server", template.getBytes()))
|
||||||
|
.map(msg -> new String(msg.getData()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Flux<@NotNull String> getRunningServers() {
|
||||||
|
return Mono.fromFuture(nats.request("crown.deploy-server", new byte[0]))
|
||||||
|
.flatMapMany(msg -> {
|
||||||
|
var ids = new String(msg.getData()).split("\u001F");
|
||||||
|
return Flux.fromStream(Arrays.stream(ids));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<@NotNull Void> destroyServer(String handle) {
|
||||||
|
return Mono.fromFuture(nats.request("crown.destroy-server",handle.getBytes()))
|
||||||
|
.then();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<@NotNull Void> updateState(String handle, String state) {
|
||||||
|
Preconditions.checkArgument(!state.contains(" "), "state may not contain spaces");
|
||||||
|
var payload = (handle + " " + state).getBytes();
|
||||||
|
return Mono.fromFuture(nats.request("crown.update-state", payload))
|
||||||
|
.then();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package de.kentoj.scrow.bukkit.crown.command;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.BukkitCommandContext;
|
||||||
|
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
|
||||||
|
import de.kentoj.scrow.bukkit.ScrowAPI;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
public class CrownCommand {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final CommandNode<CommandSender, BukkitCommandContext> rootNode;
|
||||||
|
|
||||||
|
public CrownCommand() {
|
||||||
|
this.rootNode = ScrowAPI.getCommandManager().createNode("crown", "server-manager");
|
||||||
|
this.rootNode.addLiteral(new CrownListServersLiteral().getNode());
|
||||||
|
this.rootNode.addLiteral(new CrownDeployServerLiteral().getNode());
|
||||||
|
this.rootNode.addLiteral(new CrownDestroyServerLiteral().getNode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package de.kentoj.scrow.bukkit.crown.command;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.BukkitCommandContext;
|
||||||
|
import de.kentoj.kencommandapi.api.processing.CommandExecutor;
|
||||||
|
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
|
||||||
|
import de.kentoj.kencommandapi.api.structure.argument.types.StringArgumentType;
|
||||||
|
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
|
||||||
|
import de.kentoj.scrow.bukkit.ScrowAPI;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
public class CrownDeployServerLiteral implements CommandExecutor<CommandSender, BukkitCommandContext> {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final CommandNode<CommandSender, BukkitCommandContext> node;
|
||||||
|
private final CommandArgument<CommandSender, BukkitCommandContext, String> templateArg;
|
||||||
|
|
||||||
|
public CrownDeployServerLiteral() {
|
||||||
|
this.node = ScrowAPI.getCommandManager().createNode("deploy-server");
|
||||||
|
this.node.setExecutor(this);
|
||||||
|
{
|
||||||
|
this.templateArg = ScrowAPI.getCommandManager().createArgument("template", new StringArgumentType<>());
|
||||||
|
this.node.addArgument(templateArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(BukkitCommandContext ctx) {
|
||||||
|
var template = ctx.getArg(templateArg);
|
||||||
|
ScrowAPI.getServerManager().deployServer(template)
|
||||||
|
.subscribe(handle -> {
|
||||||
|
ctx.getSender().sendMessage("Deployed instance of " + template + " with handle " + handle);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package de.kentoj.scrow.bukkit.crown.command;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.BukkitCommandContext;
|
||||||
|
import de.kentoj.kencommandapi.api.processing.CommandExecutor;
|
||||||
|
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
|
||||||
|
import de.kentoj.kencommandapi.api.structure.argument.types.StringArgumentType;
|
||||||
|
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
|
||||||
|
import de.kentoj.scrow.bukkit.ScrowAPI;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class CrownDestroyServerLiteral implements CommandExecutor<CommandSender, BukkitCommandContext> {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final CommandNode<CommandSender, BukkitCommandContext> node;
|
||||||
|
private final CommandArgument<CommandSender, BukkitCommandContext, String> handleArg;
|
||||||
|
|
||||||
|
public CrownDestroyServerLiteral() {
|
||||||
|
this.node = ScrowAPI.getCommandManager().createNode("destroy-server");
|
||||||
|
this.node.setExecutor(this);
|
||||||
|
{
|
||||||
|
this.handleArg = ScrowAPI.getCommandManager().createArgument("template", new StringArgumentType<>());
|
||||||
|
this.handleArg.setSuggestionProvider(ctx -> {
|
||||||
|
//noinspection CodeBlock2Expr
|
||||||
|
return ScrowAPI.getServerManager().getRunningServers().collect(Collectors.toSet()).toFuture();
|
||||||
|
});
|
||||||
|
this.node.addArgument(handleArg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(BukkitCommandContext ctx) {
|
||||||
|
var handle = ctx.getArg(handleArg);
|
||||||
|
ScrowAPI.getServerManager().destroyServer(handle)
|
||||||
|
.subscribe(__ -> {
|
||||||
|
ctx.getSender().sendMessage("Destroyed server with handle " + handle);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package de.kentoj.scrow.bukkit.crown.command;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.BukkitCommandContext;
|
||||||
|
import de.kentoj.kencommandapi.api.processing.CommandExecutor;
|
||||||
|
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
|
||||||
|
import de.kentoj.scrow.bukkit.ScrowAPI;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
public class CrownListServersLiteral implements CommandExecutor<CommandSender, BukkitCommandContext> {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final CommandNode<CommandSender, BukkitCommandContext> node;
|
||||||
|
|
||||||
|
public CrownListServersLiteral() {
|
||||||
|
this.node = ScrowAPI.getCommandManager().createNode("list-servers");
|
||||||
|
this.node.setExecutor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(BukkitCommandContext ctx) {
|
||||||
|
ScrowAPI.getServerManager().getRunningServers()
|
||||||
|
.collectList()
|
||||||
|
.subscribe(uids -> {
|
||||||
|
var msg = new StringBuilder().append('\n');
|
||||||
|
uids.forEach(uid -> msg.append(" > ").append(uid));
|
||||||
|
msg.append('\n');
|
||||||
|
ctx.getPlayerSender().sendMessage(msg.toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,7 +23,7 @@ public class CoinsCommand {
|
||||||
private final CommandArgument<CommandSender, BukkitCommandContext, Integer> amountArg;
|
private final CommandArgument<CommandSender, BukkitCommandContext, Integer> amountArg;
|
||||||
|
|
||||||
public CoinsCommand() {
|
public CoinsCommand() {
|
||||||
this.rootNode = ScrowAPI.getCommandManager().createNode("coins");
|
this.rootNode = ScrowAPI.getCommandManager().createNode("coins", "eco");
|
||||||
this.playerArg = ScrowAPI.getCommandManager().createArgument("player", OfflinePlayerArgumentType.getInstance());
|
this.playerArg = ScrowAPI.getCommandManager().createArgument("player", OfflinePlayerArgumentType.getInstance());
|
||||||
this.amountArg = ScrowAPI.getCommandManager().createArgument("amount", new IntegerArgumentType<>());
|
this.amountArg = ScrowAPI.getCommandManager().createArgument("amount", new IntegerArgumentType<>());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue