Skip to content

Commit

Permalink
Add Console/CommandBlock support to Fabric/Forge/Sponge (#2317)
Browse files Browse the repository at this point in the history
* Add Console/CommandBlock support to Fabric/Forge

* Hoist config option and add a common abstract class for command block actors

* Apply to Sponge too
  • Loading branch information
me4502 committed Jun 9, 2023
1 parent bb15dbc commit 40a203c
Show file tree
Hide file tree
Showing 19 changed files with 976 additions and 54 deletions.
Expand Up @@ -20,11 +20,8 @@
package com.sk89q.worldedit.bukkit;

import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.platform.AbstractNonPlayerActor;
import com.sk89q.worldedit.extension.platform.Locatable;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extension.platform.AbstractCommandBlockActor;
import com.sk89q.worldedit.session.SessionKey;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.auth.AuthorizationException;
import com.sk89q.worldedit.util.formatting.WorldEditText;
import com.sk89q.worldedit.util.formatting.text.Component;
Expand All @@ -42,22 +39,17 @@

import static com.google.common.base.Preconditions.checkNotNull;

public class BukkitBlockCommandSender extends AbstractNonPlayerActor implements Locatable {

private static final String UUID_PREFIX = "CMD";

public class BukkitBlockCommandSender extends AbstractCommandBlockActor {
private final BlockCommandSender sender;
private final WorldEditPlugin plugin;
private final Location location;
private final UUID uuid;

public BukkitBlockCommandSender(WorldEditPlugin plugin, BlockCommandSender sender) {
super(BukkitAdapter.adapt(checkNotNull(sender).getBlock().getLocation()));
checkNotNull(plugin);
checkNotNull(sender);

this.plugin = plugin;
this.sender = sender;
this.location = BukkitAdapter.adapt(sender.getBlock().getLocation());
this.uuid = UUID.nameUUIDFromBytes((UUID_PREFIX + sender.getName()).getBytes(StandardCharsets.UTF_8));
}

Expand Down Expand Up @@ -108,21 +100,6 @@ public Locale getLocale() {
return WorldEdit.getInstance().getConfiguration().defaultLocale;
}

@Override
public Location getLocation() {
return this.location;
}

@Override
public boolean setLocation(Location location) {
return false;
}

@Override
public Extent getExtent() {
return this.location.getExtent();
}

@Override
public UUID getUniqueId() {
return uuid;
Expand Down
Expand Up @@ -34,7 +34,6 @@
public class BukkitConfiguration extends YAMLConfiguration {

public boolean noOpPermissions = false;
public boolean commandBlockSupport = false;
public boolean unsupportedVersionEditing = false;
@Unreported private final WorldEditPlugin plugin;

Expand All @@ -47,7 +46,6 @@ public BukkitConfiguration(YAMLProcessor config, WorldEditPlugin plugin) {
public void load() {
super.load();
noOpPermissions = config.getBoolean("no-op-permissions", false);
commandBlockSupport = config.getBoolean("command-block-support", false);
unsupportedVersionEditing = "I accept that I will receive no support with this flag enabled.".equals(
config.getString("allow-editing-on-unsupported-versions", "false"));
if (unsupportedVersionEditing) {
Expand Down
Expand Up @@ -91,6 +91,7 @@ public abstract class LocalConfiguration {
public boolean allowSymlinks = false;
public boolean serverSideCUI = true;
public boolean extendedYLimit = false;
public boolean commandBlockSupport = false;
public String defaultLocaleName = "default";
public Locale defaultLocale = Locale.getDefault();

Expand Down
@@ -0,0 +1,49 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit 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.sk89q.worldedit.extension.platform;

import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.util.Location;

public abstract class AbstractCommandBlockActor extends AbstractNonPlayerActor implements Locatable {
protected static final String UUID_PREFIX = "CMD";

private final Location location;

public AbstractCommandBlockActor(Location location) {
this.location = location;
}

@Override
public Location getLocation() {
return this.location;
}

@Override
public boolean setLocation(Location location) {
// Can't move a CommandBlock
return false;
}

@Override
public Extent getExtent() {
return this.location.getExtent();
}
}
Expand Up @@ -133,6 +133,7 @@ public void load() {
serverSideCUI = getBool("server-side-cui", serverSideCUI);
extendedYLimit = getBool("extended-y-limit", extendedYLimit);
setDefaultLocaleName(getString("default-locale", defaultLocaleName));
commandBlockSupport = getBool("command-block-support", commandBlockSupport);

LocalSession.MAX_HISTORY_SIZE = Math.max(15, getInt("history-size", 15));

Expand Down
Expand Up @@ -129,6 +129,8 @@ public void load() {
extendedYLimit = config.getBoolean("compat.extended-y-limit", false);

setDefaultLocaleName(config.getString("default-locale", defaultLocaleName));

commandBlockSupport = config.getBoolean("command-block-support", false);
}

public void unload() {
Expand Down
Expand Up @@ -35,8 +35,6 @@
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.util.Substring;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import org.enginehub.piston.inject.InjectedValueStore;
import org.enginehub.piston.inject.Key;
import org.enginehub.piston.inject.MapBackedValueStore;
Expand All @@ -46,7 +44,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;

import static com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer;
import static com.sk89q.worldedit.fabric.FabricAdapter.adaptCommandSource;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;

Expand All @@ -62,7 +60,7 @@ public static void register(CommandDispatcher<CommandSourceStack> dispatcher, or

Command<CommandSourceStack> commandRunner = ctx -> {
WorldEdit.getInstance().getEventBus().post(new com.sk89q.worldedit.event.platform.CommandEvent(
adaptPlayer(ctx.getSource().getPlayerOrException()),
adaptCommandSource(ctx.getSource()),
"/" + ctx.getInput()
));
return 0;
Expand All @@ -82,12 +80,8 @@ public static void register(CommandDispatcher<CommandSourceStack> dispatcher, or

private static Predicate<CommandSourceStack> requirementsFor(org.enginehub.piston.Command mapping) {
return ctx -> {
final Entity entity = ctx.getEntity();
if (!(entity instanceof ServerPlayer)) {
return true;
}
final Actor actor = FabricAdapter.adaptPlayer(((ServerPlayer) entity));
InjectedValueStore store = MapBackedValueStore.create();
final Actor actor = FabricAdapter.adaptCommandSource(ctx);
store.injectValue(Key.of(Actor.class), context -> Optional.of(actor));
return mapping.getCondition().satisfied(store);
};
Expand All @@ -96,7 +90,7 @@ private static Predicate<CommandSourceStack> requirementsFor(org.enginehub.pisto
private static CompletableFuture<Suggestions> suggest(CommandContext<CommandSourceStack> context,
SuggestionsBuilder builder) throws CommandSyntaxException {
CommandSuggestionEvent event = new CommandSuggestionEvent(
FabricAdapter.adaptPlayer(context.getSource().getPlayerOrException()),
FabricAdapter.adaptCommandSource(context.getSource()),
builder.getInput()
);
WorldEdit.getInstance().getEventBus().post(event);
Expand Down
Expand Up @@ -22,6 +22,7 @@
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.fabric.internal.FabricTransmogrifier;
import com.sk89q.worldedit.fabric.internal.NBTConverter;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
Expand All @@ -37,15 +38,15 @@
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BaseCommandBlock;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
Expand Down Expand Up @@ -248,4 +249,22 @@ public static FabricPlayer adaptPlayer(ServerPlayer player) {
checkNotNull(player);
return new FabricPlayer(player);
}

/**
* Get the WorldEdit proxy for the given command source.
*
* @param commandSourceStack the command source
* @return the WorldEdit actor
*/
public static Actor adaptCommandSource(CommandSourceStack commandSourceStack) {
checkNotNull(commandSourceStack);
if (commandSourceStack.isPlayer()) {
return adaptPlayer(commandSourceStack.getPlayer());
}
if (FabricWorldEdit.inst.getConfig().commandBlockSupport && commandSourceStack.source instanceof BaseCommandBlock commandBlock) {
return new FabricBlockCommandSender(commandBlock);
}

return new FabricCommandSender(commandSourceStack);
}
}

0 comments on commit 40a203c

Please sign in to comment.