Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: use cloud v2 for commands #4283

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
4 changes: 4 additions & 0 deletions Bukkit/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ dependencies {

// Adventure
implementation(libs.adventureBukkit)

// Cloud
implementation(libs.cloudPaper)
}

tasks.processResources {
Expand All @@ -77,6 +80,7 @@ tasks.named<ShadowJar>("shadowJar") {
relocate("com.google.inject", "com.plotsquared.google")
relocate("org.aopalliance", "com.plotsquared.core.aopalliance")
relocate("cloud.commandframework.services", "com.plotsquared.core.services")
relocate("cloud.commandframework", "com.plotsquared.commands")
relocate("io.leangen.geantyref", "com.plotsquared.core.geantyref")
relocate("com.intellectualsites.arkitektonika", "com.plotsquared.core.arkitektonika")
relocate("com.intellectualsites.http", "com.plotsquared.core.http")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.plotsquared.bukkit.generator.BukkitPlotGenerator;
import com.plotsquared.bukkit.inject.BackupModule;
import com.plotsquared.bukkit.inject.BukkitModule;
import com.plotsquared.bukkit.inject.CloudModule;
import com.plotsquared.bukkit.inject.PermissionModule;
import com.plotsquared.bukkit.inject.WorldManagerModule;
import com.plotsquared.bukkit.listener.BlockEventListener;
Expand Down Expand Up @@ -64,6 +65,7 @@
import com.plotsquared.core.PlotPlatform;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.backup.BackupManager;
import com.plotsquared.core.commands.PlotSquaredCommandManager;
import com.plotsquared.core.components.ComponentPresetManager;
import com.plotsquared.core.configuration.ConfigurationNode;
import com.plotsquared.core.configuration.ConfigurationSection;
Expand All @@ -83,6 +85,7 @@
import com.plotsquared.core.inject.annotations.ImpromptuPipeline;
import com.plotsquared.core.inject.annotations.WorldConfig;
import com.plotsquared.core.inject.annotations.WorldFile;
import com.plotsquared.core.inject.modules.CommandModule;
import com.plotsquared.core.inject.modules.PlotSquaredModule;
import com.plotsquared.core.listener.PlotListener;
import com.plotsquared.core.listener.WESubscriber;
Expand Down Expand Up @@ -293,6 +296,8 @@ public void onEnable() {
new PermissionModule(),
new WorldManagerModule(),
new PlotSquaredModule(),
new CommandModule(),
new CloudModule(this),
new BukkitModule(this),
new BackupModule()
);
Expand Down Expand Up @@ -388,6 +393,8 @@ public void onEnable() {
// Commands
if (Settings.Enabled_Components.COMMANDS) {
this.registerCommands();
// Register the commands.
this.injector().getInstance(PlotSquaredCommandManager.class).registerDefaultCommands();
}

// Permissions
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.bukkit.commands;

import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.core.player.ConsolePlayer;
import com.plotsquared.core.player.PlotPlayer;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.SenderMapper;

/**
* Mapper between {@link CommandSender} and {@link PlotPlayer}.
*/
public final class BukkitSenderMapper implements SenderMapper<CommandSender, PlotPlayer<?>> {

@Override
public @NonNull PlotPlayer<?> map(final @NonNull CommandSender base) {
if (base instanceof Player player) {
return BukkitUtil.adapt(player);
}
return ConsolePlayer.getConsole();
}

@Override
public @NonNull CommandSender reverse(final @NonNull PlotPlayer<?> mapped) {
if (mapped instanceof ConsolePlayer) {
return Bukkit.getConsoleSender();
}
return (Player) mapped.getPlatformPlayer();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.bukkit.inject;

import com.google.inject.AbstractModule;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.plotsquared.bukkit.BukkitPlatform;
import com.plotsquared.bukkit.commands.BukkitSenderMapper;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.core.commands.CommandRequirement;
import com.plotsquared.core.commands.PlotSquaredCaptionProvider;
import com.plotsquared.core.commands.PlotSquaredRequirementFailureHandler;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.player.ConsolePlayer;
import com.plotsquared.core.player.PlotPlayer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.bukkit.CloudBukkitCapabilities;
import org.incendo.cloud.execution.ExecutionCoordinator;
import org.incendo.cloud.minecraft.extras.MinecraftExceptionHandler;
import org.incendo.cloud.paper.PaperCommandManager;
import org.incendo.cloud.processors.requirements.RequirementPostprocessor;

public class CloudModule extends AbstractModule {

private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + CloudModule.class.getSimpleName());

private static @NonNull CommandSender convert(final @NonNull PlotPlayer<?> player) {
if (player instanceof ConsolePlayer) {
return Bukkit.getConsoleSender();
}
return (Player) player.getPlatformPlayer();
}

private static @NonNull PlotPlayer<?> convert (final @NonNull CommandSender sender) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove these now that we have the sender mapper

if (sender instanceof Player player) {
return BukkitUtil.adapt(player);
}
return ConsolePlayer.getConsole();
}

private final BukkitPlatform bukkitPlatform;

public CloudModule(final @NonNull BukkitPlatform bukkitPlatform) {
this.bukkitPlatform = bukkitPlatform;
}

@Override
protected void configure() {
final PaperCommandManager<PlotPlayer<?>> commandManager = new PaperCommandManager<PlotPlayer<?>>(
this.bukkitPlatform,
ExecutionCoordinator.asyncCoordinator(),
new BukkitSenderMapper()
);
commandManager.captionRegistry().registerProvider(new PlotSquaredCaptionProvider());

if (commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
commandManager.registerBrigadier();
} else if (commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
commandManager.registerAsynchronousCompletions();
}

final RequirementPostprocessor<PlotPlayer<?>, CommandRequirement> requirementPostprocessor =
RequirementPostprocessor.of(CommandRequirement.REQUIREMENTS_KEY, new PlotSquaredRequirementFailureHandler());
commandManager.registerCommandPostProcessor(requirementPostprocessor);

// TODO(City): Override parsing errors using MM parsing.
MinecraftExceptionHandler.<PlotPlayer<?>>create(PlotPlayer::getAudience)
.defaultHandlers()
.decorator((ctx, component) -> TranslatableCaption.of("core.prefix").
toComponent(ctx.context().sender())
.append(component))
.registerTo(commandManager);

bind(Key.get(new TypeLiteral<CommandManager<PlotPlayer<?>>>() {})).toInstance(commandManager);
}
}
5 changes: 5 additions & 0 deletions Core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ dependencies {
api(libs.adventureApi)
api(libs.adventureMiniMessage)

// Cloud
api(libs.cloud)
api(libs.cloudMinecraftExtras)
api(libs.cloudRequirements)

// Guice
api(libs.guice) {
exclude(group = "com.google.guava")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/
package com.plotsquared.core;

import cloud.commandframework.services.ServicePipeline;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
Expand Down Expand Up @@ -47,6 +46,7 @@
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.incendo.cloud.services.ServicePipeline;

import java.io.File;

Expand Down
4 changes: 2 additions & 2 deletions Core/src/main/java/com/plotsquared/core/command/Auto.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/
package com.plotsquared.core.command;

import cloud.commandframework.services.ServicePipeline;
import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings;
Expand Down Expand Up @@ -49,6 +48,7 @@
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.incendo.cloud.services.ServicePipeline;

import java.util.Collections;
import java.util.Iterator;
Expand Down Expand Up @@ -332,7 +332,7 @@ public boolean onCommand(final PlotPlayer<?> player, String[] args) {
List<Plot> plots = this.servicePipeline
.pump(new AutoQuery(player, null, sizeX, sizeZ, plotarea))
.through(AutoService.class)
.getResult();
.complete();

plots = this.eventDispatcher.callAutoPlotsChosen(player, plots).getPlots();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands;

import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import io.leangen.geantyref.TypeToken;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.key.CloudKey;
import org.incendo.cloud.processors.requirements.Requirement;
import org.incendo.cloud.processors.requirements.Requirements;

import java.util.List;

/**
* Something that is required for a command to be executed.
*/
public interface CommandRequirement extends Requirement<PlotPlayer<?>, CommandRequirement> {

/**
* The key used to store the requirements in the {@link org.incendo.cloud.meta.CommandMeta}.
*/
CloudKey<Requirements<PlotPlayer<?>, CommandRequirement>> REQUIREMENTS_KEY = CloudKey.of(
"requirements",
new TypeToken<Requirements<PlotPlayer<?>, CommandRequirement>>() {
}
);

/**
* Returns the caption sent when the requirement is not met.
*
* @return the caption
*/
@NonNull TranslatableCaption failureCaption();

/**
* Returns the placeholder values.
*
* @return placeholder values
*/
default @NonNull TagResolver @NonNull[] tagResolvers() {
return new TagResolver[0];
}

/**
* Returns a requirement that evaluates to {@code true} if the sender has the given {@code permission} or if
* this requirement evaluates to {@code true}.
*
* @param permission the override permission
* @return the new requirement
*/
default @NonNull CommandRequirement withPermissionOverride(final @NonNull Permission permission) {
final CommandRequirement thisRequirement = this;
return new CommandRequirement() {
@Override
public @NonNull TranslatableCaption failureCaption() {
return TranslatableCaption.of("permission.no_permission");
}

@Override
public @NonNull TagResolver @NonNull [] tagResolvers() {
return new TagResolver[] {
TagResolver.resolver("node", Tag.inserting(Permission.PERMISSION_SET_FLAG_OTHER))
};
}

@Override
public @NonNull List<@NonNull CommandRequirement> parents() {
return thisRequirement.parents();
}

@Override
public boolean evaluateRequirement(final @NonNull CommandContext<PlotPlayer<?>> context) {
return context.sender().hasPermission(permission) || thisRequirement.evaluateRequirement(context);
}
};
}
}
Loading
Loading