Skip to content

Commit

Permalink
GH-359 Better suport for Minestom. Add context providers and argument…
Browse files Browse the repository at this point in the history
…s for player and instance types. (#360)

Use adventure extension. Add minestom example. Bump Minestom-CE version. Add default messages for minestom.
  • Loading branch information
Rollczi committed Jan 21, 2024
1 parent 1f75813 commit 8c81f44
Show file tree
Hide file tree
Showing 23 changed files with 454 additions and 82 deletions.
32 changes: 32 additions & 0 deletions examples/minestom/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
plugins {
id("java")
id("com.github.johnrengelman.shadow") version "8.0.0"
}

java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

repositories {
mavenCentral()
maven("https://repo.panda-lang.org/releases/")
maven("https://jitpack.io")
}

dependencies {
implementation("dev.hollowcube:minestom-ce:5347c0b11f")
implementation("net.kyori:adventure-text-minimessage:4.15.0")

// implementation("dev.rollczi:litecommands-minestom:3.3.0") // <-- uncomment in your project
implementation(project(":litecommands-minestom")) // don't use this line in your build.gradle
}

tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> {
archiveFileName.set("ExampleMinestom v${project.version}.jar")
}

sourceSets.test {
java.setSrcDirs(emptyList<String>())
resources.setSrcDirs(emptyList<String>())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package dev.rollczi.example.minestom;


import dev.rollczi.example.minestom.command.MsgCommand;
import dev.rollczi.example.minestom.handler.MyInvalidUsageHandler;
import dev.rollczi.example.minestom.handler.MyPermissionMessage;
import dev.rollczi.litecommands.LiteCommands;
import dev.rollczi.litecommands.minestom.LiteMinestomFactory;
import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandSender;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Player;
import net.minestom.server.event.GlobalEventHandler;
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.instance.InstanceManager;
import net.minestom.server.instance.block.Block;

public class ExampleMinestom {

public static void main(String[] args) {
MinecraftServer init = MinecraftServer.init();
InstanceManager instanceManager = MinecraftServer.getInstanceManager();
// Create the instance
InstanceContainer instanceContainer = instanceManager.createInstanceContainer();
// Set the ChunkGenerator
instanceContainer.setGenerator(generationUnit -> generationUnit.modifier().fill(
new Pos(generationUnit.absoluteStart().x(), 0, generationUnit.absoluteStart().z()),
new Pos(generationUnit.absoluteEnd().x(), 160, generationUnit.absoluteEnd().z()),
Block.STONE
));

// Add an event callback to specify the spawning instance (and the spawn position)
GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();
globalEventHandler.addListener(AsyncPlayerConfigurationEvent.class, event -> {
Player player = event.getPlayer();
event.setSpawningInstance(instanceContainer);
player.setRespawnPoint(new Pos(0, 160, 0));
});


// LiteCommands
LiteCommands<CommandSender> liteCommands = LiteMinestomFactory.builder()
.commands(
new MsgCommand()
)

.missingPermission(new MyPermissionMessage())
.invalidUsage(new MyInvalidUsageHandler())

.build();

init.start("localhost", 25565);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dev.rollczi.example.minestom.command;

import dev.rollczi.litecommands.annotations.argument.Arg;
import dev.rollczi.litecommands.annotations.command.Command;
import dev.rollczi.litecommands.annotations.context.Context;
import dev.rollczi.litecommands.annotations.execute.Execute;
import dev.rollczi.litecommands.annotations.join.Join;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.minestom.server.entity.Player;

@Command(name = "message", aliases = {"msg"})
public class MsgCommand {

private final MiniMessage miniMessage = MiniMessage.miniMessage();

@Execute
void execute(@Context Player player, @Arg("player") Player target, @Join("message") String message) {
player.sendMessage(miniMessage.deserialize("<gray>[<yellow>Me<gray> -> <yellow>" + target.getUsername() + "<gray>] <white>" + message));
target.sendMessage(miniMessage.deserialize("<gray>[<yellow>" + player.getUsername() + "<gray> -> <yellow>Me<gray>] <white>" + message));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dev.rollczi.example.minestom.handler;

import dev.rollczi.litecommands.handler.result.ResultHandlerChain;
import dev.rollczi.litecommands.invalidusage.InvalidUsageHandler;
import dev.rollczi.litecommands.invocation.Invocation;
import dev.rollczi.litecommands.schematic.Schematic;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.minestom.server.command.CommandSender;

public class MyInvalidUsageHandler implements InvalidUsageHandler<CommandSender> {

private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();

@Override
public void handle(Invocation<CommandSender> invocation, dev.rollczi.litecommands.invalidusage.InvalidUsage<CommandSender> result, ResultHandlerChain<CommandSender> chain) {
Schematic schematic = result.getSchematic();
CommandSender sender = invocation.sender();

if (schematic.isOnlyFirst()) {
sender.sendMessage(MINI_MESSAGE.deserialize("<red>Incorrect usage of command<gray> - " + schematic.first()));
return;
}

sender.sendMessage(MINI_MESSAGE.deserialize("<red>Incorrect usage of command"));
for (String rawSchematic : schematic.all()) {
sender.sendMessage(MINI_MESSAGE.deserialize("<gray> - " + rawSchematic));
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dev.rollczi.example.minestom.handler;

import dev.rollczi.litecommands.handler.result.ResultHandlerChain;
import dev.rollczi.litecommands.invocation.Invocation;
import dev.rollczi.litecommands.permission.MissingPermissions;
import dev.rollczi.litecommands.permission.MissingPermissionsHandler;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.minestom.server.command.CommandSender;

public class MyPermissionMessage implements MissingPermissionsHandler<CommandSender> {

private static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage();

@Override
public void handle(Invocation<CommandSender> invocation, MissingPermissions missingPermissions, ResultHandlerChain<CommandSender> chain) {
CommandSender commandSource = invocation.sender();
TagResolver.Single permission = Placeholder.parsed("permission", missingPermissions.asJoinedText());

commandSource.sendMessage(MINI_MESSAGE.deserialize("<red>You don't have permission to use this command! (<permission>)", permission));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ protected ParseResult<String> parse(Invocation<SENDER> invocation, Argument<Stri

@Override
public SuggestionResult suggest(Invocation<SENDER> invocation, Argument<String> objectStringArgument, SuggestionContext context) {
String first = context.getCurrent().firstLevel();
String first = context.getCurrent().multilevel();
return SuggestionResult.of("<" + objectStringArgument.getName() + ">", first);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,27 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.intellij.lang.annotations.MagicConstant;

public class MessageRegistry<SENDER> {

private final Map<MessageKey<?>, Message<?, ?>> messages = new HashMap<>();
private final Map<MessageKey<?>, InvokedMessage<SENDER, ?, ?>> invokedMessages = new HashMap<>();

public <T, CONTEXT> void register(MessageKey<CONTEXT> key, Message<T, CONTEXT> message) {
public <T, CONTEXT> void register(@MagicConstant(valuesFromClass = LiteMessages.class) MessageKey<CONTEXT> key, Message<T, CONTEXT> message) {
messages.put(key, message);
}

public <T, CONTEXT> void register(MessageKey<CONTEXT> key, InvokedMessage<SENDER, T, CONTEXT> message) {
public <T, CONTEXT> void register(@MagicConstant(valuesFromClass = LiteMessages.class) MessageKey<CONTEXT> key, InvokedMessage<SENDER, T, CONTEXT> message) {
invokedMessages.put(key, message);
}

public Optional<Object> getInvoked(MessageKey<Void> key, Invocation<SENDER> invocation) {
public Optional<Object> getInvoked(@MagicConstant(valuesFromClass = LiteMessages.class) MessageKey<Void> key, Invocation<SENDER> invocation) {
return getInvoked(key, invocation, null);
}

@SuppressWarnings("unchecked")
public <CONTEXT> Optional<Object> getInvoked(MessageKey<CONTEXT> key, Invocation<SENDER> invocation, CONTEXT context) {
public <CONTEXT> Optional<Object> getInvoked(@MagicConstant(valuesFromClass = LiteMessages.class) MessageKey<CONTEXT> key, Invocation<SENDER> invocation, CONTEXT context) {
InvokedMessage<SENDER, ?, CONTEXT> invokedMessage = (InvokedMessage<SENDER, ?, CONTEXT>) invokedMessages.get(key);

if (invokedMessage != null) {
Expand All @@ -36,7 +37,7 @@ public <CONTEXT> Optional<Object> getInvoked(MessageKey<CONTEXT> key, Invocation

@SuppressWarnings("unchecked")
@Deprecated
public <CONTEXT> Optional<Object> get(MessageKey<CONTEXT> key, CONTEXT context) {
public <CONTEXT> Optional<Object> get(@MagicConstant(valuesFromClass = LiteMessages.class) MessageKey<CONTEXT> key, CONTEXT context) {
Message<?, CONTEXT> message = (Message<?, CONTEXT>) messages.get(key);

if (message == null) {
Expand All @@ -47,7 +48,7 @@ public <CONTEXT> Optional<Object> get(MessageKey<CONTEXT> key, CONTEXT context)
}

@Deprecated
public Optional<Object> get(MessageKey<Void> key) {
public Optional<Object> get(@MagicConstant(valuesFromClass = LiteMessages.class) MessageKey<Void> key) {
return get(key, null);
}

Expand Down
5 changes: 3 additions & 2 deletions litecommands-minestom/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ plugins {

dependencies {
api(project(":litecommands-framework"))
api(project(":litecommands-adventure"))
testImplementation(project(":litecommands-annotations"))
compileOnly("dev.hollowcube:minestom-ce:438338381e")
testImplementation("dev.hollowcube:minestom-ce:438338381e")
compileOnly("dev.hollowcube:minestom-ce:5347c0b11f")
testImplementation("dev.hollowcube:minestom-ce:5347c0b11f")
}

litecommandsPublish {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,49 @@

import dev.rollczi.litecommands.LiteCommandsFactory;
import dev.rollczi.litecommands.LiteCommandsBuilder;
import dev.rollczi.litecommands.adventure.LiteAdventureExtension;
import dev.rollczi.litecommands.message.MessageRegistry;
import dev.rollczi.litecommands.minestom.argument.InstanceArgument;
import dev.rollczi.litecommands.minestom.argument.PlayerArgument;
import dev.rollczi.litecommands.minestom.context.InstanceContext;
import dev.rollczi.litecommands.minestom.context.PlayerContext;
import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandManager;
import net.minestom.server.command.CommandSender;
import net.minestom.server.entity.Player;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.InstanceManager;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.socket.Server;

public final class LiteMinestomFactory {

private LiteMinestomFactory() {
}

public static LiteCommandsBuilder<CommandSender, LiteMinestomSettings, ?> builder(Server server, CommandManager commandManager) {
return LiteCommandsFactory.builder(CommandSender.class, new MinestomPlatform(commandManager))
.bind(Server.class, () -> server);
public static LiteCommandsBuilder<CommandSender, LiteMinestomSettings, ?> builder() {
return builder(MinecraftServer.getServer(), MinecraftServer.getInstanceManager(), MinecraftServer.getConnectionManager(), MinecraftServer.getCommandManager());
}

public static LiteCommandsBuilder<CommandSender, LiteMinestomSettings, ?> builder(
Server server,
InstanceManager instanceManager,
ConnectionManager connectionManager,
CommandManager commandManager
) {
return LiteCommandsFactory.builder(CommandSender.class, new MinestomPlatform(commandManager)).selfProcessor((builder, internal) -> {
MessageRegistry<CommandSender> messageRegistry = internal.getMessageRegistry();

builder
.extension(new LiteAdventureExtension<>(), configuration -> configuration
.legacyColor(true)
)
.argument(Player.class, new PlayerArgument(connectionManager, messageRegistry))
.argument(Instance.class, new InstanceArgument(instanceManager, messageRegistry))
.context(Player.class, new PlayerContext(messageRegistry))
.context(Instance.class, new InstanceContext(messageRegistry))
.bind(Server.class, () -> server);
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package dev.rollczi.litecommands.minestom;

import dev.rollczi.litecommands.message.LiteMessages;
import dev.rollczi.litecommands.message.MessageKey;
import net.minestom.server.entity.Player;

public class LiteMinestomMessages extends LiteMessages {

public static final MessageKey<Player> PLAYER_IS_NOT_IN_INSTANCE = MessageKey.of(
"player-is-not-in-instance",
player -> "&cPlayer " + player.getUsername() + " is not in instance! (PLAYER_IS_NOT_IN_INSTANCE)"
);

public static final MessageKey<String> INSTANCE_NOT_FOUND = MessageKey.of(
"instance-not-found",
input -> "&cInstance " + input + " not found! (INSTANCE_NOT_FOUND)"
);

public static final MessageKey<String> PLAYER_NOT_FOUND = MessageKey.of(
"player-not-found",
input -> "&cPlayer " + input + " not found! (PLAYER_NOT_FOUND)"
);

public static final MessageKey<Void> PLAYER_ONLY = MessageKey.of(
"only-player",
unused -> "&cOnly player can execute this command! (PLAYER_ONLY)"
);

}
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
package dev.rollczi.litecommands.minestom;

import dev.rollczi.litecommands.platform.PlatformSettings;
import org.jetbrains.annotations.ApiStatus;

public class LiteMinestomSettings implements PlatformSettings {

private boolean nativePermission = false;

@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "3.4.0")
public LiteMinestomSettings nativePermission(boolean nativePermission) {
this.nativePermission = nativePermission;
return this;
}

boolean isNativePermission() {
return nativePermission;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import dev.rollczi.litecommands.platform.PlatformSuggestionListener;
import dev.rollczi.litecommands.suggestion.Suggestion;
import dev.rollczi.litecommands.argument.suggester.input.SuggestionInput;
import dev.rollczi.litecommands.util.StringUtil;
import net.kyori.adventure.text.Component;
import net.minestom.server.command.CommandSender;
import net.minestom.server.command.builder.Command;
Expand Down Expand Up @@ -39,6 +40,11 @@ class MinestomCommand extends Command {
Invocation<CommandSender> invocation = this.createInvocation(sender, alias, input);
Set<Suggestion> suggestions = this.suggestionListener.suggest(invocation, input).getSuggestions();

if (suggestions.isEmpty()) {
suggestionCallback.addEntry(new SuggestionEntry(StringUtil.EMPTY));
return;
}

for (Suggestion suggestion : suggestions) {
suggestionCallback.addEntry(new SuggestionEntry(suggestion.multilevel(), Component.empty()));
}
Expand Down
Loading

0 comments on commit 8c81f44

Please sign in to comment.