mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 01:37:37 +00:00
Merge pull request #464 from EngineHub/feature/piston-commands
Piston command system.
This commit is contained in:
commit
b47c70025e
@ -78,6 +78,11 @@ subprojects {
|
||||
maven { url "http://maven.sk89q.com/repo/" }
|
||||
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||
}
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
cacheChangingModulesFor 5, 'minutes'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configure(['core', 'bukkit', 'forge', 'sponge'].collect { project(":worldedit-$it") }) {
|
||||
|
@ -53,5 +53,13 @@
|
||||
<!-- <module name="PackageName"/> Unlikely that we would miss this in a PR -->
|
||||
<module name="ParameterName"/>
|
||||
<!-- <module name="TypeName"/> Unlikely that we would miss this in a PR -->
|
||||
<!-- Validate assignment operators -->
|
||||
<module name="WhitespaceAround">
|
||||
<property name="tokens" value="ASSIGN"/>
|
||||
</module>
|
||||
</module>
|
||||
<!-- Validate that command annotations are formatted correctly -->
|
||||
<module name="RegexpMultiline">
|
||||
<property name="format" value="^( +)@(Arg|Switch|Command)\(.*?\n\1 {5,}"/>
|
||||
</module>
|
||||
</module>
|
||||
|
@ -16,6 +16,7 @@
|
||||
<allow pkg="net.royawesome.jlibnoise"/>
|
||||
<allow pkg="org.json.simple" />
|
||||
<allow pkg="org.slf4j"/>
|
||||
<allow pkg="org.enginehub"/>
|
||||
|
||||
<subpackage name="util.yaml">
|
||||
<allow pkg="org.yaml.snakeyaml"/>
|
||||
@ -38,6 +39,7 @@
|
||||
<subpackage name="worldedit">
|
||||
<allow pkg="org.mozilla.javascript"/>
|
||||
<allow pkg="de.schlichtherle"/>
|
||||
<allow pkg="com.google.auto"/>
|
||||
|
||||
<subpackage name="bukkit">
|
||||
<allow pkg="org.bukkit"/>
|
||||
|
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,6 @@
|
||||
#Thu Mar 14 00:19:48 PDT 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip
|
||||
|
@ -6,3 +6,4 @@ include 'worldedit-libs'
|
||||
include "worldedit-libs:$it"
|
||||
include "worldedit-$it"
|
||||
}
|
||||
include "worldedit-libs:core:ap"
|
||||
|
@ -8,6 +8,12 @@ repositories {
|
||||
maven { url 'https://papermc.io/repo/repository/maven-public/' }
|
||||
}
|
||||
|
||||
configurations.all { Configuration it ->
|
||||
it.resolutionStrategy { ResolutionStrategy rs ->
|
||||
rs.force("com.google.guava:guava:21.0")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':worldedit-core')
|
||||
compile project(':worldedit-libs:bukkit')
|
||||
|
@ -31,6 +31,8 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings("deprecation")
|
||||
public class CommandsManagerRegistration extends CommandRegistration {
|
||||
|
||||
protected CommandsManager<?> commands;
|
||||
|
@ -35,6 +35,7 @@ import java.util.List;
|
||||
/**
|
||||
* An implementation of a dynamically registered {@link org.bukkit.command.Command} attached to a plugin
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DynamicPluginCommand extends org.bukkit.command.Command implements PluginIdentifiableCommand {
|
||||
|
||||
protected final CommandExecutor owner;
|
||||
|
@ -30,6 +30,7 @@ import org.bukkit.help.HelpTopicFactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DynamicPluginCommandHelpTopic extends HelpTopic {
|
||||
|
||||
private final DynamicPluginCommand cmd;
|
||||
|
@ -20,25 +20,31 @@
|
||||
package com.sk89q.worldedit.bukkit;
|
||||
|
||||
import com.sk89q.bukkit.util.CommandInspector;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.util.command.CommandMapping;
|
||||
import com.sk89q.worldedit.util.command.Description;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.CommandParameters;
|
||||
import org.enginehub.piston.NoInputCommandParameters;
|
||||
import org.enginehub.piston.inject.InjectedValueStore;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
import org.enginehub.piston.inject.MapBackedValueStore;
|
||||
import org.enginehub.piston.inject.MemoizingValueAccess;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldedit.bukkit.BukkitTextAdapter.reduceToText;
|
||||
|
||||
class BukkitCommandInspector implements CommandInspector {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(BukkitCommandInspector.class);
|
||||
private final WorldEditPlugin plugin;
|
||||
private final Dispatcher dispatcher;
|
||||
private final CommandManager dispatcher;
|
||||
|
||||
BukkitCommandInspector(WorldEditPlugin plugin, Dispatcher dispatcher) {
|
||||
BukkitCommandInspector(WorldEditPlugin plugin, CommandManager dispatcher) {
|
||||
checkNotNull(plugin);
|
||||
checkNotNull(dispatcher);
|
||||
this.plugin = plugin;
|
||||
@ -47,9 +53,9 @@ class BukkitCommandInspector implements CommandInspector {
|
||||
|
||||
@Override
|
||||
public String getShortText(Command command) {
|
||||
CommandMapping mapping = dispatcher.get(command.getName());
|
||||
if (mapping != null) {
|
||||
return mapping.getDescription().getDescription();
|
||||
Optional<org.enginehub.piston.Command> mapping = dispatcher.getCommand(command.getName());
|
||||
if (mapping.isPresent()) {
|
||||
return reduceToText(mapping.get().getDescription());
|
||||
} else {
|
||||
logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'");
|
||||
return "Help text not available";
|
||||
@ -58,10 +64,9 @@ class BukkitCommandInspector implements CommandInspector {
|
||||
|
||||
@Override
|
||||
public String getFullText(Command command) {
|
||||
CommandMapping mapping = dispatcher.get(command.getName());
|
||||
if (mapping != null) {
|
||||
Description description = mapping.getDescription();
|
||||
return "Usage: " + description.getUsage() + (description.getHelp() != null ? "\n" + description.getHelp() : "");
|
||||
Optional<org.enginehub.piston.Command> mapping = dispatcher.getCommand(command.getName());
|
||||
if (mapping.isPresent()) {
|
||||
return reduceToText(mapping.get().getFullHelp());
|
||||
} else {
|
||||
logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'");
|
||||
return "Help text not available";
|
||||
@ -70,11 +75,15 @@ class BukkitCommandInspector implements CommandInspector {
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandSender sender, Command command) {
|
||||
CommandMapping mapping = dispatcher.get(command.getName());
|
||||
if (mapping != null) {
|
||||
CommandLocals locals = new CommandLocals();
|
||||
locals.put(Actor.class, plugin.wrapCommandSender(sender));
|
||||
return mapping.getCallable().testPermission(locals);
|
||||
Optional<org.enginehub.piston.Command> mapping = dispatcher.getCommand(command.getName());
|
||||
if (mapping.isPresent()) {
|
||||
InjectedValueStore store = MapBackedValueStore.create();
|
||||
store.injectValue(Key.of(Actor.class), context ->
|
||||
Optional.of(plugin.wrapCommandSender(sender)));
|
||||
CommandParameters parameters = NoInputCommandParameters.builder()
|
||||
.injectedValues(MemoizingValueAccess.wrap(store))
|
||||
.build();
|
||||
return mapping.get().getCondition().satisfied(parameters);
|
||||
} else {
|
||||
logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'");
|
||||
return false;
|
||||
|
@ -26,7 +26,7 @@ import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.auth.AuthorizationException;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -94,7 +94,7 @@ public class BukkitCommandSender implements Actor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(TextComponent component) {
|
||||
public void print(Component component) {
|
||||
TextAdapter.sendComponent(sender, component);
|
||||
}
|
||||
|
||||
|
@ -31,13 +31,13 @@ import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.HandSide;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.gamemode.GameMode;
|
||||
import com.sk89q.worldedit.world.gamemode.GameModes;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@ -127,7 +127,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(TextComponent component) {
|
||||
public void print(Component component) {
|
||||
TextAdapter.sendComponent(player, component);
|
||||
}
|
||||
|
||||
|
@ -22,27 +22,29 @@ package com.sk89q.worldedit.bukkit;
|
||||
import com.sk89q.bukkit.util.CommandInfo;
|
||||
import com.sk89q.bukkit.util.CommandRegistration;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.command.util.PermissionCondition;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
|
||||
import com.sk89q.worldedit.extension.platform.Preference;
|
||||
import com.sk89q.worldedit.util.command.CommandMapping;
|
||||
import com.sk89q.worldedit.util.command.Description;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import com.sk89q.worldedit.world.registry.Registries;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import static com.sk89q.worldedit.bukkit.BukkitTextAdapter.reduceToText;
|
||||
|
||||
public class BukkitServerInterface implements MultiUserPlatform {
|
||||
public Server server;
|
||||
@ -70,7 +72,7 @@ public class BukkitServerInterface implements MultiUserPlatform {
|
||||
if (plugin.getBukkitImplAdapter() != null) {
|
||||
return plugin.getBukkitImplAdapter().getDataVersion();
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -124,20 +126,25 @@ public class BukkitServerInterface implements MultiUserPlatform {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCommands(Dispatcher dispatcher) {
|
||||
List<CommandInfo> toRegister = new ArrayList<>();
|
||||
public void registerCommands(CommandManager dispatcher) {
|
||||
BukkitCommandInspector inspector = new BukkitCommandInspector(plugin, dispatcher);
|
||||
|
||||
for (CommandMapping command : dispatcher.getCommands()) {
|
||||
Description description = command.getDescription();
|
||||
List<String> permissions = description.getPermissions();
|
||||
String[] permissionsArray = new String[permissions.size()];
|
||||
permissions.toArray(permissionsArray);
|
||||
dynamicCommands.register(dispatcher.getAllCommands()
|
||||
.map(command -> {
|
||||
String[] permissionsArray = command.getCondition()
|
||||
.as(PermissionCondition.class)
|
||||
.map(PermissionCondition::getPermissions)
|
||||
.map(s -> s.toArray(new String[0]))
|
||||
.orElseGet(() -> new String[0]);
|
||||
|
||||
toRegister.add(new CommandInfo(description.getUsage(), description.getDescription(), command.getAllAliases(), inspector, permissionsArray));
|
||||
}
|
||||
|
||||
dynamicCommands.register(toRegister);
|
||||
String[] aliases = Stream.concat(
|
||||
Stream.of(command.getName()),
|
||||
command.getAliases().stream()
|
||||
).toArray(String[]::new);
|
||||
return new CommandInfo(reduceToText(command.getUsage()),
|
||||
reduceToText(command.getDescription()), aliases,
|
||||
inspector, permissionsArray);
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.bukkit;
|
||||
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||
|
||||
public class BukkitTextAdapter {
|
||||
|
||||
public static String reduceToText(Component component) {
|
||||
StringBuilder text = new StringBuilder();
|
||||
appendTextTo(text, component);
|
||||
return text.toString();
|
||||
}
|
||||
|
||||
private static void appendTextTo(StringBuilder builder, Component component) {
|
||||
if (component instanceof TextComponent) {
|
||||
builder.append(((TextComponent) component).content());
|
||||
} else if (component instanceof TranslatableComponent) {
|
||||
builder.append(((TranslatableComponent) component).key());
|
||||
}
|
||||
for (Component child : component.children()) {
|
||||
appendTextTo(builder, child);
|
||||
}
|
||||
}
|
||||
|
||||
private BukkitTextAdapter() {
|
||||
}
|
||||
|
||||
}
|
@ -21,13 +21,11 @@
|
||||
|
||||
package com.sk89q.worldedit.bukkit;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.command.CommandMapping;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.Event.Result;
|
||||
@ -40,9 +38,15 @@ import org.bukkit.event.player.PlayerCommandSendEvent;
|
||||
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.CommandParameters;
|
||||
import org.enginehub.piston.NoInputCommandParameters;
|
||||
import org.enginehub.piston.inject.InjectedValueStore;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
import org.enginehub.piston.inject.MapBackedValueStore;
|
||||
import org.enginehub.piston.inject.MemoizingValueAccess;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Handles all events thrown in relation to a Player
|
||||
@ -87,7 +91,7 @@ public class WorldEditListener implements Listener {
|
||||
|
||||
if (split.length > 0) {
|
||||
split[0] = split[0].substring(1);
|
||||
split = plugin.getWorldEdit().getPlatformManager().getCommandManager().commandDetection(split);
|
||||
split = plugin.getWorldEdit().getPlatformManager().getPlatformCommandManager().commandDetection(split);
|
||||
}
|
||||
|
||||
final String newMessage = "/" + StringUtil.joinString(split, " ");
|
||||
@ -108,13 +112,19 @@ public class WorldEditListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onPlayerCommand(PlayerCommandSendEvent event) {
|
||||
CommandLocals locals = new CommandLocals();
|
||||
locals.put(Actor.class, plugin.wrapCommandSender(event.getPlayer()));
|
||||
Set<String> toRemove = plugin.getWorldEdit().getPlatformManager().getCommandManager().getDispatcher().getCommands().stream()
|
||||
.filter(commandMapping -> !commandMapping.getCallable().testPermission(locals))
|
||||
.map(CommandMapping::getPrimaryAlias)
|
||||
.collect(Collectors.toSet());
|
||||
event.getCommands().removeIf(toRemove::contains);
|
||||
InjectedValueStore store = MapBackedValueStore.create();
|
||||
store.injectValue(Key.of(Actor.class), context ->
|
||||
Optional.of(plugin.wrapCommandSender(event.getPlayer())));
|
||||
CommandParameters parameters = NoInputCommandParameters.builder()
|
||||
.injectedValues(MemoizingValueAccess.wrap(store))
|
||||
.build();
|
||||
CommandManager commandManager = plugin.getWorldEdit().getPlatformManager().getPlatformCommandManager().getCommandManager();
|
||||
event.getCommands().removeIf(name ->
|
||||
// remove if in the manager and not satisfied
|
||||
commandManager.getCommand(name)
|
||||
.filter(command -> !command.getCondition().satisfied(parameters))
|
||||
.isPresent()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -289,7 +289,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
||||
// code of WorldEdit expects it
|
||||
String[] split = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, split, 1, args.length);
|
||||
split[0] = cmd.getName();
|
||||
split[0] = "/" + cmd.getName();
|
||||
|
||||
CommandEvent event = new CommandEvent(wrapCommandSender(sender), Joiner.on(" ").join(split));
|
||||
getWorldEdit().getEventBus().post(event);
|
||||
@ -303,7 +303,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
||||
// code of WorldEdit expects it
|
||||
String[] split = new String[args.length + 1];
|
||||
System.arraycopy(args, 0, split, 1, args.length);
|
||||
split[0] = cmd.getName();
|
||||
split[0] = "/" + cmd.getName();
|
||||
|
||||
CommandSuggestionEvent event = new CommandSuggestionEvent(wrapCommandSender(sender), Joiner.on(" ").join(split));
|
||||
getWorldEdit().getEventBus().post(event);
|
||||
|
@ -1,5 +1,18 @@
|
||||
plugins {
|
||||
id("net.ltgt.apt") version "0.21"
|
||||
}
|
||||
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'net.ltgt.apt-eclipse'
|
||||
apply plugin: 'net.ltgt.apt-idea'
|
||||
|
||||
configurations.all { Configuration it ->
|
||||
it.resolutionStrategy { ResolutionStrategy rs ->
|
||||
rs.force("com.google.guava:guava:21.0")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':worldedit-libs:core')
|
||||
@ -11,10 +24,21 @@ dependencies {
|
||||
compile 'com.google.code.gson:gson:2.8.0'
|
||||
compile 'com.googlecode.json-simple:json-simple:1.1.1'
|
||||
compile 'org.slf4j:slf4j-api:1.7.26'
|
||||
|
||||
compileOnly project(':worldedit-libs:core:ap')
|
||||
annotationProcessor project(':worldedit-libs:core:ap')
|
||||
annotationProcessor "com.google.guava:guava:21.0"
|
||||
def avVersion = "1.6.5"
|
||||
compileOnly "com.google.auto.value:auto-value-annotations:$avVersion"
|
||||
annotationProcessor "com.google.auto.value:auto-value:$avVersion"
|
||||
//compile 'net.sf.trove4j:trove4j:3.0.3'
|
||||
testCompile 'org.mockito:mockito-core:1.9.0-rc1'
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
it.options.compilerArgs.add("-Aarg.name.key.prefix=")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
|
@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<assembly
|
||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
<format>tar.bz2</format>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<files>
|
||||
<file>
|
||||
<source>${project.build.directory}/${artifactId}-${project.version}.jar</source>
|
||||
<destName>WorldEdit.jar</destName>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<filtered>false</filtered>
|
||||
</file>
|
||||
<file>
|
||||
<source>README.html</source>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<filtered>true</filtered>
|
||||
</file>
|
||||
</files>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<includes>
|
||||
<include>LICENSE.txt</include>
|
||||
<include>CHANGELOG.txt</include>
|
||||
<include>contrib/craftscripts/*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
@ -60,6 +60,7 @@ import java.util.Set;
|
||||
* @param <T> command sender class
|
||||
*/
|
||||
@SuppressWarnings("ProtectedField")
|
||||
@Deprecated
|
||||
public abstract class CommandsManager<T> {
|
||||
|
||||
protected static final Logger logger =
|
||||
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contains the old command system. It is no longer in use. Please switch
|
||||
* to Piston, Intake, ACF, or similar systems.
|
||||
*/
|
||||
package com.sk89q.minecraft.util.commands;
|
@ -122,7 +122,6 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
@ -175,15 +174,6 @@ public class EditSession implements Extent, AutoCloseable {
|
||||
public String getDisplayName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
public static Optional<ReorderMode> getFromDisplayName(String name) {
|
||||
for (ReorderMode mode : values()) {
|
||||
if (mode.getDisplayName().equalsIgnoreCase(name)) {
|
||||
return Optional.of(mode);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ProtectedField")
|
||||
@ -914,16 +904,15 @@ public class EditSession implements Extent, AutoCloseable {
|
||||
* Remove blocks of a certain type nearby a given position.
|
||||
*
|
||||
* @param position center position of cuboid
|
||||
* @param blockType the block type to match
|
||||
* @param mask the mask to match
|
||||
* @param apothem an apothem of the cuboid, where the minimum is 1
|
||||
* @return number of blocks affected
|
||||
* @throws MaxChangedBlocksException thrown if too many blocks are changed
|
||||
*/
|
||||
public int removeNear(BlockVector3 position, BlockType blockType, int apothem) throws MaxChangedBlocksException {
|
||||
public int removeNear(BlockVector3 position, Mask mask, int apothem) throws MaxChangedBlocksException {
|
||||
checkNotNull(position);
|
||||
checkArgument(apothem >= 1, "apothem >= 1");
|
||||
|
||||
Mask mask = new BlockTypeMask(this, blockType);
|
||||
BlockVector3 adjustment = BlockVector3.ONE.multiply(apothem - 1);
|
||||
Region region = new CuboidRegion(
|
||||
getWorld(), // Causes clamping of Y range
|
||||
|
@ -52,6 +52,7 @@ import com.sk89q.worldedit.world.item.ItemTypes;
|
||||
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
@ -91,7 +92,7 @@ public class LocalSession {
|
||||
private transient int cuiVersion = -1;
|
||||
private transient boolean fastMode = false;
|
||||
private transient Mask mask;
|
||||
private transient TimeZone timezone = TimeZone.getDefault();
|
||||
private transient ZoneId timezone = ZoneId.systemDefault();
|
||||
private transient BlockVector3 cuiTemporaryBlock;
|
||||
private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.MULTI_STAGE;
|
||||
|
||||
@ -169,7 +170,7 @@ public class LocalSession {
|
||||
*
|
||||
* @return the timezone
|
||||
*/
|
||||
public TimeZone getTimeZone() {
|
||||
public ZoneId getTimeZone() {
|
||||
return timezone;
|
||||
}
|
||||
|
||||
@ -178,7 +179,7 @@ public class LocalSession {
|
||||
*
|
||||
* @param timezone the user's timezone
|
||||
*/
|
||||
public void setTimezone(TimeZone timezone) {
|
||||
public void setTimezone(ZoneId timezone) {
|
||||
checkNotNull(timezone);
|
||||
this.timezone = timezone;
|
||||
}
|
||||
@ -849,9 +850,10 @@ public class LocalSession {
|
||||
public Calendar detectDate(String input) {
|
||||
checkNotNull(input);
|
||||
|
||||
Time.setTimeZone(getTimeZone());
|
||||
TimeZone tz = TimeZone.getTimeZone(getTimeZone());
|
||||
Time.setTimeZone(tz);
|
||||
Options opt = new com.sk89q.jchronic.Options();
|
||||
opt.setNow(Calendar.getInstance(getTimeZone()));
|
||||
opt.setNow(Calendar.getInstance(tz));
|
||||
Span date = Chronic.parse(input, opt);
|
||||
if (date == null) {
|
||||
return null;
|
||||
|
@ -303,6 +303,17 @@ public final class WorldEdit {
|
||||
if (exts.size() != 1) {
|
||||
exts = exts.subList(0, 1);
|
||||
}
|
||||
} else {
|
||||
int dot = filename.lastIndexOf('.');
|
||||
if (dot < 0 || dot == filename.length() - 1) {
|
||||
String currentExt = filename.substring(dot + 1);
|
||||
if (exts.contains(currentExt) && checkFilename(filename)) {
|
||||
File f = new File(dir, filename);
|
||||
if (f.exists()) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File result = null;
|
||||
for (Iterator<String> iter = exts.iterator(); iter.hasNext() && (result == null || (!isSave && !result.exists()));) {
|
||||
@ -317,7 +328,7 @@ public final class WorldEdit {
|
||||
private File getSafeFileWithExtension(File dir, String filename, String extension) {
|
||||
if (extension != null) {
|
||||
int dot = filename.lastIndexOf('.');
|
||||
if (dot < 0 || !filename.substring(dot).equalsIgnoreCase(extension)) {
|
||||
if (dot < 0 || dot == filename.length() - 1 || !filename.substring(dot + 1).equalsIgnoreCase(extension)) {
|
||||
filename += "." + extension;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.command.factory.ItemUseFactory;
|
||||
import com.sk89q.worldedit.command.factory.ReplaceFactory;
|
||||
import com.sk89q.worldedit.command.factory.TreeGeneratorFactory;
|
||||
import com.sk89q.worldedit.command.util.PermissionCondition;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.factory.Apply;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.regions.factory.RegionFactory;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import com.sk89q.worldedit.internal.command.CommandRegistrationHandler;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.CommandParameters;
|
||||
import org.enginehub.piston.DefaultCommandManagerService;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
import org.enginehub.piston.part.CommandArgument;
|
||||
import org.enginehub.piston.part.SubCommandPart;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.enginehub.piston.part.CommandParts.arg;
|
||||
|
||||
@CommandContainer
|
||||
public class ApplyBrushCommands {
|
||||
|
||||
private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("shape"), TextComponent.of("The shape of the region"))
|
||||
.defaultsTo(ImmutableList.of())
|
||||
.ofTypes(ImmutableList.of(Key.of(RegionFactory.class)))
|
||||
.build();
|
||||
|
||||
private static final CommandArgument RADIUS = arg(TranslatableComponent.of("radius"), TextComponent.of("The size of the brush"))
|
||||
.defaultsTo(ImmutableList.of("5"))
|
||||
.ofTypes(ImmutableList.of(Key.of(double.class)))
|
||||
.build();
|
||||
|
||||
public static void register(CommandManager commandManager, CommandRegistrationHandler registration) {
|
||||
commandManager.register("apply", builder -> {
|
||||
builder.description(TextComponent.of("Apply brush, apply a function to every block"));
|
||||
builder.action(org.enginehub.piston.Command.Action.NULL_ACTION);
|
||||
|
||||
CommandManager manager = DefaultCommandManagerService.getInstance()
|
||||
.newCommandManager();
|
||||
registration.register(
|
||||
manager,
|
||||
ApplyBrushCommandsRegistration.builder(),
|
||||
new ApplyBrushCommands()
|
||||
);
|
||||
|
||||
builder.condition(new PermissionCondition(ImmutableSet.of("worldedit.brush.apply")));
|
||||
|
||||
builder.addParts(REGION_FACTORY, RADIUS);
|
||||
builder.addPart(SubCommandPart.builder(TranslatableComponent.of("type"), TextComponent.of("Type of brush to use"))
|
||||
.withCommands(manager.getAllCommands().collect(Collectors.toList()))
|
||||
.required()
|
||||
.build());
|
||||
});
|
||||
}
|
||||
|
||||
private void setApplyBrush(CommandParameters parameters, Player player, LocalSession localSession,
|
||||
Contextual<? extends RegionFunction> generatorFactory) throws WorldEditException {
|
||||
double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class));
|
||||
RegionFactory regionFactory = REGION_FACTORY.value(parameters).asSingle(RegionFactory.class);
|
||||
BrushCommands.setOperationBasedBrush(player, localSession, radius,
|
||||
new Apply(generatorFactory), regionFactory, "worldedit.brush.apply");
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "forest",
|
||||
desc = "Plant trees"
|
||||
)
|
||||
public void forest(CommandParameters parameters,
|
||||
Player player, LocalSession localSession,
|
||||
@Arg(desc = "The type of tree to plant")
|
||||
TreeGenerator.TreeType type) throws WorldEditException {
|
||||
setApplyBrush(parameters, player, localSession, new TreeGeneratorFactory(type));
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "item",
|
||||
desc = "Use an item"
|
||||
)
|
||||
public void item(CommandParameters parameters,
|
||||
Player player, LocalSession localSession,
|
||||
@Arg(desc = "The type of item to use")
|
||||
BaseItem item) throws WorldEditException {
|
||||
setApplyBrush(parameters, player, localSession, new ItemUseFactory(item));
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "set",
|
||||
desc = "Place a block"
|
||||
)
|
||||
public void set(CommandParameters parameters,
|
||||
Player player, LocalSession localSession,
|
||||
@Arg(desc = "The pattern of blocks to use")
|
||||
Pattern pattern) throws WorldEditException {
|
||||
setApplyBrush(parameters, player, localSession, new ReplaceFactory(pattern));
|
||||
}
|
||||
|
||||
}
|
@ -19,17 +19,13 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.Logging;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.function.FlatRegionFunction;
|
||||
@ -46,93 +42,71 @@ import com.sk89q.worldedit.regions.FlatRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.Regions;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BiomeData;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.registry.BiomeRegistry;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
|
||||
|
||||
/**
|
||||
* Implements biome-related commands such as "/biomelist".
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class BiomeCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public BiomeCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
public BiomeCommands() {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "biomelist", "biomels" },
|
||||
usage = "[page]",
|
||||
desc = "Gets all biomes available.",
|
||||
max = 1
|
||||
name = "biomelist",
|
||||
aliases = { "biomels" },
|
||||
desc = "Gets all biomes available."
|
||||
)
|
||||
@CommandPermissions("worldedit.biome.list")
|
||||
public void biomeList(Player player, CommandContext args) throws WorldEditException {
|
||||
int page;
|
||||
int offset;
|
||||
int count = 0;
|
||||
|
||||
if (args.argsLength() == 0 || (page = args.getInteger(0)) < 2) {
|
||||
page = 1;
|
||||
offset = 0;
|
||||
} else {
|
||||
offset = (page - 1) * 19;
|
||||
}
|
||||
|
||||
public void biomeList(Player player,
|
||||
@Arg(desc = "Page number.", def = "1")
|
||||
int page) throws WorldEditException {
|
||||
BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager()
|
||||
.queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry();
|
||||
Collection<BiomeType> biomes = BiomeType.REGISTRY.values();
|
||||
int totalPages = biomes.size() / 19 + 1;
|
||||
player.print("Available Biomes (page " + page + "/" + totalPages + ") :");
|
||||
for (BiomeType biome : biomes) {
|
||||
if (offset > 0) {
|
||||
offset--;
|
||||
} else {
|
||||
BiomeData data = biomeRegistry.getData(biome);
|
||||
if (data != null) {
|
||||
player.print(" " + data.getName());
|
||||
if (++count == 19) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
player.print(" <unknown #" + biome.getId() + ">");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PaginationBox paginationBox = PaginationBox.fromStrings("Available Biomes", "/biomelist %page%",
|
||||
BiomeType.REGISTRY.values().stream()
|
||||
.map(biomeRegistry::getData).filter(Objects::nonNull)
|
||||
.map(BiomeData::getName).collect(Collectors.toList()));
|
||||
player.print(paginationBox.create(page));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "biomeinfo" },
|
||||
flags = "pt",
|
||||
name = "biomeinfo",
|
||||
desc = "Get the biome of the targeted block.",
|
||||
help =
|
||||
"Get the biome of the block.\n" +
|
||||
"By default use all the blocks contained in your selection.\n" +
|
||||
"-t use the block you are looking at.\n" +
|
||||
"-p use the block you are currently in",
|
||||
max = 0
|
||||
descFooter = "By default, uses all blocks in your selection."
|
||||
)
|
||||
@CommandPermissions("worldedit.biome.info")
|
||||
public void biomeInfo(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void biomeInfo(Player player, LocalSession session,
|
||||
@Switch(name = 't', desc = "Use the block you are looking at.")
|
||||
boolean useLineOfSight,
|
||||
@Switch(name = 'p', desc = "Use the block you are currently in.")
|
||||
boolean usePosition) throws WorldEditException {
|
||||
BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager()
|
||||
.queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry();
|
||||
Set<BiomeType> biomes = new HashSet<>();
|
||||
String qualifier;
|
||||
|
||||
if (args.hasFlag('t')) {
|
||||
if (useLineOfSight) {
|
||||
Location blockPosition = player.getBlockTrace(300);
|
||||
if (blockPosition == null) {
|
||||
player.printError("No block in sight!");
|
||||
@ -143,7 +117,7 @@ public class BiomeCommands {
|
||||
biomes.add(biome);
|
||||
|
||||
qualifier = "at line of sight point";
|
||||
} else if (args.hasFlag('p')) {
|
||||
} else if (usePosition) {
|
||||
BiomeType biome = player.getWorld().getBiome(player.getLocation().toVector().toBlockPoint().toBlockVector2());
|
||||
biomes.add(biome);
|
||||
|
||||
@ -177,18 +151,16 @@ public class BiomeCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/setbiome" },
|
||||
usage = "<biome>",
|
||||
flags = "p",
|
||||
desc = "Sets the biome of the player's current block or region.",
|
||||
help =
|
||||
"Set the biome of the region.\n" +
|
||||
"By default use all the blocks contained in your selection.\n" +
|
||||
"-p use the block you are currently in"
|
||||
name = "/setbiome",
|
||||
desc = "Sets the biome of your current block or region.",
|
||||
descFooter = "By default, uses all the blocks in your selection"
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.biome.set")
|
||||
public void setBiome(Player player, LocalSession session, EditSession editSession, BiomeType target, @Switch('p') boolean atPosition) throws WorldEditException {
|
||||
public void setBiome(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "Biome type.") BiomeType target,
|
||||
@Switch(name = 'p', desc = "Use your current position")
|
||||
boolean atPosition) throws WorldEditException {
|
||||
World world = player.getWorld();
|
||||
Region region;
|
||||
Mask mask = editSession.getMask();
|
||||
|
@ -19,15 +19,12 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.factory.ReplaceFactory;
|
||||
import com.sk89q.worldedit.command.factory.TreeGeneratorFactory;
|
||||
import com.sk89q.worldedit.command.tool.BrushTool;
|
||||
import com.sk89q.worldedit.command.tool.brush.ButcherBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.ClipboardBrush;
|
||||
@ -35,26 +32,42 @@ import com.sk89q.worldedit.command.tool.brush.CylinderBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.GravityBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.HollowCylinderBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.HollowSphereBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.OperationFactoryBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.SmoothBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.SphereBrush;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.CreatureButcher;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.factory.Apply;
|
||||
import com.sk89q.worldedit.function.factory.Deform;
|
||||
import com.sk89q.worldedit.function.factory.Paint;
|
||||
import com.sk89q.worldedit.function.mask.BlockTypeMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.factory.RegionFactory;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.session.request.RequestExtent;
|
||||
import com.sk89q.worldedit.util.HandSide;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.ArgFlag;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Commands to set brush shape.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class BrushCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
@ -70,19 +83,18 @@ public class BrushCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "sphere", "s" },
|
||||
usage = "<pattern> [radius]",
|
||||
flags = "h",
|
||||
desc = "Choose the sphere brush",
|
||||
help =
|
||||
"Chooses the sphere brush.\n" +
|
||||
"The -h flag creates hollow spheres instead.",
|
||||
min = 1,
|
||||
max = 2
|
||||
name = "sphere",
|
||||
aliases = { "s" },
|
||||
desc = "Choose the sphere brush"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.sphere")
|
||||
public void sphereBrush(Player player, LocalSession session, Pattern fill,
|
||||
@Optional("2") double radius, @Switch('h') boolean hollow) throws WorldEditException {
|
||||
public void sphereBrush(Player player, LocalSession session,
|
||||
@Arg(desc = "The pattern of blocks to set")
|
||||
Pattern fill,
|
||||
@Arg(desc = "The radius of the sphere", def = "2")
|
||||
double radius,
|
||||
@Switch(name = 'h', desc = "Create hollow spheres instead")
|
||||
boolean hollow) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
|
||||
@ -99,19 +111,20 @@ public class BrushCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "cylinder", "cyl", "c" },
|
||||
usage = "<block> [radius] [height]",
|
||||
flags = "h",
|
||||
desc = "Choose the cylinder brush",
|
||||
help =
|
||||
"Chooses the cylinder brush.\n" +
|
||||
"The -h flag creates hollow cylinders instead.",
|
||||
min = 1,
|
||||
max = 3
|
||||
name = "cylinder",
|
||||
aliases = { "cyl", "c" },
|
||||
desc = "Choose the cylinder brush"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.cylinder")
|
||||
public void cylinderBrush(Player player, LocalSession session, Pattern fill,
|
||||
@Optional("2") double radius, @Optional("1") int height, @Switch('h') boolean hollow) throws WorldEditException {
|
||||
public void cylinderBrush(Player player, LocalSession session,
|
||||
@Arg(desc = "The pattern of blocks to set")
|
||||
Pattern fill,
|
||||
@Arg(desc = "The radius of the cylinder", def = "2")
|
||||
double radius,
|
||||
@Arg(desc = "The height of the cylinder", def = "1")
|
||||
int height,
|
||||
@Switch(name = 'h', desc = "Create hollow cylinders instead")
|
||||
boolean hollow) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
worldEdit.checkMaxBrushRadius(height);
|
||||
|
||||
@ -129,20 +142,22 @@ public class BrushCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "clipboard", "copy" },
|
||||
usage = "",
|
||||
flags = "aoebm",
|
||||
desc = "Choose the clipboard brush",
|
||||
help =
|
||||
"Chooses the clipboard brush.\n" +
|
||||
"The -a flag makes it not paste air.\n" +
|
||||
"Without the -p flag, the paste will appear centered at the target location. " +
|
||||
"With the flag, then the paste will appear relative to where you had " +
|
||||
"stood relative to the copied area when you copied it."
|
||||
name = "clipboard",
|
||||
aliases = { "copy" },
|
||||
desc = "Choose the clipboard brush"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.clipboard")
|
||||
public void clipboardBrush(Player player, LocalSession session, @Switch('a') boolean ignoreAir, @Switch('o') boolean usingOrigin,
|
||||
@Switch('e') boolean pasteEntities, @Switch('b') boolean pasteBiomes, @Switch('m') Mask sourceMask) throws WorldEditException {
|
||||
public void clipboardBrush(Player player, LocalSession session,
|
||||
@Switch(name = 'a', desc = "Don't paste air from the clipboard")
|
||||
boolean ignoreAir,
|
||||
@Switch(name = 'o', desc = "Paste using clipboard origin, instead of being centered at the target location")
|
||||
boolean usingOrigin,
|
||||
@Switch(name = 'e', desc = "Paste entities if available")
|
||||
boolean pasteEntities,
|
||||
@Switch(name = 'b', desc = "Paste biomes if available")
|
||||
boolean pasteBiomes,
|
||||
@ArgFlag(name = 'm', desc = "Skip blocks matching this mask in the clipboard", def = "")
|
||||
Mask sourceMask) throws WorldEditException {
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
|
||||
@ -159,18 +174,18 @@ public class BrushCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "smooth" },
|
||||
usage = "[size] [iterations] [filter]",
|
||||
name = "smooth",
|
||||
desc = "Choose the terrain softener brush",
|
||||
help =
|
||||
"Chooses the terrain softener brush. Optionally, specify a mask of blocks to be used for the heightmap.\n" +
|
||||
"For example, '/brush smooth 2 4 grass_block,dirt,stone'.",
|
||||
min = 0,
|
||||
max = 3
|
||||
descFooter = "Example: '/brush smooth 2 4 grass_block,dirt,stone'"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.smooth")
|
||||
public void smoothBrush(Player player, LocalSession session,
|
||||
@Optional("2") double radius, @Optional("4") int iterations, @Optional Mask mask) throws WorldEditException {
|
||||
@Arg(desc = "The radius to sample for softening", def = "2")
|
||||
double radius,
|
||||
@Arg(desc = "The number of iterations to perform", def = "4")
|
||||
int iterations,
|
||||
@Arg(desc = "The mask of blocks to use for the heightmap", def = "")
|
||||
Mask mask) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
|
||||
@ -181,14 +196,14 @@ public class BrushCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "ex", "extinguish" },
|
||||
usage = "[radius]",
|
||||
desc = "Shortcut fire extinguisher brush",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "extinguish",
|
||||
aliases = { "ex" },
|
||||
desc = "Shortcut fire extinguisher brush"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.ex")
|
||||
public void extinguishBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException {
|
||||
public void extinguishBrush(Player player, LocalSession session,
|
||||
@Arg(desc = "The radius to extinguish", def = "5")
|
||||
double radius) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
|
||||
@ -202,19 +217,16 @@ public class BrushCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "gravity", "grav" },
|
||||
usage = "[radius]",
|
||||
flags = "h",
|
||||
desc = "Gravity brush",
|
||||
help =
|
||||
"This brush simulates the affect of gravity.\n" +
|
||||
"The -h flag makes it affect blocks starting at the world's max y, " +
|
||||
"instead of the clicked block's y + radius.",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "gravity",
|
||||
aliases = { "grav" },
|
||||
desc = "Gravity brush, simulates the effect of gravity"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.gravity")
|
||||
public void gravityBrush(Player player, LocalSession session, @Optional("5") double radius, @Switch('h') boolean fromMaxY) throws WorldEditException {
|
||||
public void gravityBrush(Player player, LocalSession session,
|
||||
@Arg(desc = "The radius to apply gravity in", def = "5")
|
||||
double radius,
|
||||
@Switch(name = 'h', desc = "Affect blocks starting at max Y, rather than the target location Y + radius")
|
||||
boolean fromMaxY) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
|
||||
@ -226,29 +238,32 @@ public class BrushCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "butcher", "kill" },
|
||||
usage = "[radius]",
|
||||
flags = "plangbtfr",
|
||||
desc = "Butcher brush",
|
||||
help = "Kills nearby mobs within the specified radius.\n" +
|
||||
"Flags:\n" +
|
||||
" -p also kills pets.\n" +
|
||||
" -n also kills NPCs.\n" +
|
||||
" -g also kills Golems.\n" +
|
||||
" -a also kills animals.\n" +
|
||||
" -b also kills ambient mobs.\n" +
|
||||
" -t also kills mobs with name tags.\n" +
|
||||
" -f compounds all previous flags.\n" +
|
||||
" -r also destroys armor stands.\n" +
|
||||
" -l currently does nothing.",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "butcher",
|
||||
aliases = { "kill" },
|
||||
desc = "Butcher brush, kills mobs within a radius"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.butcher")
|
||||
public void butcherBrush(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void butcherBrush(Player player, LocalSession session,
|
||||
@Arg(desc = "Radius to kill mobs in", def = "5")
|
||||
double radius,
|
||||
@Switch(name = 'p', desc = "Also kill pets")
|
||||
boolean killPets,
|
||||
@Switch(name = 'n', desc = "Also kill NPCs")
|
||||
boolean killNpcs,
|
||||
@Switch(name = 'g', desc = "Also kill golems")
|
||||
boolean killGolems,
|
||||
@Switch(name = 'a', desc = "Also kill animals")
|
||||
boolean killAnimals,
|
||||
@Switch(name = 'b', desc = "Also kill ambient mobs")
|
||||
boolean killAmbient,
|
||||
@Switch(name = 't', desc = "Also kill mobs with name tags")
|
||||
boolean killWithName,
|
||||
@Switch(name = 'f', desc = "Also kill all friendly mobs (Applies the flags `-abgnpt`)")
|
||||
boolean killFriendly,
|
||||
@Switch(name = 'r', desc = "Also destroy armor stands")
|
||||
boolean killArmorStands) throws WorldEditException {
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
double radius = args.argsLength() > 0 ? args.getDouble(0) : 5;
|
||||
double maxRadius = config.maxBrushRadius;
|
||||
// hmmmm not horribly worried about this because -1 is still rather efficient,
|
||||
// the problem arises when butcherMaxRadius is some really high number but not infinite
|
||||
@ -262,7 +277,14 @@ public class BrushCommands {
|
||||
}
|
||||
|
||||
CreatureButcher flags = new CreatureButcher(player);
|
||||
flags.fromCommand(args);
|
||||
flags.or(CreatureButcher.Flags.FRIENDLY , killFriendly); // No permission check here. Flags will instead be filtered by the subsequent calls.
|
||||
flags.or(CreatureButcher.Flags.PETS , killPets, "worldedit.butcher.pets");
|
||||
flags.or(CreatureButcher.Flags.NPCS , killNpcs, "worldedit.butcher.npcs");
|
||||
flags.or(CreatureButcher.Flags.GOLEMS , killGolems, "worldedit.butcher.golems");
|
||||
flags.or(CreatureButcher.Flags.ANIMALS , killAnimals, "worldedit.butcher.animals");
|
||||
flags.or(CreatureButcher.Flags.AMBIENT , killAmbient, "worldedit.butcher.ambient");
|
||||
flags.or(CreatureButcher.Flags.TAGGED , killWithName, "worldedit.butcher.tagged");
|
||||
flags.or(CreatureButcher.Flags.ARMOR_STAND , killArmorStands, "worldedit.butcher.armorstands");
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
|
||||
tool.setSize(radius);
|
||||
@ -270,4 +292,106 @@ public class BrushCommands {
|
||||
|
||||
player.print(String.format("Butcher brush equipped (%.0f).", radius));
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "deform",
|
||||
desc = "Deform brush, applies an expression to an area"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.deform")
|
||||
public void deform(Player player, LocalSession localSession,
|
||||
@Arg(desc = "The shape of the region")
|
||||
RegionFactory shape,
|
||||
@Arg(desc = "The size of the brush", def = "5")
|
||||
double radius,
|
||||
@Arg(desc = "Expression to apply", def = "y-=0.2")
|
||||
String expression,
|
||||
@Switch(name = 'r', desc = "Use the game's coordinate origin")
|
||||
boolean useRawCoords,
|
||||
@Switch(name = 'o', desc = "Use the placement position as the origin")
|
||||
boolean usePlacement) throws WorldEditException {
|
||||
Deform deform = new Deform(expression);
|
||||
if (useRawCoords) {
|
||||
deform.setMode(Deform.Mode.RAW_COORD);
|
||||
} else if (usePlacement) {
|
||||
deform.setMode(Deform.Mode.OFFSET);
|
||||
deform.setOffset(localSession.getPlacementPosition(player).toVector3());
|
||||
}
|
||||
setOperationBasedBrush(player, localSession, radius,
|
||||
deform, shape, "worldedit.brush.deform");
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "set",
|
||||
desc = "Set brush, sets all blocks in the area"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.set")
|
||||
public void set(Player player, LocalSession localSession,
|
||||
@Arg(desc = "The shape of the region")
|
||||
RegionFactory shape,
|
||||
@Arg(desc = "The size of the brush", def = "5")
|
||||
double radius,
|
||||
@Arg(desc = "The pattern of blocks to set")
|
||||
Pattern pattern) throws WorldEditException {
|
||||
setOperationBasedBrush(player, localSession, radius,
|
||||
new Apply(new ReplaceFactory(pattern)), shape, "worldedit.brush.set");
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "forest",
|
||||
desc = "Forest brush, creates a forest in the area"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.forest")
|
||||
public void forest(Player player, LocalSession localSession,
|
||||
@Arg(desc = "The shape of the region")
|
||||
RegionFactory shape,
|
||||
@Arg(desc = "The size of the brush", def = "5")
|
||||
double radius,
|
||||
@Arg(desc = "The density of the brush", def = "20")
|
||||
double density,
|
||||
@Arg(desc = "The type of tree to use")
|
||||
TreeGenerator.TreeType type) throws WorldEditException {
|
||||
setOperationBasedBrush(player, localSession, radius,
|
||||
new Paint(new TreeGeneratorFactory(type), density / 100), shape, "worldedit.brush.forest");
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "raise",
|
||||
desc = "Raise brush, raise all blocks by one"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.raise")
|
||||
public void raise(Player player, LocalSession localSession,
|
||||
@Arg(desc = "The shape of the region")
|
||||
RegionFactory shape,
|
||||
@Arg(desc = "The size of the brush", def = "5")
|
||||
double radius) throws WorldEditException {
|
||||
setOperationBasedBrush(player, localSession, radius,
|
||||
new Deform("y-=1"), shape, "worldedit.brush.raise");
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "lower",
|
||||
desc = "Lower brush, lower all blocks by one"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.lower")
|
||||
public void lower(Player player, LocalSession localSession,
|
||||
@Arg(desc = "The shape of the region")
|
||||
RegionFactory shape,
|
||||
@Arg(desc = "The size of the brush", def = "5")
|
||||
double radius) throws WorldEditException {
|
||||
setOperationBasedBrush(player, localSession, radius,
|
||||
new Deform("y+=1"), shape, "worldedit.brush.lower");
|
||||
}
|
||||
|
||||
static void setOperationBasedBrush(Player player, LocalSession session, double radius,
|
||||
Contextual<? extends Operation> factory,
|
||||
RegionFactory shape,
|
||||
String permission) throws WorldEditException {
|
||||
WorldEdit.getInstance().checkMaxBrushRadius(radius);
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
|
||||
tool.setSize(radius);
|
||||
tool.setFill(null);
|
||||
tool.setBrush(new OperationFactoryBrush(factory, shape, session), permission);
|
||||
|
||||
player.print("Set brush to " + factory);
|
||||
}
|
||||
}
|
||||
|
@ -20,31 +20,36 @@
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.Logging;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.MathUtils;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
|
||||
import com.sk89q.worldedit.world.storage.LegacyChunkStore;
|
||||
import com.sk89q.worldedit.world.storage.McRegionChunkStore;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Commands for working with chunks.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class ChunkCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
@ -55,14 +60,11 @@ public class ChunkCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "chunkinfo" },
|
||||
usage = "",
|
||||
desc = "Get information about the chunk that you are inside",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "chunkinfo",
|
||||
desc = "Get information about the chunk you're inside"
|
||||
)
|
||||
@CommandPermissions("worldedit.chunkinfo")
|
||||
public void chunkInfo(Player player) throws WorldEditException {
|
||||
public void chunkInfo(Player player) {
|
||||
Location pos = player.getBlockIn();
|
||||
int chunkX = (int) Math.floor(pos.getBlockX() / 16.0);
|
||||
int chunkZ = (int) Math.floor(pos.getBlockZ() / 16.0);
|
||||
@ -79,27 +81,22 @@ public class ChunkCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "listchunks" },
|
||||
usage = "",
|
||||
desc = "List chunks that your selection includes",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "listchunks",
|
||||
desc = "List chunks that your selection includes"
|
||||
)
|
||||
@CommandPermissions("worldedit.listchunks")
|
||||
public void listChunks(Player player, LocalSession session) throws WorldEditException {
|
||||
public void listChunks(Player player, LocalSession session,
|
||||
@Arg(desc = "Page number.", def = "1") int page) throws WorldEditException {
|
||||
Set<BlockVector2> chunks = session.getSelection(player.getWorld()).getChunks();
|
||||
|
||||
for (BlockVector2 chunk : chunks) {
|
||||
player.print(LegacyChunkStore.getFilename(chunk));
|
||||
}
|
||||
PaginationBox paginationBox = PaginationBox.fromStrings("Selected Chunks", "/listchunks %page%",
|
||||
chunks.stream().map(BlockVector2::toString).collect(Collectors.toList()));
|
||||
player.print(paginationBox.create(page));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "delchunks" },
|
||||
usage = "",
|
||||
desc = "Delete chunks that your selection includes",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "delchunks",
|
||||
desc = "Delete chunks that your selection includes"
|
||||
)
|
||||
@CommandPermissions("worldedit.delchunks")
|
||||
@Logging(REGION)
|
||||
|
@ -19,18 +19,13 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.Logging;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
@ -49,46 +44,42 @@ import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.session.PasteBuilder;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.ArgFlag;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
|
||||
|
||||
/**
|
||||
* Clipboard commands.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class ClipboardCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public ClipboardCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
public ClipboardCommands() {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/copy" },
|
||||
flags = "em",
|
||||
desc = "Copy the selection to the clipboard",
|
||||
help = "Copy the selection to the clipboard\n" +
|
||||
"Flags:\n" +
|
||||
" -e will also copy entities\n" +
|
||||
" -b will also copy biomes\n" +
|
||||
" -m sets a source mask so that excluded blocks become air",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "/copy",
|
||||
desc = "Copy the selection to the clipboard"
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.copy")
|
||||
public void copy(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region, @Switch('e') boolean copyEntities,
|
||||
@Switch('m') Mask mask, @Switch('b') boolean copyBiomes) throws WorldEditException {
|
||||
|
||||
@Selection Region region,
|
||||
@Switch(name = 'e', desc = "Also copy entities")
|
||||
boolean copyEntities,
|
||||
@Switch(name = 'b', desc = "Also copy biomes")
|
||||
boolean copyBiomes,
|
||||
@ArgFlag(name = 'm', desc = "Set the exclude mask, matching blocks become air", def = "")
|
||||
Mask mask) throws WorldEditException {
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
clipboard.setOrigin(session.getPlacementPosition(player));
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
|
||||
@ -106,24 +97,22 @@ public class ClipboardCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/cut" },
|
||||
flags = "em",
|
||||
usage = "[leave-pattern]",
|
||||
name = "/cut",
|
||||
desc = "Cut the selection to the clipboard",
|
||||
help = "Copy the selection to the clipboard\n" +
|
||||
"The space will be filled with the leave pattern if specified, otherwise air." +
|
||||
"Flags:\n" +
|
||||
" -e will also cut entities\n" +
|
||||
" -b will also copy biomes (source biomes unaffected)\n" +
|
||||
" -m sets a source mask so that excluded blocks become air\n" +
|
||||
"WARNING: Cutting and pasting entities cannot yet be undone!",
|
||||
max = 1
|
||||
descFooter = "WARNING: Cutting and pasting entities cannot be undone!"
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.cut")
|
||||
@Logging(REGION)
|
||||
public void cut(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region, @Optional("air") Pattern leavePattern, @Switch('e') boolean copyEntities,
|
||||
@Switch('m') Mask mask, @Switch('b') boolean copyBiomes) throws WorldEditException {
|
||||
@Selection Region region,
|
||||
@Arg(desc = "Pattern to leave in place of the selection", def = "air")
|
||||
Pattern leavePattern,
|
||||
@Switch(name = 'e', desc = "Also cut entities")
|
||||
boolean copyEntities,
|
||||
@Switch(name = 'b', desc = "Also copy biomes, source biomes are unaffected")
|
||||
boolean copyBiomes,
|
||||
@ArgFlag(name = 'm', desc = "Set the exclude mask, matching blocks become air", def = "")
|
||||
Mask mask) throws WorldEditException {
|
||||
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
clipboard.setOrigin(session.getPlacementPosition(player));
|
||||
@ -144,26 +133,24 @@ public class ClipboardCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/paste" },
|
||||
flags = "saobem:",
|
||||
desc = "Paste the clipboard's contents",
|
||||
help =
|
||||
"Pastes the clipboard's contents.\n" +
|
||||
"Flags:\n" +
|
||||
" -a skips air blocks\n" +
|
||||
" -b pastes biomes if available\n" +
|
||||
" -e pastes entities if available\n" +
|
||||
" -m [<mask>] skips matching blocks in the clipboard\n" +
|
||||
" -o pastes at the original position\n" +
|
||||
" -s selects the region after pasting\n",
|
||||
max = 0
|
||||
name = "/paste",
|
||||
desc = "Paste the clipboard's contents"
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.paste")
|
||||
@Logging(PLACEMENT)
|
||||
public void paste(Player player, LocalSession session, EditSession editSession,
|
||||
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
|
||||
@Switch('s') boolean selectPasted, @Switch('e') boolean pasteEntities,
|
||||
@Switch('b') boolean pasteBiomes, @Switch('m') Mask sourceMask) throws WorldEditException {
|
||||
@Switch(name = 'a', desc = "Skip air blocks")
|
||||
boolean ignoreAirBlocks,
|
||||
@Switch(name = 'o', desc = "Paste at the original position")
|
||||
boolean atOrigin,
|
||||
@Switch(name = 's', desc = "Select the region after pasting")
|
||||
boolean selectPasted,
|
||||
@Switch(name = 'e', desc = "Paste entities if available")
|
||||
boolean pasteEntities,
|
||||
@Switch(name = 'b', desc = "Paste biomes if available")
|
||||
boolean pasteBiomes,
|
||||
@ArgFlag(name = 'm', desc = "Skip blocks matching this mask", def = "")
|
||||
Mask sourceMask) throws WorldEditException {
|
||||
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
@ -197,42 +184,43 @@ public class ClipboardCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/rotate" },
|
||||
usage = "<y-axis> [<x-axis>] [<z-axis>]",
|
||||
name = "/rotate",
|
||||
desc = "Rotate the contents of the clipboard",
|
||||
help = "Non-destructively rotate the contents of the clipboard.\n" +
|
||||
descFooter = "Non-destructively rotate the contents of the clipboard.\n" +
|
||||
"Angles are provided in degrees and a positive angle will result in a clockwise rotation. " +
|
||||
"Multiple rotations can be stacked. Interpolation is not performed so angles should be a multiple of 90 degrees.\n"
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.rotate")
|
||||
public void rotate(Player player, LocalSession session, Double yRotate, @Optional Double xRotate, @Optional Double zRotate) throws WorldEditException {
|
||||
if ((yRotate != null && Math.abs(yRotate % 90) > 0.001) ||
|
||||
xRotate != null && Math.abs(xRotate % 90) > 0.001 ||
|
||||
zRotate != null && Math.abs(zRotate % 90) > 0.001) {
|
||||
public void rotate(Player player, LocalSession session,
|
||||
@Arg(desc = "Amount to rotate on the y-axis")
|
||||
double yRotate,
|
||||
@Arg(desc = "Amount to rotate on the x-axis", def = "0")
|
||||
double xRotate,
|
||||
@Arg(desc = "Amount to rotate on the z-axis", def = "0")
|
||||
double zRotate) throws WorldEditException {
|
||||
if (Math.abs(yRotate % 90) > 0.001 ||
|
||||
Math.abs(xRotate % 90) > 0.001 ||
|
||||
Math.abs(zRotate % 90) > 0.001) {
|
||||
player.printDebug("Note: Interpolation is not yet supported, so angles that are multiples of 90 is recommended.");
|
||||
}
|
||||
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
AffineTransform transform = new AffineTransform();
|
||||
transform = transform.rotateY(-(yRotate != null ? yRotate : 0));
|
||||
transform = transform.rotateX(-(xRotate != null ? xRotate : 0));
|
||||
transform = transform.rotateZ(-(zRotate != null ? zRotate : 0));
|
||||
transform = transform.rotateY(-yRotate);
|
||||
transform = transform.rotateX(-xRotate);
|
||||
transform = transform.rotateZ(-zRotate);
|
||||
holder.setTransform(holder.getTransform().combine(transform));
|
||||
player.print("The clipboard copy has been rotated.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/flip" },
|
||||
usage = "[<direction>]",
|
||||
desc = "Flip the contents of the clipboard",
|
||||
help =
|
||||
"Flips the contents of the clipboard across the point from which the copy was made.\n",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/flip",
|
||||
desc = "Flip the contents of the clipboard across the origin"
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.flip")
|
||||
public void flip(Player player, LocalSession session,
|
||||
@Optional(Direction.AIM) @Direction BlockVector3 direction) throws WorldEditException {
|
||||
@Arg(desc = "The direction to flip, defaults to look direction.", def = Direction.AIM)
|
||||
@Direction BlockVector3 direction) throws WorldEditException {
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
AffineTransform transform = new AffineTransform();
|
||||
transform = transform.scale(direction.abs().multiply(-2).add(1, 1, 1).toVector3());
|
||||
@ -241,11 +229,8 @@ public class ClipboardCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "clearclipboard" },
|
||||
usage = "",
|
||||
desc = "Clear your clipboard",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "clearclipboard",
|
||||
desc = "Clear your clipboard"
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.clear")
|
||||
public void clearClipboard(Player player, LocalSession session) throws WorldEditException {
|
||||
|
@ -19,28 +19,31 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.input.DisallowedUsageException;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import com.sk89q.worldedit.world.item.ItemType;
|
||||
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* General WorldEdit commands.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class GeneralCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
@ -56,19 +59,18 @@ public class GeneralCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/limit" },
|
||||
usage = "[limit]",
|
||||
desc = "Modify block change limit",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/limit",
|
||||
desc = "Modify block change limit"
|
||||
)
|
||||
@CommandPermissions("worldedit.limit")
|
||||
public void limit(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void limit(Player player, LocalSession session,
|
||||
@Arg(desc = "The limit to set", def = "")
|
||||
Integer limit) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
boolean mayDisable = player.hasPermission("worldedit.limit.unrestricted");
|
||||
|
||||
int limit = args.argsLength() == 0 ? config.defaultChangeLimit : Math.max(-1, args.getInteger(0));
|
||||
limit = limit == null ? config.defaultChangeLimit : Math.max(-1, limit);
|
||||
if (!mayDisable && config.maxChangeLimit > -1) {
|
||||
if (limit > config.maxChangeLimit) {
|
||||
player.printError("Your maximum allowable limit is " + config.maxChangeLimit + ".");
|
||||
@ -86,19 +88,18 @@ public class GeneralCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/timeout" },
|
||||
usage = "[time]",
|
||||
desc = "Modify evaluation timeout time.",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/timeout",
|
||||
desc = "Modify evaluation timeout time."
|
||||
)
|
||||
@CommandPermissions("worldedit.timeout")
|
||||
public void timeout(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void timeout(Player player, LocalSession session,
|
||||
@Arg(desc = "The timeout time to set", def = "")
|
||||
Integer limit) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
boolean mayDisable = player.hasPermission("worldedit.timeout.unrestricted");
|
||||
|
||||
int limit = args.argsLength() == 0 ? config.calculationTimeout : Math.max(-1, args.getInteger(0));
|
||||
limit = limit == null ? config.calculationTimeout : Math.max(-1, limit);
|
||||
if (!mayDisable && config.maxCalculationTimeout > -1) {
|
||||
if (limit > config.maxCalculationTimeout) {
|
||||
player.printError("Your maximum allowable timeout is " + config.maxCalculationTimeout + " ms.");
|
||||
@ -116,89 +117,65 @@ public class GeneralCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/fast" },
|
||||
usage = "[on|off]",
|
||||
desc = "Toggle fast mode",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/fast",
|
||||
desc = "Toggle fast mode"
|
||||
)
|
||||
@CommandPermissions("worldedit.fast")
|
||||
public void fast(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
String newState = args.getString(0, null);
|
||||
if (session.hasFastMode()) {
|
||||
if ("on".equals(newState)) {
|
||||
player.printError("Fast mode already enabled.");
|
||||
public void fast(Player player, LocalSession session,
|
||||
@Arg(desc = "The new fast mode state", def = "")
|
||||
Boolean fastMode) throws WorldEditException {
|
||||
boolean hasFastMode = session.hasFastMode();
|
||||
if (fastMode != null && fastMode == hasFastMode) {
|
||||
player.printError("Fast mode already " + (fastMode ? "enabled" : "disabled") + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasFastMode) {
|
||||
session.setFastMode(false);
|
||||
player.print("Fast mode disabled.");
|
||||
} else {
|
||||
if ("off".equals(newState)) {
|
||||
player.printError("Fast mode already disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.setFastMode(true);
|
||||
player.print("Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/reorder" },
|
||||
usage = "[multi|fast|none]",
|
||||
desc = "Sets the reorder mode of WorldEdit",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/reorder",
|
||||
desc = "Sets the reorder mode of WorldEdit"
|
||||
)
|
||||
@CommandPermissions("worldedit.reorder")
|
||||
public void reorderMode(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
String newState = args.getString(0, null);
|
||||
if (newState == null) {
|
||||
public void reorderMode(Player player, LocalSession session,
|
||||
@Arg(desc = "The reorder mode", def = "")
|
||||
EditSession.ReorderMode reorderMode) throws WorldEditException {
|
||||
if (reorderMode == null) {
|
||||
player.print("The reorder mode is " + session.getReorderMode().getDisplayName());
|
||||
} else {
|
||||
java.util.Optional<EditSession.ReorderMode> reorderModeOptional = EditSession.ReorderMode.getFromDisplayName(newState);
|
||||
if (!reorderModeOptional.isPresent()) {
|
||||
player.printError("Unknown reorder mode!");
|
||||
return;
|
||||
}
|
||||
|
||||
EditSession.ReorderMode reorderMode = reorderModeOptional.get();
|
||||
session.setReorderMode(reorderMode);
|
||||
player.print("The reorder mode is now " + session.getReorderMode().getDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/drawsel" },
|
||||
usage = "[on|off]",
|
||||
desc = "Toggle drawing the current selection",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/drawsel",
|
||||
desc = "Toggle drawing the current selection"
|
||||
)
|
||||
@CommandPermissions("worldedit.drawsel")
|
||||
public void drawSelection(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
public void drawSelection(Player player, LocalSession session,
|
||||
@Arg(desc = "The new draw selection state", def = "")
|
||||
Boolean drawSelection) throws WorldEditException {
|
||||
if (!WorldEdit.getInstance().getConfiguration().serverSideCUI) {
|
||||
throw new DisallowedUsageException("This functionality is disabled in the configuration!");
|
||||
}
|
||||
String newState = args.getString(0, null);
|
||||
if (session.shouldUseServerCUI()) {
|
||||
if ("on".equals(newState)) {
|
||||
player.printError("Server CUI already enabled.");
|
||||
boolean useServerCui = session.shouldUseServerCUI();
|
||||
if (drawSelection != null && drawSelection == useServerCui) {
|
||||
player.printError("Server CUI already " + (useServerCui ? "enabled" : "disabled") + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
if (useServerCui) {
|
||||
session.setUseServerCUI(false);
|
||||
session.updateServerCUI(player);
|
||||
player.print("Server CUI disabled.");
|
||||
} else {
|
||||
if ("off".equals(newState)) {
|
||||
player.printError("Server CUI already disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.setUseServerCUI(true);
|
||||
session.updateServerCUI(player);
|
||||
player.print("Server CUI enabled. This only supports cuboid regions, with a maximum size of 32x32x32.");
|
||||
@ -206,14 +183,14 @@ public class GeneralCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/gmask", "gmask" },
|
||||
usage = "[mask]",
|
||||
desc = "Set the global mask",
|
||||
min = 0,
|
||||
max = -1
|
||||
name = "gmask",
|
||||
aliases = {"/gmask"},
|
||||
desc = "Set the global mask"
|
||||
)
|
||||
@CommandPermissions("worldedit.global-mask")
|
||||
public void gmask(Player player, LocalSession session, @Optional Mask mask) throws WorldEditException {
|
||||
public void gmask(Player player, LocalSession session,
|
||||
@Arg(desc = "The mask to set", def = "")
|
||||
Mask mask) throws WorldEditException {
|
||||
if (mask == null) {
|
||||
session.setMask((Mask) null);
|
||||
player.print("Global mask disabled.");
|
||||
@ -224,11 +201,9 @@ public class GeneralCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/toggleplace", "toggleplace" },
|
||||
usage = "",
|
||||
desc = "Switch between your position and pos1 for placement",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "toggleplace",
|
||||
aliases = {"/toggleplace"},
|
||||
desc = "Switch between your position and pos1 for placement"
|
||||
)
|
||||
public void togglePlace(Player player, LocalSession session) throws WorldEditException {
|
||||
|
||||
@ -240,24 +215,17 @@ public class GeneralCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/searchitem", "/l", "/search", "searchitem" },
|
||||
usage = "<query>",
|
||||
flags = "bi",
|
||||
desc = "Search for an item",
|
||||
help =
|
||||
"Searches for an item.\n" +
|
||||
"Flags:\n" +
|
||||
" -b only search for blocks\n" +
|
||||
" -i only search for items",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "searchitem",
|
||||
aliases = {"/searchitem", "/l", "/search"},
|
||||
desc = "Search for an item"
|
||||
)
|
||||
public void searchItem(Actor actor, CommandContext args) throws WorldEditException {
|
||||
|
||||
String query = args.getString(0).trim().toLowerCase();
|
||||
boolean blocksOnly = args.hasFlag('b');
|
||||
boolean itemsOnly = args.hasFlag('i');
|
||||
|
||||
public void searchItem(Actor actor,
|
||||
@Arg(desc = "Item query")
|
||||
String query,
|
||||
@Switch(name = 'b', desc = "Only search for blocks")
|
||||
boolean blocksOnly,
|
||||
@Switch(name = 'i', desc = "Only search for items")
|
||||
boolean itemsOnly) throws WorldEditException {
|
||||
ItemType type = ItemTypes.get(query);
|
||||
|
||||
if (type != null) {
|
||||
|
@ -19,35 +19,39 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.Logging;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.annotation.Radii;
|
||||
import com.sk89q.worldedit.internal.annotation.Selection;
|
||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||
import com.sk89q.worldedit.util.command.binding.Range;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.binding.Text;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION;
|
||||
|
||||
/**
|
||||
* Commands for the generation of shapes and other objects.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class GenerationCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
@ -63,54 +67,52 @@ public class GenerationCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hcyl" },
|
||||
usage = "<pattern> <radius>[,<radius>] [height]",
|
||||
desc = "Generates a hollow cylinder.",
|
||||
help =
|
||||
"Generates a hollow cylinder.\n" +
|
||||
"By specifying 2 radii, separated by a comma,\n" +
|
||||
"you can generate elliptical cylinders.\n" +
|
||||
"The 1st radius is north/south, the 2nd radius is east/west.",
|
||||
min = 2,
|
||||
max = 3
|
||||
name = "/hcyl",
|
||||
desc = "Generates a hollow cylinder."
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.cylinder")
|
||||
@Logging(PLACEMENT)
|
||||
public void hcyl(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("1") int height) throws WorldEditException {
|
||||
cyl(player, session, editSession, pattern, radiusString, height, true);
|
||||
public int hcyl(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The pattern of blocks to generate")
|
||||
Pattern pattern,
|
||||
@Arg(desc = "The radii of the cylinder. 1st is N/S, 2nd is E/W")
|
||||
@Radii(2)
|
||||
List<Double> radii,
|
||||
@Arg(desc = "The height of the cylinder", def = "1")
|
||||
int height) throws WorldEditException {
|
||||
return cyl(player, session, editSession, pattern, radii, height, true);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/cyl" },
|
||||
usage = "<block> <radius>[,<radius>] [height]",
|
||||
flags = "h",
|
||||
desc = "Generates a cylinder.",
|
||||
help =
|
||||
"Generates a cylinder.\n" +
|
||||
"By specifying 2 radii, separated by a comma,\n" +
|
||||
"you can generate elliptical cylinders.\n" +
|
||||
"The 1st radius is north/south, the 2nd radius is east/west.",
|
||||
min = 2,
|
||||
max = 3
|
||||
name = "/cyl",
|
||||
desc = "Generates a cylinder."
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.cylinder")
|
||||
@Logging(PLACEMENT)
|
||||
public void cyl(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("1") int height, @Switch('h') boolean hollow) throws WorldEditException {
|
||||
String[] radii = radiusString.split(",");
|
||||
public int cyl(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The pattern of blocks to generate")
|
||||
Pattern pattern,
|
||||
@Arg(desc = "The radii of the cylinder. 1st is N/S, 2nd is E/W")
|
||||
@Radii(2)
|
||||
List<Double> radii,
|
||||
@Arg(desc = "The height of the cylinder", def = "1")
|
||||
int height,
|
||||
@Switch(name = 'h', desc = "Make a hollow cylinder")
|
||||
boolean hollow) throws WorldEditException {
|
||||
final double radiusX, radiusZ;
|
||||
switch (radii.length) {
|
||||
switch (radii.size()) {
|
||||
case 1:
|
||||
radiusX = radiusZ = Math.max(1, Double.parseDouble(radii[0]));
|
||||
radiusX = radiusZ = Math.max(1, radii.get(0));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
radiusX = Math.max(1, Double.parseDouble(radii[0]));
|
||||
radiusZ = Math.max(1, Double.parseDouble(radii[1]));
|
||||
radiusX = Math.max(1, radii.get(0));
|
||||
radiusZ = Math.max(1, radii.get(1));
|
||||
break;
|
||||
|
||||
default:
|
||||
player.printError("You must either specify 1 or 2 radius values.");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
worldEdit.checkMaxRadius(radiusX);
|
||||
@ -120,58 +122,57 @@ public class GenerationCommands {
|
||||
BlockVector3 pos = session.getPlacementPosition(player);
|
||||
int affected = editSession.makeCylinder(pos, pattern, radiusX, radiusZ, height, !hollow);
|
||||
player.print(affected + " block(s) have been created.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hsphere" },
|
||||
usage = "<block> <radius>[,<radius>,<radius>] [raised?]",
|
||||
desc = "Generates a hollow sphere.",
|
||||
help =
|
||||
"Generates a hollow sphere.\n" +
|
||||
"By specifying 3 radii, separated by commas,\n" +
|
||||
"you can generate an ellipsoid. The order of the ellipsoid radii\n" +
|
||||
"is north/south, up/down, east/west.",
|
||||
min = 2,
|
||||
max = 3
|
||||
name = "/hsphere",
|
||||
desc = "Generates a hollow sphere."
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.sphere")
|
||||
@Logging(PLACEMENT)
|
||||
public void hsphere(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("false") boolean raised) throws WorldEditException {
|
||||
sphere(player, session, editSession, pattern, radiusString, raised, true);
|
||||
public int hsphere(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The pattern of blocks to generate")
|
||||
Pattern pattern,
|
||||
@Arg(desc = "The radii of the sphere. Order is N/S, U/D, E/W")
|
||||
@Radii(3)
|
||||
List<Double> radii,
|
||||
@Switch(name = 'r', desc = "Raise the bottom of the sphere to the placement position")
|
||||
boolean raised) throws WorldEditException {
|
||||
return sphere(player, session, editSession, pattern, radii, raised, true);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/sphere" },
|
||||
usage = "<block> <radius>[,<radius>,<radius>] [raised?]",
|
||||
flags = "h",
|
||||
desc = "Generates a filled sphere.",
|
||||
help =
|
||||
"Generates a filled sphere.\n" +
|
||||
"By specifying 3 radii, separated by commas,\n" +
|
||||
"you can generate an ellipsoid. The order of the ellipsoid radii\n" +
|
||||
"is north/south, up/down, east/west.",
|
||||
min = 2,
|
||||
max = 3
|
||||
name = "/sphere",
|
||||
desc = "Generates a filled sphere."
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.sphere")
|
||||
@Logging(PLACEMENT)
|
||||
public void sphere(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("false") boolean raised, @Switch('h') boolean hollow) throws WorldEditException {
|
||||
String[] radii = radiusString.split(",");
|
||||
public int sphere(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The pattern of blocks to generate")
|
||||
Pattern pattern,
|
||||
@Arg(desc = "The radii of the sphere. Order is N/S, U/D, E/W")
|
||||
@Radii(3)
|
||||
List<Double> radii,
|
||||
@Switch(name = 'r', desc = "Raise the bottom of the sphere to the placement position")
|
||||
boolean raised,
|
||||
@Switch(name = 'h', desc = "Make a hollow sphere")
|
||||
boolean hollow) throws WorldEditException {
|
||||
final double radiusX, radiusY, radiusZ;
|
||||
switch (radii.length) {
|
||||
switch (radii.size()) {
|
||||
case 1:
|
||||
radiusX = radiusY = radiusZ = Math.max(1, Double.parseDouble(radii[0]));
|
||||
radiusX = radiusY = radiusZ = Math.max(1, radii.get(0));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
radiusX = Math.max(1, Double.parseDouble(radii[0]));
|
||||
radiusY = Math.max(1, Double.parseDouble(radii[1]));
|
||||
radiusZ = Math.max(1, Double.parseDouble(radii[2]));
|
||||
radiusX = Math.max(1, radii.get(0));
|
||||
radiusY = Math.max(1, radii.get(1));
|
||||
radiusZ = Math.max(1, radii.get(2));
|
||||
break;
|
||||
|
||||
default:
|
||||
player.printError("You must either specify 1 or 3 radius values.");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
worldEdit.checkMaxRadius(radiusX);
|
||||
@ -186,98 +187,102 @@ public class GenerationCommands {
|
||||
int affected = editSession.makeSphere(pos, pattern, radiusX, radiusY, radiusZ, !hollow);
|
||||
player.findFreePosition();
|
||||
player.print(affected + " block(s) have been created.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "forestgen" },
|
||||
usage = "[size] [type] [density]",
|
||||
desc = "Generate a forest",
|
||||
min = 0,
|
||||
max = 3
|
||||
name = "forestgen",
|
||||
desc = "Generate a forest"
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.forest")
|
||||
@Logging(POSITION)
|
||||
public void forestGen(Player player, LocalSession session, EditSession editSession, @Optional("10") int size,
|
||||
@Optional("tree") TreeType type, @Optional("5") @Range(min = 0, max = 100) double density) throws WorldEditException {
|
||||
public int forestGen(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The size of the forest, in blocks", def = "10")
|
||||
int size,
|
||||
@Arg(desc = "The type of forest", def = "tree")
|
||||
TreeType type,
|
||||
@Arg(desc = "The density of the forest, between 0 and 100", def = "5")
|
||||
double density) throws WorldEditException {
|
||||
if (density < 0 || density > 100) {
|
||||
throw new IllegalArgumentException("Density must be between 0 and 100");
|
||||
}
|
||||
density = density / 100;
|
||||
int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, type);
|
||||
player.print(affected + " trees created.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "pumpkins" },
|
||||
usage = "[size]",
|
||||
desc = "Generate pumpkin patches",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "pumpkins",
|
||||
desc = "Generate pumpkin patches"
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.pumpkins")
|
||||
@Logging(POSITION)
|
||||
public void pumpkins(Player player, LocalSession session, EditSession editSession, @Optional("10") int apothem) throws WorldEditException {
|
||||
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), apothem);
|
||||
public int pumpkins(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The size of the patch", def = "10")
|
||||
int size) throws WorldEditException {
|
||||
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), size);
|
||||
player.print(affected + " pumpkin patches created.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hpyramid" },
|
||||
usage = "<block> <size>",
|
||||
desc = "Generate a hollow pyramid",
|
||||
min = 2,
|
||||
max = 2
|
||||
name = "/hpyramid",
|
||||
desc = "Generate a hollow pyramid"
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.pyramid")
|
||||
@Logging(PLACEMENT)
|
||||
public void hollowPyramid(Player player, LocalSession session, EditSession editSession, Pattern pattern, @Range(min = 1) int size) throws WorldEditException {
|
||||
pyramid(player, session, editSession, pattern, size, true);
|
||||
public int hollowPyramid(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The pattern of blocks to set")
|
||||
Pattern pattern,
|
||||
@Arg(desc = "The size of the pyramid")
|
||||
int size) throws WorldEditException {
|
||||
return pyramid(player, session, editSession, pattern, size, true);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/pyramid" },
|
||||
usage = "<block> <size>",
|
||||
flags = "h",
|
||||
desc = "Generate a filled pyramid",
|
||||
min = 2,
|
||||
max = 2
|
||||
name = "/pyramid",
|
||||
desc = "Generate a filled pyramid"
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.pyramid")
|
||||
@Logging(PLACEMENT)
|
||||
public void pyramid(Player player, LocalSession session, EditSession editSession, Pattern pattern, @Range(min = 1) int size, @Switch('h') boolean hollow) throws WorldEditException {
|
||||
public int pyramid(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The pattern of blocks to set")
|
||||
Pattern pattern,
|
||||
@Arg(desc = "The size of the pyramid")
|
||||
int size,
|
||||
@Switch(name = 'h', desc = "Make a hollow pyramid")
|
||||
boolean hollow) throws WorldEditException {
|
||||
BlockVector3 pos = session.getPlacementPosition(player);
|
||||
worldEdit.checkMaxRadius(size);
|
||||
int affected = editSession.makePyramid(pos, pattern, size, !hollow);
|
||||
player.findFreePosition();
|
||||
player.print(affected + " block(s) have been created.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/generate", "/gen", "/g" },
|
||||
usage = "<block> <expression>",
|
||||
name = "/generate",
|
||||
aliases = { "/gen", "/g" },
|
||||
desc = "Generates a shape according to a formula.",
|
||||
help =
|
||||
"Generates a shape according to a formula that is expected to\n" +
|
||||
"return positive numbers (true) if the point is inside the shape\n" +
|
||||
"Optionally set type/data to the desired block.\n" +
|
||||
"Flags:\n" +
|
||||
" -h to generate a hollow shape\n" +
|
||||
" -r to use raw minecraft coordinates\n" +
|
||||
" -o is like -r, except offset from placement.\n" +
|
||||
" -c is like -r, except offset selection center.\n" +
|
||||
"If neither -r nor -o is given, the selection is mapped to -1..1\n" +
|
||||
"See also tinyurl.com/wesyntax.",
|
||||
flags = "hroc",
|
||||
min = 2,
|
||||
max = -1
|
||||
descFooter = "See also https://tinyurl.com/wesyntax."
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.shape")
|
||||
@Logging(ALL)
|
||||
public void generate(Player player, LocalSession session, EditSession editSession,
|
||||
public int generate(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region,
|
||||
@Arg(desc = "The pattern of blocks to set")
|
||||
Pattern pattern,
|
||||
@Text String expression,
|
||||
@Switch('h') boolean hollow,
|
||||
@Switch('r') boolean useRawCoords,
|
||||
@Switch('o') boolean offset,
|
||||
@Switch('c') boolean offsetCenter) throws WorldEditException {
|
||||
@Arg(desc = "Expression to test block placement locations and set block type", variable = true)
|
||||
List<String> expression,
|
||||
@Switch(name = 'h', desc = "Generate a hollow shape")
|
||||
boolean hollow,
|
||||
@Switch(name = 'r', desc = "Use the game's coordinate origin")
|
||||
boolean useRawCoords,
|
||||
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
|
||||
boolean offset,
|
||||
@Switch(name = 'c', desc = "Use the selection's center as origin")
|
||||
boolean offsetCenter) throws WorldEditException {
|
||||
|
||||
final Vector3 zero;
|
||||
Vector3 unit;
|
||||
@ -307,43 +312,38 @@ public class GenerationCommands {
|
||||
}
|
||||
|
||||
try {
|
||||
final int affected = editSession.makeShape(region, zero, unit, pattern, expression, hollow, session.getTimeout());
|
||||
final int affected = editSession.makeShape(region, zero, unit, pattern, String.join(" ", expression), hollow, session.getTimeout());
|
||||
player.findFreePosition();
|
||||
player.print(affected + " block(s) have been created.");
|
||||
return affected;
|
||||
} catch (ExpressionException e) {
|
||||
player.printError(e.getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/generatebiome", "/genbiome", "/gb" },
|
||||
usage = "<biome> <expression>",
|
||||
name = "/generatebiome",
|
||||
aliases = { "/genbiome", "/gb" },
|
||||
desc = "Sets biome according to a formula.",
|
||||
help =
|
||||
"Generates a shape according to a formula that is expected to\n" +
|
||||
"return positive numbers (true) if the point is inside the shape\n" +
|
||||
"Sets the biome of blocks in that shape.\n" +
|
||||
"Flags:\n" +
|
||||
" -h to generate a hollow shape\n" +
|
||||
" -r to use raw minecraft coordinates\n" +
|
||||
" -o is like -r, except offset from placement.\n" +
|
||||
" -c is like -r, except offset selection center.\n" +
|
||||
"If neither -r nor -o is given, the selection is mapped to -1..1\n" +
|
||||
"See also tinyurl.com/wesyntax.",
|
||||
flags = "hroc",
|
||||
min = 2,
|
||||
max = -1
|
||||
descFooter = "See also https://tinyurl.com/wesyntax."
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.shape.biome")
|
||||
@Logging(ALL)
|
||||
public void generateBiome(Player player, LocalSession session, EditSession editSession,
|
||||
public int generateBiome(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region,
|
||||
@Arg(desc = "The biome type to set")
|
||||
BiomeType target,
|
||||
@Text String expression,
|
||||
@Switch('h') boolean hollow,
|
||||
@Switch('r') boolean useRawCoords,
|
||||
@Switch('o') boolean offset,
|
||||
@Switch('c') boolean offsetCenter) throws WorldEditException {
|
||||
@Arg(desc = "Expression to test block placement locations and set biome type", variable = true)
|
||||
List<String> expression,
|
||||
@Switch(name = 'h', desc = "Generate a hollow shape")
|
||||
boolean hollow,
|
||||
@Switch(name = 'r', desc = "Use the game's coordinate origin")
|
||||
boolean useRawCoords,
|
||||
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
|
||||
boolean offset,
|
||||
@Switch(name = 'c', desc = "Use the selection's center as origin")
|
||||
boolean offsetCenter) throws WorldEditException {
|
||||
final Vector3 zero;
|
||||
Vector3 unit;
|
||||
|
||||
@ -372,11 +372,13 @@ public class GenerationCommands {
|
||||
}
|
||||
|
||||
try {
|
||||
final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow, session.getTimeout());
|
||||
final int affected = editSession.makeBiomeShape(region, zero, unit, target, String.join(" ", expression), hollow, session.getTimeout());
|
||||
player.findFreePosition();
|
||||
player.print("" + affected + " columns affected.");
|
||||
return affected;
|
||||
} catch (ExpressionException e) {
|
||||
player.printError(e.getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,20 +19,23 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Commands to undo, redo, and clear history.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class HistoryCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
@ -48,28 +51,29 @@ public class HistoryCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/undo", "undo" },
|
||||
usage = "[times] [player]",
|
||||
desc = "Undoes the last action",
|
||||
min = 0,
|
||||
max = 2
|
||||
name = "undo",
|
||||
aliases = { "/undo" },
|
||||
desc = "Undoes the last action (from history)"
|
||||
)
|
||||
@CommandPermissions("worldedit.history.undo")
|
||||
public void undo(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
int times = Math.max(1, args.getInteger(0, 1));
|
||||
public void undo(Player player, LocalSession session,
|
||||
@Arg(desc = "Number of undoes to perform", def = "1")
|
||||
int times,
|
||||
@Arg(name = "player", desc = "Undo this player's operations", def = "")
|
||||
String playerName) throws WorldEditException {
|
||||
times = Math.max(1, times);
|
||||
for (int i = 0; i < times; ++i) {
|
||||
EditSession undone;
|
||||
if (args.argsLength() < 2) {
|
||||
undone = session.undo(session.getBlockBag(player), player);
|
||||
} else {
|
||||
LocalSession undoSession = session;
|
||||
if (playerName != null) {
|
||||
player.checkPermission("worldedit.history.undo.other");
|
||||
LocalSession sess = worldEdit.getSessionManager().findByName(args.getString(1));
|
||||
LocalSession sess = worldEdit.getSessionManager().findByName(playerName);
|
||||
if (sess == null) {
|
||||
player.printError("Unable to find session for " + args.getString(1));
|
||||
player.printError("Unable to find session for " + playerName);
|
||||
break;
|
||||
}
|
||||
undone = sess.undo(session.getBlockBag(player), player);
|
||||
undoSession = session;
|
||||
}
|
||||
EditSession undone = undoSession.undo(undoSession.getBlockBag(player), player);
|
||||
if (undone != null) {
|
||||
player.print("Undo successful.");
|
||||
worldEdit.flushBlockBag(player, undone);
|
||||
@ -81,30 +85,29 @@ public class HistoryCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/redo", "redo" },
|
||||
usage = "[times] [player]",
|
||||
desc = "Redoes the last action (from history)",
|
||||
min = 0,
|
||||
max = 2
|
||||
name = "redo",
|
||||
aliases = { "/redo" },
|
||||
desc = "Redoes the last action (from history)"
|
||||
)
|
||||
@CommandPermissions("worldedit.history.redo")
|
||||
public void redo(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
int times = Math.max(1, args.getInteger(0, 1));
|
||||
|
||||
public void redo(Player player, LocalSession session,
|
||||
@Arg(desc = "Number of redoes to perform", def = "1")
|
||||
int times,
|
||||
@Arg(name = "player", desc = "Redo this player's operations", def = "")
|
||||
String playerName) throws WorldEditException {
|
||||
times = Math.max(1, times);
|
||||
for (int i = 0; i < times; ++i) {
|
||||
EditSession redone;
|
||||
if (args.argsLength() < 2) {
|
||||
redone = session.redo(session.getBlockBag(player), player);
|
||||
} else {
|
||||
LocalSession redoSession = session;
|
||||
if (playerName != null) {
|
||||
player.checkPermission("worldedit.history.redo.other");
|
||||
LocalSession sess = worldEdit.getSessionManager().findByName(args.getString(1));
|
||||
LocalSession sess = worldEdit.getSessionManager().findByName(playerName);
|
||||
if (sess == null) {
|
||||
player.printError("Unable to find session for " + args.getString(1));
|
||||
player.printError("Unable to find session for " + playerName);
|
||||
break;
|
||||
}
|
||||
redone = sess.redo(session.getBlockBag(player), player);
|
||||
redoSession = session;
|
||||
}
|
||||
EditSession redone = redoSession.redo(redoSession.getBlockBag(player), player);
|
||||
if (redone != null) {
|
||||
player.print("Redo successful.");
|
||||
worldEdit.flushBlockBag(player, redone);
|
||||
@ -116,11 +119,9 @@ public class HistoryCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/clearhistory", "clearhistory" },
|
||||
usage = "",
|
||||
desc = "Clear your history",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "clearhistory",
|
||||
aliases = { "/clearhistory" },
|
||||
desc = "Clear your history"
|
||||
)
|
||||
@CommandPermissions("worldedit.history.clear")
|
||||
public void clearHistory(Player player, LocalSession session) throws WorldEditException {
|
||||
|
@ -19,23 +19,26 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.Logging;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION;
|
||||
|
||||
/**
|
||||
* Commands for moving the player around.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class NavigationCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
@ -51,80 +54,78 @@ public class NavigationCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "unstuck", "!" },
|
||||
usage = "",
|
||||
desc = "Escape from being stuck inside a block",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "unstuck",
|
||||
aliases = { "!" },
|
||||
desc = "Escape from being stuck inside a block"
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.unstuck")
|
||||
public void unstuck(Player player) throws WorldEditException {
|
||||
player.print("There you go!");
|
||||
player.findFreePosition();
|
||||
player.print("There you go!");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "ascend", "asc" },
|
||||
usage = "[# of levels]",
|
||||
desc = "Go up a floor",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "ascend",
|
||||
aliases = { "asc" },
|
||||
desc = "Go up a floor"
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.ascend")
|
||||
public void ascend(Player player, @Optional("1") int levelsToAscend) throws WorldEditException {
|
||||
public void ascend(Player player,
|
||||
@Arg(desc = "# of levels to ascend", def = "1")
|
||||
int levels) throws WorldEditException {
|
||||
int ascentLevels = 0;
|
||||
while (player.ascendLevel()) {
|
||||
++ascentLevels;
|
||||
if (levelsToAscend == ascentLevels) {
|
||||
if (levels == ascentLevels) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ascentLevels == 0) {
|
||||
player.printError("No free spot above you found.");
|
||||
} else {
|
||||
player.print((ascentLevels != 1) ? "Ascended " + Integer.toString(ascentLevels) + " levels." : "Ascended a level.");
|
||||
player.print((ascentLevels != 1) ? "Ascended " + ascentLevels + " levels." : "Ascended a level.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "descend", "desc" },
|
||||
usage = "[# of floors]",
|
||||
desc = "Go down a floor",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "descend",
|
||||
aliases = { "desc" },
|
||||
desc = "Go down a floor"
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.descend")
|
||||
public void descend(Player player, @Optional("1") int levelsToDescend) throws WorldEditException {
|
||||
public void descend(Player player,
|
||||
@Arg(desc = "# of levels to descend", def = "1")
|
||||
int levels) throws WorldEditException {
|
||||
int descentLevels = 0;
|
||||
while (player.descendLevel()) {
|
||||
++descentLevels;
|
||||
if (levelsToDescend == descentLevels) {
|
||||
if (levels == descentLevels) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (descentLevels == 0) {
|
||||
player.printError("No free spot below you found.");
|
||||
} else {
|
||||
player.print((descentLevels != 1) ? "Descended " + Integer.toString(descentLevels) + " levels." : "Descended a level.");
|
||||
player.print((descentLevels != 1) ? "Descended " + descentLevels + " levels." : "Descended a level.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "ceil" },
|
||||
usage = "[clearance]",
|
||||
desc = "Go to the celing",
|
||||
flags = "fg",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "ceil",
|
||||
desc = "Go to the ceiling"
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.ceiling")
|
||||
@Logging(POSITION)
|
||||
public void ceiling(Player player, CommandContext args) throws WorldEditException {
|
||||
public void ceiling(Player player,
|
||||
@Arg(desc = "# of blocks to leave above you", def = "0")
|
||||
int clearance,
|
||||
@Switch(name = 'f', desc = "Force using flight to keep you still")
|
||||
boolean forceFlight,
|
||||
@Switch(name = 'g', desc = "Force using glass to keep you still")
|
||||
boolean forceGlass) throws WorldEditException {
|
||||
clearance = Math.max(0, clearance);
|
||||
|
||||
final int clearance = args.argsLength() > 0 ?
|
||||
Math.max(0, args.getInteger(0)) : 0;
|
||||
|
||||
final boolean alwaysGlass = getAlwaysGlass(args);
|
||||
boolean alwaysGlass = getAlwaysGlass(forceFlight, forceGlass);
|
||||
if (player.ascendToCeiling(clearance, alwaysGlass)) {
|
||||
player.print("Whoosh!");
|
||||
} else {
|
||||
@ -133,11 +134,8 @@ public class NavigationCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "thru" },
|
||||
usage = "",
|
||||
desc = "Passthrough walls",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "thru",
|
||||
desc = "Pass through walls"
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.thru.command")
|
||||
public void thru(Player player) throws WorldEditException {
|
||||
@ -149,11 +147,9 @@ public class NavigationCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "jumpto", "j" },
|
||||
usage = "",
|
||||
desc = "Teleport to a location",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "jumpto",
|
||||
aliases = { "j" },
|
||||
desc = "Teleport to a location"
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.jumpto.command")
|
||||
public void jumpTo(Player player) throws WorldEditException {
|
||||
@ -168,19 +164,19 @@ public class NavigationCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "up" },
|
||||
usage = "<block>",
|
||||
desc = "Go upwards some distance",
|
||||
flags = "fg",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "up",
|
||||
desc = "Go upwards some distance"
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.up")
|
||||
@Logging(POSITION)
|
||||
public void up(Player player, CommandContext args) throws WorldEditException {
|
||||
final int distance = args.getInteger(0);
|
||||
|
||||
final boolean alwaysGlass = getAlwaysGlass(args);
|
||||
public void up(Player player,
|
||||
@Arg(desc = "Distance to go upwards")
|
||||
int distance,
|
||||
@Switch(name = 'f', desc = "Force using flight to keep you still")
|
||||
boolean forceFlight,
|
||||
@Switch(name = 'g', desc = "Force using glass to keep you still")
|
||||
boolean forceGlass) throws WorldEditException {
|
||||
boolean alwaysGlass = getAlwaysGlass(forceFlight, forceGlass);
|
||||
if (player.ascendUpwards(distance, alwaysGlass)) {
|
||||
player.print("Whoosh!");
|
||||
} else {
|
||||
@ -191,15 +187,13 @@ public class NavigationCommands {
|
||||
/**
|
||||
* Helper function for /up and /ceil.
|
||||
*
|
||||
* @param args The {@link CommandContext} to extract the flags from.
|
||||
* @param forceFlight if flight should be used, rather than the default config option
|
||||
* @param forceGlass if glass should always be placed, rather than the default config option
|
||||
* @return true, if glass should always be put under the player
|
||||
*/
|
||||
private boolean getAlwaysGlass(CommandContext args) {
|
||||
private boolean getAlwaysGlass(boolean forceFlight, boolean forceGlass) {
|
||||
final LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
final boolean forceFlight = args.hasFlag('f');
|
||||
final boolean forceGlass = args.hasFlag('g');
|
||||
|
||||
return forceGlass || (config.navigationUseGlass && !forceFlight);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.command.factory.ItemUseFactory;
|
||||
import com.sk89q.worldedit.command.factory.ReplaceFactory;
|
||||
import com.sk89q.worldedit.command.factory.TreeGeneratorFactory;
|
||||
import com.sk89q.worldedit.command.util.PermissionCondition;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.factory.Paint;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.regions.factory.RegionFactory;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import com.sk89q.worldedit.internal.command.CommandRegistrationHandler;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.CommandParameters;
|
||||
import org.enginehub.piston.DefaultCommandManagerService;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
import org.enginehub.piston.part.CommandArgument;
|
||||
import org.enginehub.piston.part.SubCommandPart;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.enginehub.piston.part.CommandParts.arg;
|
||||
|
||||
@CommandContainer
|
||||
public class PaintBrushCommands {
|
||||
|
||||
private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("shape"), TextComponent.of("The shape of the region"))
|
||||
.defaultsTo(ImmutableList.of())
|
||||
.ofTypes(ImmutableList.of(Key.of(RegionFactory.class)))
|
||||
.build();
|
||||
|
||||
private static final CommandArgument RADIUS = arg(TranslatableComponent.of("radius"), TextComponent.of("The size of the brush"))
|
||||
.defaultsTo(ImmutableList.of("5"))
|
||||
.ofTypes(ImmutableList.of(Key.of(double.class)))
|
||||
.build();
|
||||
|
||||
private static final CommandArgument DENSITY = arg(TranslatableComponent.of("density"), TextComponent.of("The density of the brush"))
|
||||
.defaultsTo(ImmutableList.of("20"))
|
||||
.ofTypes(ImmutableList.of(Key.of(double.class)))
|
||||
.build();
|
||||
|
||||
public static void register(CommandManager commandManager, CommandRegistrationHandler registration) {
|
||||
commandManager.register("paint", builder -> {
|
||||
builder.description(TextComponent.of("Paint brush, apply a function to a surface"));
|
||||
builder.action(org.enginehub.piston.Command.Action.NULL_ACTION);
|
||||
|
||||
CommandManager manager = DefaultCommandManagerService.getInstance()
|
||||
.newCommandManager();
|
||||
registration.register(
|
||||
manager,
|
||||
PaintBrushCommandsRegistration.builder(),
|
||||
new PaintBrushCommands()
|
||||
);
|
||||
|
||||
builder.condition(new PermissionCondition(ImmutableSet.of("worldedit.brush.paint")));
|
||||
|
||||
builder.addParts(REGION_FACTORY, RADIUS, DENSITY);
|
||||
builder.addPart(SubCommandPart.builder(TranslatableComponent.of("type"), TextComponent.of("Type of brush to use"))
|
||||
.withCommands(manager.getAllCommands().collect(Collectors.toList()))
|
||||
.required()
|
||||
.build());
|
||||
});
|
||||
}
|
||||
|
||||
private void setPaintBrush(CommandParameters parameters, Player player, LocalSession localSession,
|
||||
Contextual<? extends RegionFunction> generatorFactory) throws WorldEditException {
|
||||
double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class));
|
||||
double density = requireNonNull(DENSITY.value(parameters).asSingle(double.class)) / 100;
|
||||
RegionFactory regionFactory = REGION_FACTORY.value(parameters).asSingle(RegionFactory.class);
|
||||
BrushCommands.setOperationBasedBrush(player, localSession, radius,
|
||||
new Paint(generatorFactory, density), regionFactory, "worldedit.brush.paint");
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "forest",
|
||||
desc = "Plant trees"
|
||||
)
|
||||
public void forest(CommandParameters parameters,
|
||||
Player player, LocalSession localSession,
|
||||
@Arg(desc = "The type of tree to plant")
|
||||
TreeGenerator.TreeType type) throws WorldEditException {
|
||||
setPaintBrush(parameters, player, localSession, new TreeGeneratorFactory(type));
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "item",
|
||||
desc = "Use an item"
|
||||
)
|
||||
public void item(CommandParameters parameters,
|
||||
Player player, LocalSession localSession,
|
||||
@Arg(desc = "The type of item to use")
|
||||
BaseItem item) throws WorldEditException {
|
||||
setPaintBrush(parameters, player, localSession, new ItemUseFactory(item));
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "set",
|
||||
desc = "Place a block"
|
||||
)
|
||||
public void set(CommandParameters parameters,
|
||||
Player player, LocalSession localSession,
|
||||
@Arg(desc = "The pattern of blocks to use")
|
||||
Pattern pattern) throws WorldEditException {
|
||||
setPaintBrush(parameters, player, localSession, new ReplaceFactory(pattern));
|
||||
}
|
||||
|
||||
}
|
@ -19,31 +19,26 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.ORIENTATION_REGION;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
import static com.sk89q.worldedit.regions.Regions.asFlatRegion;
|
||||
import static com.sk89q.worldedit.regions.Regions.maximumBlockY;
|
||||
import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.Logging;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.GroundFunction;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.block.BlockReplace;
|
||||
import com.sk89q.worldedit.function.generator.FloraGenerator;
|
||||
import com.sk89q.worldedit.function.generator.ForestGenerator;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.NoiseFilter2D;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.visitor.LayerVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
||||
import com.sk89q.worldedit.internal.annotation.Selection;
|
||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||
@ -58,56 +53,79 @@ import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||
import com.sk89q.worldedit.util.command.binding.Range;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.binding.Text;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.ORIENTATION_REGION;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
|
||||
import static com.sk89q.worldedit.regions.Regions.asFlatRegion;
|
||||
import static com.sk89q.worldedit.regions.Regions.maximumBlockY;
|
||||
import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
|
||||
|
||||
/**
|
||||
* Commands that operate on regions.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class RegionCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public RegionCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
public RegionCommands() {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/line" },
|
||||
usage = "<pattern> [thickness]",
|
||||
name = "/set",
|
||||
desc = "Sets all the blocks in the region"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.set")
|
||||
@Logging(REGION)
|
||||
public int set(Player player, EditSession editSession,
|
||||
@Selection Region region,
|
||||
@Arg(desc = "The patter of blocks to set")
|
||||
Pattern pattern) {
|
||||
RegionFunction set = new BlockReplace(editSession, pattern);
|
||||
RegionVisitor visitor = new RegionVisitor(region, set);
|
||||
|
||||
Operations.completeBlindly(visitor);
|
||||
List<String> messages = Lists.newArrayList();
|
||||
visitor.addStatusMessages(messages);
|
||||
if (messages.isEmpty()) {
|
||||
player.print("Operation completed.");
|
||||
} else {
|
||||
player.print("Operation completed (" + Joiner.on(", ").join(messages) + ").");
|
||||
}
|
||||
|
||||
return visitor.getAffected();
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "/line",
|
||||
desc = "Draws a line segment between cuboid selection corners",
|
||||
help =
|
||||
"Draws a line segment between cuboid selection corners.\n" +
|
||||
"Can only be used with cuboid selections.\n" +
|
||||
"Flags:\n" +
|
||||
" -h generates only a shell",
|
||||
flags = "h",
|
||||
min = 1,
|
||||
max = 2
|
||||
descFooter = "Can only be used with a cuboid selection"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.line")
|
||||
@Logging(REGION)
|
||||
public void line(Player player, EditSession editSession,
|
||||
public int line(Player player, EditSession editSession,
|
||||
@Selection Region region,
|
||||
@Arg(desc = "The pattern of blocks to place")
|
||||
Pattern pattern,
|
||||
@Optional("0") @Range(min = 0) int thickness,
|
||||
@Switch('h') boolean shell) throws WorldEditException {
|
||||
|
||||
@Arg(desc = "The thickness of the line", def = "0")
|
||||
int thickness,
|
||||
@Switch(name = 'h', desc = "Generate only a shell")
|
||||
boolean shell) throws WorldEditException {
|
||||
if (!(region instanceof CuboidRegion)) {
|
||||
player.printError("//line only works with cuboid selections");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
checkArgument(thickness >= 0, "Thickness must be >= 0");
|
||||
|
||||
CuboidRegion cuboidregion = (CuboidRegion) region;
|
||||
BlockVector3 pos1 = cuboidregion.getPos1();
|
||||
@ -115,32 +133,29 @@ public class RegionCommands {
|
||||
int blocksChanged = editSession.drawLine(pattern, pos1, pos2, thickness, !shell);
|
||||
|
||||
player.print(blocksChanged + " block(s) have been changed.");
|
||||
return blocksChanged;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/curve" },
|
||||
usage = "<pattern> [thickness]",
|
||||
name = "/curve",
|
||||
desc = "Draws a spline through selected points",
|
||||
help =
|
||||
"Draws a spline through selected points.\n" +
|
||||
"Can only be used with convex polyhedral selections.\n" +
|
||||
"Flags:\n" +
|
||||
" -h generates only a shell",
|
||||
flags = "h",
|
||||
min = 1,
|
||||
max = 2
|
||||
descFooter = "Can only be used with a convex polyhedral selection"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.curve")
|
||||
@Logging(REGION)
|
||||
public void curve(Player player, EditSession editSession,
|
||||
public int curve(Player player, EditSession editSession,
|
||||
@Selection Region region,
|
||||
@Arg(desc = "The pattern of blocks to place")
|
||||
Pattern pattern,
|
||||
@Optional("0") @Range(min = 0) int thickness,
|
||||
@Switch('h') boolean shell) throws WorldEditException {
|
||||
@Arg(desc = "The thickness of the curve", def = "0")
|
||||
int thickness,
|
||||
@Switch(name = 'h', desc = "Generate only a shell")
|
||||
boolean shell) throws WorldEditException {
|
||||
if (!(region instanceof ConvexPolyhedralRegion)) {
|
||||
player.printError("//curve only works with convex polyhedral selections");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
checkArgument(thickness >= 0, "Thickness must be >= 0");
|
||||
|
||||
ConvexPolyhedralRegion cpregion = (ConvexPolyhedralRegion) region;
|
||||
List<BlockVector3> vectors = new ArrayList<>(cpregion.getVertices());
|
||||
@ -148,139 +163,140 @@ public class RegionCommands {
|
||||
int blocksChanged = editSession.drawSpline(pattern, vectors, 0, 0, 0, 10, thickness, !shell);
|
||||
|
||||
player.print(blocksChanged + " block(s) have been changed.");
|
||||
return blocksChanged;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/replace", "/re", "/rep" },
|
||||
usage = "[from-block] <to-block>",
|
||||
desc = "Replace all blocks in the selection with another",
|
||||
flags = "f",
|
||||
min = 1,
|
||||
max = 2
|
||||
name = "/replace",
|
||||
aliases = { "/re", "/rep" },
|
||||
desc = "Replace all blocks in the selection with another"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.replace")
|
||||
@Logging(REGION)
|
||||
public void replace(Player player, EditSession editSession, @Selection Region region, @Optional Mask from, Pattern to) throws WorldEditException {
|
||||
public int replace(Player player, EditSession editSession, @Selection Region region,
|
||||
@Arg(desc = "The mask representing blocks to replace", def = "")
|
||||
Mask from,
|
||||
@Arg(desc = "The pattern of blocks to replace with")
|
||||
Pattern to) throws WorldEditException {
|
||||
if (from == null) {
|
||||
from = new ExistingBlockMask(editSession);
|
||||
}
|
||||
int affected = editSession.replaceBlocks(region, from, to);
|
||||
player.print(affected + " block(s) have been replaced.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/overlay" },
|
||||
usage = "<pattern>",
|
||||
desc = "Set a block on top of blocks in the region",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "/overlay",
|
||||
desc = "Set a block on top of blocks in the region"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.overlay")
|
||||
@Logging(REGION)
|
||||
public void overlay(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
|
||||
public int overlay(Player player, EditSession editSession, @Selection Region region,
|
||||
@Arg(desc = "The pattern of blocks to overlay")
|
||||
Pattern pattern) throws WorldEditException {
|
||||
int affected = editSession.overlayCuboidBlocks(region, pattern);
|
||||
player.print(affected + " block(s) have been overlaid.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/center", "/middle" },
|
||||
usage = "<pattern>",
|
||||
desc = "Set the center block(s)",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "/center",
|
||||
aliases = { "/middle" },
|
||||
desc = "Set the center block(s)"
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.region.center")
|
||||
public void center(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
|
||||
public int center(Player player, EditSession editSession, @Selection Region region,
|
||||
@Arg(desc = "The pattern of blocks to set")
|
||||
Pattern pattern) throws WorldEditException {
|
||||
int affected = editSession.center(region, pattern);
|
||||
player.print("Center set ("+ affected + " blocks changed)");
|
||||
player.print("Center set (" + affected + " block(s) changed)");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/naturalize" },
|
||||
usage = "",
|
||||
desc = "3 layers of dirt on top then rock below",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "/naturalize",
|
||||
desc = "3 layers of dirt on top then rock below"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.naturalize")
|
||||
@Logging(REGION)
|
||||
public void naturalize(Player player, EditSession editSession, @Selection Region region) throws WorldEditException {
|
||||
public int naturalize(Player player, EditSession editSession, @Selection Region region) throws WorldEditException {
|
||||
int affected = editSession.naturalizeCuboidBlocks(region);
|
||||
player.print(affected + " block(s) have been made to look more natural.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/walls" },
|
||||
usage = "<pattern>",
|
||||
desc = "Build the four sides of the selection",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "/walls",
|
||||
desc = "Build the four sides of the selection"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.walls")
|
||||
@Logging(REGION)
|
||||
public void walls(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
|
||||
public int walls(Player player, EditSession editSession, @Selection Region region,
|
||||
@Arg(desc = "The pattern of blocks to set")
|
||||
Pattern pattern) throws WorldEditException {
|
||||
int affected = editSession.makeWalls(region, pattern);
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/faces", "/outline" },
|
||||
usage = "<pattern>",
|
||||
desc = "Build the walls, ceiling, and floor of a selection",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "/faces",
|
||||
aliases = { "/outline" },
|
||||
desc = "Build the walls, ceiling, and floor of a selection"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.faces")
|
||||
@Logging(REGION)
|
||||
public void faces(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
|
||||
public int faces(Player player, EditSession editSession, @Selection Region region,
|
||||
@Arg(desc = "The pattern of blocks to set")
|
||||
Pattern pattern) throws WorldEditException {
|
||||
int affected = editSession.makeCuboidFaces(region, pattern);
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/smooth" },
|
||||
usage = "[iterations] [filter]",
|
||||
name = "/smooth",
|
||||
desc = "Smooth the elevation in the selection",
|
||||
help =
|
||||
"Smooths the elevation in the selection.\n" +
|
||||
"Optionally, restricts the height map to a set of blocks specified with mask syntax.\n" +
|
||||
"For example, '//smooth 1 grass_block,dirt,stone' would only smooth natural surface terrain.",
|
||||
min = 0,
|
||||
max = 2
|
||||
descFooter = "Example: '//smooth 1 grass_block,dirt,stone' would only smooth natural surface terrain."
|
||||
)
|
||||
@CommandPermissions("worldedit.region.smooth")
|
||||
@Logging(REGION)
|
||||
public void smooth(Player player, EditSession editSession, @Selection Region region, @Optional("1") int iterations, @Optional Mask mask) throws WorldEditException {
|
||||
public int smooth(Player player, EditSession editSession, @Selection Region region,
|
||||
@Arg(desc = "# of iterations to perform", def = "1")
|
||||
int iterations,
|
||||
@Arg(desc = "The mask of blocks to use as the height map", def = "")
|
||||
Mask mask) throws WorldEditException {
|
||||
HeightMap heightMap = new HeightMap(editSession, region, mask);
|
||||
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
|
||||
int affected = heightMap.applyFilter(filter, iterations);
|
||||
player.print("Terrain's height map smoothed. " + affected + " block(s) changed.");
|
||||
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/move" },
|
||||
usage = "[count] [direction] [leave-id]",
|
||||
flags = "sa",
|
||||
desc = "Move the contents of the selection",
|
||||
help =
|
||||
"Moves the contents of the selection.\n" +
|
||||
"The -s flag shifts the selection to the target location.\n" +
|
||||
"The -a flag skips air blocks.\n" +
|
||||
"Optionally fills the old location with <leave-id>.",
|
||||
min = 0,
|
||||
max = 3
|
||||
name = "/move",
|
||||
desc = "Move the contents of the selection"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.move")
|
||||
@Logging(ORIENTATION_REGION)
|
||||
public void move(Player player, EditSession editSession, LocalSession session,
|
||||
public int move(Player player, EditSession editSession, LocalSession session,
|
||||
@Selection Region region,
|
||||
@Optional("1") @Range(min = 1) int count,
|
||||
@Optional(Direction.AIM) @Direction(includeDiagonals = true) BlockVector3 direction,
|
||||
@Optional("air") Pattern replace,
|
||||
@Switch('s') boolean moveSelection,
|
||||
@Switch('a') boolean ignoreAirBlocks) throws WorldEditException {
|
||||
@Arg(desc = "# of blocks to move", def = "1")
|
||||
int count,
|
||||
@Arg(desc = "The direction to move", def = Direction.AIM)
|
||||
@Direction(includeDiagonals = true)
|
||||
BlockVector3 direction,
|
||||
@Arg(desc = "The pattern of blocks to leave", def = "air")
|
||||
Pattern replace,
|
||||
@Switch(name = 's', desc = "Shift the selection to the target location")
|
||||
boolean moveSelection,
|
||||
@Switch(name = 'a', desc = "Ignore air blocks")
|
||||
boolean ignoreAirBlocks) throws WorldEditException {
|
||||
if (count < 1) {
|
||||
throw new IllegalArgumentException("Count must be >= 1");
|
||||
}
|
||||
|
||||
int affected = editSession.moveRegion(region, direction, count, !ignoreAirBlocks, replace);
|
||||
|
||||
@ -295,30 +311,27 @@ public class RegionCommands {
|
||||
}
|
||||
}
|
||||
|
||||
player.print(affected + " blocks moved.");
|
||||
player.print(affected + " block(s) moved.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/stack" },
|
||||
usage = "[count] [direction]",
|
||||
flags = "sa",
|
||||
desc = "Repeat the contents of the selection",
|
||||
help =
|
||||
"Repeats the contents of the selection.\n" +
|
||||
"Flags:\n" +
|
||||
" -s shifts the selection to the last stacked copy\n" +
|
||||
" -a skips air blocks",
|
||||
min = 0,
|
||||
max = 2
|
||||
name = "/stack",
|
||||
desc = "Repeat the contents of the selection"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.stack")
|
||||
@Logging(ORIENTATION_REGION)
|
||||
public void stack(Player player, EditSession editSession, LocalSession session,
|
||||
public int stack(Player player, EditSession editSession, LocalSession session,
|
||||
@Selection Region region,
|
||||
@Optional("1") @Range(min = 1) int count,
|
||||
@Optional(Direction.AIM) @Direction(includeDiagonals = true) BlockVector3 direction,
|
||||
@Switch('s') boolean moveSelection,
|
||||
@Switch('a') boolean ignoreAirBlocks) throws WorldEditException {
|
||||
@Arg(desc = "# of copies to stack", def = "1")
|
||||
int count,
|
||||
@Arg(desc = "The direction to stack", def = Direction.AIM)
|
||||
@Direction(includeDiagonals = true)
|
||||
BlockVector3 direction,
|
||||
@Switch(name = 's', desc = "Shift the selection to the last stacked copy")
|
||||
boolean moveSelection,
|
||||
@Switch(name = 'a', desc = "Ignore air blocks")
|
||||
boolean ignoreAirBlocks) throws WorldEditException {
|
||||
int affected = editSession.stackCuboidRegion(region, direction, count, !ignoreAirBlocks);
|
||||
|
||||
if (moveSelection) {
|
||||
@ -335,26 +348,22 @@ public class RegionCommands {
|
||||
}
|
||||
}
|
||||
|
||||
player.print(affected + " blocks changed. Undo with //undo");
|
||||
player.print(affected + " block(s) changed. Undo with //undo");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/regen" },
|
||||
usage = "",
|
||||
name = "/regen",
|
||||
desc = "Regenerates the contents of the selection",
|
||||
help =
|
||||
"Regenerates the contents of the current selection.\n" +
|
||||
"This command might affect things outside the selection,\n" +
|
||||
"if they are within the same chunk.",
|
||||
min = 0,
|
||||
max = 0
|
||||
descFooter = "This command might affect things outside the selection,\n" +
|
||||
"if they are within the same chunk."
|
||||
)
|
||||
@CommandPermissions("worldedit.regen")
|
||||
@Logging(REGION)
|
||||
public void regenerateChunk(Player player, LocalSession session, EditSession editSession, @Selection Region region) throws WorldEditException {
|
||||
Mask mask = session.getMask();
|
||||
try {
|
||||
session.setMask((Mask) null);
|
||||
session.setMask(null);
|
||||
player.getWorld().regenerate(region, editSession);
|
||||
} finally {
|
||||
session.setMask(mask);
|
||||
@ -363,25 +372,22 @@ public class RegionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/deform" },
|
||||
usage = "<expression>",
|
||||
name = "/deform",
|
||||
desc = "Deforms a selected region with an expression",
|
||||
help =
|
||||
"Deforms a selected region with an expression\n" +
|
||||
"The expression is executed for each block and is expected\n" +
|
||||
descFooter = "The expression is executed for each block and is expected\n" +
|
||||
"to modify the variables x, y and z to point to a new block\n" +
|
||||
"to fetch. See also tinyurl.com/wesyntax.",
|
||||
flags = "ro",
|
||||
min = 1,
|
||||
max = -1
|
||||
"to fetch. See also tinyurl.com/wesyntax."
|
||||
)
|
||||
@CommandPermissions("worldedit.region.deform")
|
||||
@Logging(ALL)
|
||||
public void deform(Player player, LocalSession session, EditSession editSession,
|
||||
public int deform(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region,
|
||||
@Text String expression,
|
||||
@Switch('r') boolean useRawCoords,
|
||||
@Switch('o') boolean offset) throws WorldEditException {
|
||||
@Arg(desc = "The expression to use", variable = true)
|
||||
List<String> expression,
|
||||
@Switch(name = 'r', desc = "Use the game's coordinate origin")
|
||||
boolean useRawCoords,
|
||||
@Switch(name = 'o', desc = "Use the selection's center as origin")
|
||||
boolean offset) throws WorldEditException {
|
||||
final Vector3 zero;
|
||||
Vector3 unit;
|
||||
|
||||
@ -404,61 +410,63 @@ public class RegionCommands {
|
||||
}
|
||||
|
||||
try {
|
||||
final int affected = editSession.deformRegion(region, zero, unit, expression, session.getTimeout());
|
||||
final int affected = editSession.deformRegion(region, zero, unit, String.join(" ", expression), session.getTimeout());
|
||||
player.findFreePosition();
|
||||
player.print(affected + " block(s) have been deformed.");
|
||||
return affected;
|
||||
} catch (ExpressionException e) {
|
||||
player.printError(e.getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hollow" },
|
||||
usage = "[<thickness>[ <pattern>]]",
|
||||
name = "/hollow",
|
||||
desc = "Hollows out the object contained in this selection",
|
||||
help =
|
||||
"Hollows out the object contained in this selection.\n" +
|
||||
"Optionally fills the hollowed out part with the given block.\n" +
|
||||
"Thickness is measured in manhattan distance.",
|
||||
min = 0,
|
||||
max = 2
|
||||
descFooter = "Thickness is measured in manhattan distance."
|
||||
)
|
||||
@CommandPermissions("worldedit.region.hollow")
|
||||
@Logging(REGION)
|
||||
public void hollow(Player player, EditSession editSession,
|
||||
public int hollow(Player player, EditSession editSession,
|
||||
@Selection Region region,
|
||||
@Optional("0") @Range(min = 0) int thickness,
|
||||
@Optional("air") Pattern pattern) throws WorldEditException {
|
||||
@Arg(desc = "Thickness of the shell to leave", def = "0")
|
||||
int thickness,
|
||||
@Arg(desc = "The pattern of blocks to replace the hollowed area with", def = "air")
|
||||
Pattern pattern) throws WorldEditException {
|
||||
checkArgument(thickness >= 0, "Thickness must be >= 0");
|
||||
|
||||
int affected = editSession.hollowOutRegion(region, thickness, pattern);
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/forest" },
|
||||
usage = "[type] [density]",
|
||||
desc = "Make a forest within the region",
|
||||
min = 0,
|
||||
max = 2
|
||||
name = "/forest",
|
||||
desc = "Make a forest within the region"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.forest")
|
||||
@Logging(REGION)
|
||||
public void forest(Player player, EditSession editSession, @Selection Region region, @Optional("tree") TreeType type,
|
||||
@Optional("5") @Range(min = 0, max = 100) double density) throws WorldEditException {
|
||||
public int forest(Player player, EditSession editSession, @Selection Region region,
|
||||
@Arg(desc = "The type of tree to place", def = "tree")
|
||||
TreeType type,
|
||||
@Arg(desc = "The density of the forest", def = "5")
|
||||
double density) throws WorldEditException {
|
||||
checkArgument(0 <= density && density <= 100, "Density must be in [0, 100]");
|
||||
int affected = editSession.makeForest(region, density / 100, type);
|
||||
player.print(affected + " trees created.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/flora" },
|
||||
usage = "[density]",
|
||||
desc = "Make flora within the region",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/flora",
|
||||
desc = "Make flora within the region"
|
||||
)
|
||||
@CommandPermissions("worldedit.region.flora")
|
||||
@Logging(REGION)
|
||||
public void flora(Player player, EditSession editSession, @Selection Region region, @Optional("10") @Range(min = 0, max = 100) double density) throws WorldEditException {
|
||||
public int flora(Player player, EditSession editSession, @Selection Region region,
|
||||
@Arg(desc = "The density of the forest", def = "5")
|
||||
double density) throws WorldEditException {
|
||||
checkArgument(0 <= density && density <= 100, "Density must be in [0, 100]");
|
||||
density = density / 100;
|
||||
FloraGenerator generator = new FloraGenerator(editSession);
|
||||
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);
|
||||
@ -466,7 +474,9 @@ public class RegionCommands {
|
||||
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
|
||||
Operations.completeLegacy(visitor);
|
||||
|
||||
player.print(ground.getAffected() + " flora created.");
|
||||
int affected = ground.getAffected();
|
||||
player.print(affected + " flora created.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,16 +19,12 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.io.Files;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
@ -41,12 +37,19 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
|
||||
import com.sk89q.worldedit.util.formatting.component.SchematicPaginationBox;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.io.Closer;
|
||||
import com.sk89q.worldedit.util.io.file.FilenameException;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.ArgFlag;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.enginehub.piston.exception.StopExecutionException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
@ -57,19 +60,15 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Commands that work with schematic files.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class SchematicCommands {
|
||||
|
||||
/**
|
||||
* 9 schematics per page fits in the MC chat window.
|
||||
*/
|
||||
private static final int SCHEMATICS_PER_PAGE = 9;
|
||||
private static final Logger log = LoggerFactory.getLogger(SchematicCommands.class);
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
@ -84,17 +83,21 @@ public class SchematicCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "load" },
|
||||
usage = "[<format>] <filename>",
|
||||
desc = "Load a schematic into your clipboard",
|
||||
min = 1, max = 2
|
||||
name = "load",
|
||||
desc = "Load a schematic into your clipboard"
|
||||
)
|
||||
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load"})
|
||||
public void load(Player player, LocalSession session, @Optional("sponge") String formatName, String filename) throws FilenameException {
|
||||
public void load(Player player, LocalSession session,
|
||||
@Arg(desc = "File name.")
|
||||
String filename,
|
||||
@Arg(desc = "Format name.", def = "sponge")
|
||||
String formatName) throws FilenameException {
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
|
||||
File f = worldEdit.getSafeOpenFile(player, dir, filename, BuiltInClipboardFormat.SPONGE_SCHEMATIC.getPrimaryFileExtension(), ClipboardFormats.getFileExtensionArray());
|
||||
File f = worldEdit.getSafeOpenFile(player, dir, filename,
|
||||
BuiltInClipboardFormat.SPONGE_SCHEMATIC.getPrimaryFileExtension(),
|
||||
ClipboardFormats.getFileExtensionArray());
|
||||
|
||||
if (!f.exists()) {
|
||||
player.printError("Schematic " + filename + " does not exist!");
|
||||
@ -122,21 +125,23 @@ public class SchematicCommands {
|
||||
player.print(filename + " loaded. Paste it with //paste");
|
||||
} catch (IOException e) {
|
||||
player.printError("Schematic could not read or it does not exist: " + e.getMessage());
|
||||
log.warn("Failed to load a saved clipboard", e);
|
||||
log.warn("Failed to load schematic: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "save" },
|
||||
flags = "f",
|
||||
usage = "[<format>] <filename>",
|
||||
desc = "Save a schematic into your clipboard",
|
||||
help = "-f is required to overwrite an existing file",
|
||||
min = 1, max = 2
|
||||
name = "save",
|
||||
desc = "Save a schematic into your clipboard"
|
||||
)
|
||||
@CommandPermissions({"worldedit.clipboard.save", "worldedit.schematic.save"})
|
||||
public void save(Player player, LocalSession session, @Optional("sponge") String formatName,
|
||||
String filename, @Switch('f') boolean allowOverwrite) throws CommandException, WorldEditException {
|
||||
public void save(Player player, LocalSession session,
|
||||
@Arg(desc = "File name.")
|
||||
String filename,
|
||||
@Arg(desc = "Format name.", def = "sponge")
|
||||
String formatName,
|
||||
@Switch(name = 'f', desc = "Overwrite an existing file.")
|
||||
boolean allowOverwrite
|
||||
) throws WorldEditException {
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
|
||||
@ -152,7 +157,7 @@ public class SchematicCommands {
|
||||
boolean overwrite = f.exists();
|
||||
if (overwrite) {
|
||||
if (!player.hasPermission("worldedit.schematic.delete")) {
|
||||
throw new CommandException("That schematic already exists!");
|
||||
throw new StopExecutionException(TextComponent.of("That schematic already exists!"));
|
||||
}
|
||||
if (!allowOverwrite) {
|
||||
player.printError("That schematic already exists. Use the -f flag to overwrite it.");
|
||||
@ -179,7 +184,8 @@ public class SchematicCommands {
|
||||
File parent = f.getParentFile();
|
||||
if (parent != null && !parent.exists()) {
|
||||
if (!parent.mkdirs()) {
|
||||
throw new CommandException("Could not create folder for schematics!");
|
||||
throw new StopExecutionException(TextComponent.of(
|
||||
"Could not create folder for schematics!"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,15 +204,14 @@ public class SchematicCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "delete", "d" },
|
||||
usage = "<filename>",
|
||||
desc = "Delete a saved schematic",
|
||||
help = "Delete a schematic from the schematic list",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "delete",
|
||||
aliases = {"d"},
|
||||
desc = "Delete a saved schematic"
|
||||
)
|
||||
@CommandPermissions("worldedit.schematic.delete")
|
||||
public void delete(Actor actor, String filename) throws WorldEditException {
|
||||
public void delete(Actor actor,
|
||||
@Arg(desc = "File name.")
|
||||
String filename) throws WorldEditException {
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
|
||||
|
||||
@ -232,12 +237,12 @@ public class SchematicCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"formats", "listformats", "f"},
|
||||
desc = "List available formats",
|
||||
max = 0
|
||||
name = "formats",
|
||||
aliases = {"listformats", "f"},
|
||||
desc = "List available formats"
|
||||
)
|
||||
@CommandPermissions("worldedit.schematic.formats")
|
||||
public void formats(Actor actor) throws WorldEditException {
|
||||
public void formats(Actor actor) {
|
||||
actor.print("Available clipboard formats (Name: Lookup names)");
|
||||
StringBuilder builder;
|
||||
boolean first = true;
|
||||
@ -257,18 +262,22 @@ public class SchematicCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"list", "all", "ls"},
|
||||
name = "list",
|
||||
aliases = {"all", "ls"},
|
||||
desc = "List saved schematics",
|
||||
max = 1,
|
||||
flags = "dnp",
|
||||
help = "List all schematics in the schematics directory\n" +
|
||||
" -d sorts by date, oldest first\n" +
|
||||
" -n sorts by date, newest first\n" +
|
||||
" -p <page> prints the requested page\n" +
|
||||
"Note: Format is not thoroughly verified until loading."
|
||||
descFooter = "Note: Format is not fully verified until loading."
|
||||
)
|
||||
@CommandPermissions("worldedit.schematic.list")
|
||||
public void list(Actor actor, CommandContext args, @Switch('p') @Optional("1") int page) throws WorldEditException {
|
||||
public void list(Actor actor,
|
||||
@ArgFlag(name = 'p', desc = "Page to view.", def = "1")
|
||||
int page,
|
||||
@Switch(name = 'd', desc = "Sort by date, oldest first")
|
||||
boolean oldFirst,
|
||||
@Switch(name = 'n', desc = "Sort by date, newest first")
|
||||
boolean newFirst) throws WorldEditException {
|
||||
if (oldFirst && newFirst) {
|
||||
throw new StopExecutionException(TextComponent.of("Cannot sort by oldest and newest."));
|
||||
}
|
||||
File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().saveDir);
|
||||
List<File> fileList = allFiles(dir);
|
||||
|
||||
@ -280,17 +289,7 @@ public class SchematicCommands {
|
||||
File[] files = new File[fileList.size()];
|
||||
fileList.toArray(files);
|
||||
|
||||
int pageCount = files.length / SCHEMATICS_PER_PAGE + 1;
|
||||
if (page < 1) {
|
||||
actor.printError("Page must be at least 1");
|
||||
return;
|
||||
}
|
||||
if (page > pageCount) {
|
||||
actor.printError("Page must be less than " + (pageCount + 1));
|
||||
return;
|
||||
}
|
||||
|
||||
final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0;
|
||||
final int sortType = oldFirst ? -1 : newFirst ? 1 : 0;
|
||||
// cleanup file list
|
||||
Arrays.sort(files, (f1, f2) -> {
|
||||
// http://stackoverflow.com/questions/203030/best-way-to-list-files-in-java-sorted-by-date-modified
|
||||
@ -309,20 +308,9 @@ public class SchematicCommands {
|
||||
return res;
|
||||
});
|
||||
|
||||
List<String> schematics = listFiles(worldEdit.getConfiguration().saveDir, files);
|
||||
int offset = (page - 1) * SCHEMATICS_PER_PAGE;
|
||||
|
||||
actor.print("Available schematics (Filename: Format) [" + page + "/" + pageCount + "]:");
|
||||
StringBuilder build = new StringBuilder();
|
||||
int limit = Math.min(offset + SCHEMATICS_PER_PAGE, schematics.size());
|
||||
for (int i = offset; i < limit;) {
|
||||
build.append(schematics.get(i));
|
||||
if (++i != limit) {
|
||||
build.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
actor.print(build.toString());
|
||||
String pageCommand = actor.isPlayer() ? "//schem list -p %page%" + (oldFirst ? " -d" : newFirst ? " -n" : "") : null;
|
||||
PaginationBox paginationBox = new SchematicPaginationBox(worldEdit.getConfiguration().saveDir, files, pageCommand);
|
||||
actor.print(paginationBox.create(page));
|
||||
}
|
||||
|
||||
private List<File> allFiles(File root) {
|
||||
@ -341,22 +329,4 @@ public class SchematicCommands {
|
||||
return fileList;
|
||||
}
|
||||
|
||||
private List<String> listFiles(String prefix, File[] files) {
|
||||
if (prefix == null) prefix = "";
|
||||
List<String> result = new ArrayList<>();
|
||||
for (File file : files) {
|
||||
StringBuilder build = new StringBuilder();
|
||||
|
||||
build.append("\u00a72");
|
||||
//ClipboardFormat format = ClipboardFormats.findByFile(file);
|
||||
Multimap<String, ClipboardFormat> exts = ClipboardFormats.getFileExtensionMap();
|
||||
ClipboardFormat format = exts.get(Files.getFileExtension(file.getName()))
|
||||
.stream().findFirst().orElse(null);
|
||||
boolean inRoot = file.getParentFile().getName().equals(prefix);
|
||||
build.append(inRoot ? file.getName() : file.getPath().split(Pattern.quote(prefix + File.separator))[1])
|
||||
.append(": ").append(format == null ? "Unknown" : format.getName() + "*");
|
||||
result.add(build.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -19,23 +19,28 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.Logging;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL;
|
||||
|
||||
/**
|
||||
* Commands related to scripting.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class ScriptingCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
@ -51,42 +56,39 @@ public class ScriptingCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "cs" },
|
||||
usage = "<filename> [args...]",
|
||||
desc = "Execute a CraftScript",
|
||||
min = 1,
|
||||
max = -1
|
||||
name = "cs",
|
||||
desc = "Execute a CraftScript"
|
||||
)
|
||||
@CommandPermissions("worldedit.scripting.execute")
|
||||
@Logging(ALL)
|
||||
public void execute(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
String[] scriptArgs = args.getSlice(1);
|
||||
String name = args.getString(0);
|
||||
|
||||
if (!player.hasPermission("worldedit.scripting.execute." + name)) {
|
||||
public void execute(Player player, LocalSession session,
|
||||
@Arg(desc = "Filename of the CraftScript to load")
|
||||
String filename,
|
||||
@Arg(desc = "Arguments to the CraftScript", def = "", variable = true)
|
||||
List<String> args) throws WorldEditException {
|
||||
if (!player.hasPermission("worldedit.scripting.execute." + filename)) {
|
||||
player.printError("You don't have permission to use that script.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.setLastScript(name);
|
||||
session.setLastScript(filename);
|
||||
|
||||
File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().scriptsDir);
|
||||
File f = worldEdit.getSafeOpenFile(player, dir, name, "js", "js");
|
||||
File f = worldEdit.getSafeOpenFile(player, dir, filename, "js", "js");
|
||||
|
||||
worldEdit.runScript(player, f, scriptArgs);
|
||||
worldEdit.runScript(player, f, Stream.concat(Stream.of(filename), args.stream())
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { ".s" },
|
||||
usage = "[args...]",
|
||||
desc = "Execute last CraftScript",
|
||||
min = 0,
|
||||
max = -1
|
||||
name = ".s",
|
||||
desc = "Execute last CraftScript"
|
||||
)
|
||||
@CommandPermissions("worldedit.scripting.execute")
|
||||
@Logging(ALL)
|
||||
public void executeLast(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void executeLast(Player player, LocalSession session,
|
||||
@Arg(desc = "Arguments to the CraftScript", def = "", variable = true)
|
||||
List<String> args) throws WorldEditException {
|
||||
|
||||
String lastScript = session.getLastScript();
|
||||
|
||||
@ -100,11 +102,10 @@ public class ScriptingCommands {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] scriptArgs = args.getSlice(0);
|
||||
|
||||
File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().scriptsDir);
|
||||
File f = worldEdit.getSafeOpenFile(player, dir, lastScript, "js", "js");
|
||||
|
||||
worldEdit.runScript(player, f, scriptArgs);
|
||||
worldEdit.runScript(player, f, Stream.concat(Stream.of(lastScript), args.stream())
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
}
|
||||
|
@ -19,19 +19,16 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.command.argument.ExpandAmount;
|
||||
import com.sk89q.worldedit.command.argument.SelectorChoice;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.Logging;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
|
||||
@ -39,6 +36,8 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.block.BlockDistributionCounter;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
||||
import com.sk89q.worldedit.internal.annotation.MultiDirection;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
@ -63,16 +62,23 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||
import com.sk89q.worldedit.world.storage.ChunkStore;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
|
||||
|
||||
/**
|
||||
* Selection commands.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class SelectionCommands {
|
||||
|
||||
private final WorldEdit we;
|
||||
@ -82,26 +88,17 @@ public class SelectionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/pos1" },
|
||||
usage = "[coordinates]",
|
||||
desc = "Set position 1",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/pos1",
|
||||
desc = "Set position 1"
|
||||
)
|
||||
@Logging(POSITION)
|
||||
@CommandPermissions("worldedit.selection.pos")
|
||||
public void pos1(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
public void pos1(Player player, LocalSession session,
|
||||
@Arg(desc = "Coordinates to set position 1 to", def = "")
|
||||
BlockVector3 coordinates) throws WorldEditException {
|
||||
Location pos;
|
||||
|
||||
if (args.argsLength() == 1) {
|
||||
if (args.getString(0).matches("-?\\d+,-?\\d+,-?\\d+")) {
|
||||
String[] coords = args.getString(0).split(",");
|
||||
pos = new Location(player.getWorld(), Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(coords[2]));
|
||||
} else {
|
||||
player.printError("Invalid coordinates " + args.getString(0));
|
||||
return;
|
||||
}
|
||||
if (coordinates != null) {
|
||||
pos = new Location(player.getWorld(), coordinates.toVector3());
|
||||
} else {
|
||||
pos = player.getBlockIn();
|
||||
}
|
||||
@ -116,27 +113,17 @@ public class SelectionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/pos2" },
|
||||
usage = "[coordinates]",
|
||||
desc = "Set position 2",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/pos2",
|
||||
desc = "Set position 2"
|
||||
)
|
||||
@Logging(POSITION)
|
||||
@CommandPermissions("worldedit.selection.pos")
|
||||
public void pos2(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
public void pos2(Player player, LocalSession session,
|
||||
@Arg(desc = "Coordinates to set position 2 to", def = "")
|
||||
BlockVector3 coordinates) throws WorldEditException {
|
||||
Location pos;
|
||||
if (args.argsLength() == 1) {
|
||||
if (args.getString(0).matches("-?\\d+,-?\\d+,-?\\d+")) {
|
||||
String[] coords = args.getString(0).split(",");
|
||||
pos = new Location(player.getWorld(), Integer.parseInt(coords[0]),
|
||||
Integer.parseInt(coords[1]),
|
||||
Integer.parseInt(coords[2]));
|
||||
} else {
|
||||
player.printError("Invalid coordinates " + args.getString(0));
|
||||
return;
|
||||
}
|
||||
if (coordinates != null) {
|
||||
pos = new Location(player.getWorld(), coordinates.toVector3());
|
||||
} else {
|
||||
pos = player.getBlockIn();
|
||||
}
|
||||
@ -151,11 +138,8 @@ public class SelectionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hpos1" },
|
||||
usage = "",
|
||||
desc = "Set position 1 to targeted block",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "/hpos1",
|
||||
desc = "Set position 1 to targeted block"
|
||||
)
|
||||
@CommandPermissions("worldedit.selection.hpos")
|
||||
public void hpos1(Player player, LocalSession session) throws WorldEditException {
|
||||
@ -176,11 +160,8 @@ public class SelectionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hpos2" },
|
||||
usage = "",
|
||||
desc = "Set position 2 to targeted block",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "/hpos2",
|
||||
desc = "Set position 2 to targeted block"
|
||||
)
|
||||
@CommandPermissions("worldedit.selection.hpos")
|
||||
public void hpos2(Player player, LocalSession session) throws WorldEditException {
|
||||
@ -201,28 +182,22 @@ public class SelectionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/chunk" },
|
||||
usage = "[x,z coordinates]",
|
||||
flags = "sc",
|
||||
desc = "Set the selection to your current chunk.",
|
||||
help =
|
||||
"Set the selection to the chunk you are currently in.\n" +
|
||||
"With the -s flag, your current selection is expanded\n" +
|
||||
"to encompass all chunks that are part of it.\n\n" +
|
||||
"Specifying coordinates will use those instead of your\n"+
|
||||
"current position. Use -c to specify chunk coordinates,\n" +
|
||||
"otherwise full coordinates will be implied.\n" +
|
||||
"(for example, the coordinates 5,5 are the same as -c 0,0)",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/chunk",
|
||||
desc = "Set the selection to your current chunk."
|
||||
)
|
||||
@Logging(POSITION)
|
||||
@CommandPermissions("worldedit.selection.chunk")
|
||||
public void chunk(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void chunk(Player player, LocalSession session,
|
||||
@Arg(desc = "The chunk to select", def = "")
|
||||
BlockVector2 coordinates,
|
||||
@Switch(name = 's', desc = "Expand your selection to encompass all chunks that are part of it")
|
||||
boolean expandSelection,
|
||||
@Switch(name = 'c', desc = "Use chunk coordinates instead of block coordinates")
|
||||
boolean useChunkCoordinates) throws WorldEditException {
|
||||
final BlockVector3 min;
|
||||
final BlockVector3 max;
|
||||
final World world = player.getWorld();
|
||||
if (args.hasFlag('s')) {
|
||||
if (expandSelection) {
|
||||
Region region = session.getSelection(world);
|
||||
|
||||
final BlockVector2 min2D = ChunkStore.toChunk(region.getMinimumPoint());
|
||||
@ -236,16 +211,11 @@ public class SelectionCommands {
|
||||
+ max2D.getBlockX() + ", " + max2D.getBlockZ() + ")");
|
||||
} else {
|
||||
final BlockVector2 min2D;
|
||||
if (args.argsLength() == 1) {
|
||||
if (coordinates != null) {
|
||||
// coords specified
|
||||
String[] coords = args.getString(0).split(",");
|
||||
if (coords.length != 2) {
|
||||
throw new InsufficientArgumentsException("Invalid coordinates specified.");
|
||||
}
|
||||
int x = Integer.parseInt(coords[0]);
|
||||
int z = Integer.parseInt(coords[1]);
|
||||
BlockVector2 pos = BlockVector2.at(x, z);
|
||||
min2D = (args.hasFlag('c')) ? pos : ChunkStore.toChunk(pos.toBlockVector3());
|
||||
min2D = useChunkCoordinates
|
||||
? coordinates
|
||||
: ChunkStore.toChunk(coordinates.toBlockVector3());
|
||||
} else {
|
||||
// use player loc
|
||||
min2D = ChunkStore.toChunk(player.getBlockIn().toVector().toBlockPoint());
|
||||
@ -273,29 +243,21 @@ public class SelectionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/wand" },
|
||||
usage = "",
|
||||
desc = "Get the wand object",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "/wand",
|
||||
desc = "Get the wand object"
|
||||
)
|
||||
@CommandPermissions("worldedit.wand")
|
||||
public void wand(Player player) throws WorldEditException {
|
||||
|
||||
player.giveItem(new BaseItemStack(ItemTypes.get(we.getConfiguration().wandItem), 1));
|
||||
player.print("Left click: select pos #1; Right click: select pos #2");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "toggleeditwand" },
|
||||
usage = "",
|
||||
desc = "Toggle functionality of the edit wand",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "toggleeditwand",
|
||||
desc = "Toggle functionality of the edit wand"
|
||||
)
|
||||
@CommandPermissions("worldedit.wand.toggle")
|
||||
public void toggleWand(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
public void toggleWand(Player player, LocalSession session) throws WorldEditException {
|
||||
session.setToolControl(!session.isToolControlEnabled());
|
||||
|
||||
if (session.isToolControlEnabled()) {
|
||||
@ -306,20 +268,23 @@ public class SelectionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/expand" },
|
||||
usage = "<amount> [reverse-amount] <direction>",
|
||||
desc = "Expand the selection area",
|
||||
min = 1,
|
||||
max = 3
|
||||
name = "/expand",
|
||||
desc = "Expand the selection area"
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.selection.expand")
|
||||
public void expand(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void expand(Player player, LocalSession session,
|
||||
@Arg(desc = "Amount to expand the selection by, can be `vert` to expand to the whole vertical column")
|
||||
ExpandAmount amount,
|
||||
@Arg(desc = "Amount to expand the selection by in the other direction", def = "0")
|
||||
int reverseAmount,
|
||||
@Arg(desc = "Direction to expand", def = Direction.AIM)
|
||||
@MultiDirection
|
||||
List<BlockVector3> direction) throws WorldEditException {
|
||||
|
||||
// Special syntax (//expand vert) to expand the selection between
|
||||
// sky and bedrock.
|
||||
if (args.getString(0).equalsIgnoreCase("vert")
|
||||
|| args.getString(0).equalsIgnoreCase("vertical")) {
|
||||
if (amount.isVert()) {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
try {
|
||||
int oldSize = region.getArea();
|
||||
@ -338,57 +303,16 @@ public class SelectionCommands {
|
||||
return;
|
||||
}
|
||||
|
||||
List<BlockVector3> dirs = new ArrayList<>();
|
||||
int change = args.getInteger(0);
|
||||
int reverseChange = 0;
|
||||
|
||||
switch (args.argsLength()) {
|
||||
case 2:
|
||||
// Either a reverse amount or a direction
|
||||
try {
|
||||
reverseChange = args.getInteger(1);
|
||||
dirs.add(we.getDirection(player, "me"));
|
||||
} catch (NumberFormatException e) {
|
||||
if (args.getString(1).contains(",")) {
|
||||
String[] split = args.getString(1).split(",");
|
||||
for (String s : split) {
|
||||
dirs.add(we.getDirection(player, s.toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Both reverse amount and direction
|
||||
reverseChange = args.getInteger(1);
|
||||
if (args.getString(2).contains(",")) {
|
||||
String[] split = args.getString(2).split(",");
|
||||
for (String s : split) {
|
||||
dirs.add(we.getDirection(player, s.toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, args.getString(2).toLowerCase()));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
dirs.add(we.getDirection(player, "me"));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
int oldSize = region.getArea();
|
||||
|
||||
if (reverseChange == 0) {
|
||||
for (BlockVector3 dir : dirs) {
|
||||
region.expand(dir.multiply(change));
|
||||
if (reverseAmount == 0) {
|
||||
for (BlockVector3 dir : direction) {
|
||||
region.expand(dir.multiply(amount.getAmount()));
|
||||
}
|
||||
} else {
|
||||
for (BlockVector3 dir : dirs) {
|
||||
region.expand(dir.multiply(change), dir.multiply(-reverseChange));
|
||||
for (BlockVector3 dir : direction) {
|
||||
region.expand(dir.multiply(amount.getAmount()), dir.multiply(-reverseAmount));
|
||||
}
|
||||
}
|
||||
|
||||
@ -397,70 +321,33 @@ public class SelectionCommands {
|
||||
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
|
||||
player.print("Region expanded " + (newSize - oldSize) + " blocks.");
|
||||
player.print("Region expanded " + (newSize - oldSize) + " block(s).");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/contract" },
|
||||
usage = "<amount> [reverse-amount] [direction]",
|
||||
desc = "Contract the selection area",
|
||||
min = 1,
|
||||
max = 3
|
||||
name = "/contract",
|
||||
desc = "Contract the selection area"
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.selection.contract")
|
||||
public void contract(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
List<BlockVector3> dirs = new ArrayList<>();
|
||||
int change = args.getInteger(0);
|
||||
int reverseChange = 0;
|
||||
|
||||
switch (args.argsLength()) {
|
||||
case 2:
|
||||
// Either a reverse amount or a direction
|
||||
try {
|
||||
reverseChange = args.getInteger(1);
|
||||
dirs.add(we.getDirection(player, "me"));
|
||||
} catch (NumberFormatException e) {
|
||||
if (args.getString(1).contains(",")) {
|
||||
String[] split = args.getString(1).split(",");
|
||||
for (String s : split) {
|
||||
dirs.add(we.getDirection(player, s.toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Both reverse amount and direction
|
||||
reverseChange = args.getInteger(1);
|
||||
if (args.getString(2).contains(",")) {
|
||||
String[] split = args.getString(2).split(",");
|
||||
for (String s : split) {
|
||||
dirs.add(we.getDirection(player, s.toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, args.getString(2).toLowerCase()));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
dirs.add(we.getDirection(player, "me"));
|
||||
break;
|
||||
}
|
||||
|
||||
public void contract(Player player, LocalSession session,
|
||||
@Arg(desc = "Amount to contract the selection by")
|
||||
int amount,
|
||||
@Arg(desc = "Amount to contract the selection by in the other direction", def = "0")
|
||||
int reverseAmount,
|
||||
@Arg(desc = "Direction to contract", def = Direction.AIM)
|
||||
@MultiDirection
|
||||
List<BlockVector3> direction) throws WorldEditException {
|
||||
try {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
int oldSize = region.getArea();
|
||||
if (reverseChange == 0) {
|
||||
for (BlockVector3 dir : dirs) {
|
||||
region.contract(dir.multiply(change));
|
||||
if (reverseAmount == 0) {
|
||||
for (BlockVector3 dir : direction) {
|
||||
region.contract(dir.multiply(amount));
|
||||
}
|
||||
} else {
|
||||
for (BlockVector3 dir : dirs) {
|
||||
region.contract(dir.multiply(change), dir.multiply(-reverseChange));
|
||||
for (BlockVector3 dir : direction) {
|
||||
region.contract(dir.multiply(amount), dir.multiply(-reverseAmount));
|
||||
}
|
||||
}
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
@ -476,35 +363,22 @@ public class SelectionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/shift" },
|
||||
usage = "<amount> [direction]",
|
||||
desc = "Shift the selection area",
|
||||
min = 1,
|
||||
max = 2
|
||||
name = "/shift",
|
||||
desc = "Shift the selection area"
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.selection.shift")
|
||||
public void shift(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
List<BlockVector3> dirs = new ArrayList<>();
|
||||
int change = args.getInteger(0);
|
||||
if (args.argsLength() == 2) {
|
||||
if (args.getString(1).contains(",")) {
|
||||
for (String s : args.getString(1).split(",")) {
|
||||
dirs.add(we.getDirection(player, s.toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, "me"));
|
||||
}
|
||||
|
||||
public void shift(Player player, LocalSession session,
|
||||
@Arg(desc = "Amount to shift the selection by")
|
||||
int amount,
|
||||
@Arg(desc = "Direction to contract", def = Direction.AIM)
|
||||
@MultiDirection
|
||||
List<BlockVector3> direction) throws WorldEditException {
|
||||
try {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
|
||||
for (BlockVector3 dir : dirs) {
|
||||
region.shift(dir.multiply(change));
|
||||
for (BlockVector3 dir : direction) {
|
||||
region.shift(dir.multiply(amount));
|
||||
}
|
||||
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
@ -518,107 +392,92 @@ public class SelectionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/outset" },
|
||||
usage = "<amount>",
|
||||
desc = "Outset the selection area",
|
||||
help =
|
||||
"Expands the selection by the given amount in all directions.\n" +
|
||||
"Flags:\n" +
|
||||
" -h only expand horizontally\n" +
|
||||
" -v only expand vertically\n",
|
||||
flags = "hv",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "/outset",
|
||||
desc = "Outset the selection area"
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.selection.outset")
|
||||
public void outset(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void outset(Player player, LocalSession session,
|
||||
@Arg(desc = "Amount to expand the selection by in all directions")
|
||||
int amount,
|
||||
@Switch(name = 'h', desc = "Only expand horizontally")
|
||||
boolean onlyHorizontal,
|
||||
@Switch(name = 'v', desc = "Only expand vertically")
|
||||
boolean onlyVertical) throws WorldEditException {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
region.expand(getChangesForEachDir(args));
|
||||
region.expand(getChangesForEachDir(amount, onlyHorizontal, onlyVertical));
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
player.print("Region outset.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/inset" },
|
||||
usage = "<amount>",
|
||||
desc = "Inset the selection area",
|
||||
help =
|
||||
"Contracts the selection by the given amount in all directions.\n" +
|
||||
"Flags:\n" +
|
||||
" -h only contract horizontally\n" +
|
||||
" -v only contract vertically\n",
|
||||
flags = "hv",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "/inset",
|
||||
desc = "Inset the selection area"
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.selection.inset")
|
||||
public void inset(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void inset(Player player, LocalSession session,
|
||||
@Arg(desc = "Amount to contract the selection by in all directions")
|
||||
int amount,
|
||||
@Switch(name = 'h', desc = "Only contract horizontally")
|
||||
boolean onlyHorizontal,
|
||||
@Switch(name = 'v', desc = "Only contract vertically")
|
||||
boolean onlyVertical) throws WorldEditException {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
region.contract(getChangesForEachDir(args));
|
||||
region.contract(getChangesForEachDir(amount, onlyHorizontal, onlyVertical));
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
player.print("Region inset.");
|
||||
}
|
||||
|
||||
private BlockVector3[] getChangesForEachDir(CommandContext args) {
|
||||
List<BlockVector3> changes = new ArrayList<>(6);
|
||||
int change = args.getInteger(0);
|
||||
private BlockVector3[] getChangesForEachDir(int amount, boolean onlyHorizontal, boolean onlyVertical) {
|
||||
Stream.Builder<BlockVector3> changes = Stream.builder();
|
||||
|
||||
if (!args.hasFlag('h')) {
|
||||
changes.add((BlockVector3.UNIT_Y).multiply(change));
|
||||
changes.add((BlockVector3.UNIT_MINUS_Y).multiply(change));
|
||||
if (!onlyHorizontal) {
|
||||
changes.add(BlockVector3.UNIT_Y);
|
||||
changes.add(BlockVector3.UNIT_MINUS_Y);
|
||||
}
|
||||
|
||||
if (!args.hasFlag('v')) {
|
||||
changes.add((BlockVector3.UNIT_X).multiply(change));
|
||||
changes.add((BlockVector3.UNIT_MINUS_X).multiply(change));
|
||||
changes.add((BlockVector3.UNIT_Z).multiply(change));
|
||||
changes.add((BlockVector3.UNIT_MINUS_Z).multiply(change));
|
||||
if (!onlyVertical) {
|
||||
changes.add(BlockVector3.UNIT_X);
|
||||
changes.add(BlockVector3.UNIT_MINUS_X);
|
||||
changes.add(BlockVector3.UNIT_Z);
|
||||
changes.add(BlockVector3.UNIT_MINUS_Z);
|
||||
}
|
||||
|
||||
return changes.toArray(new BlockVector3[0]);
|
||||
return changes.build().map(v -> v.multiply(amount)).toArray(BlockVector3[]::new);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/size" },
|
||||
flags = "c",
|
||||
usage = "",
|
||||
desc = "Get information about the selection",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "/size",
|
||||
desc = "Get information about the selection"
|
||||
)
|
||||
@CommandPermissions("worldedit.selection.size")
|
||||
public void size(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
if (args.hasFlag('c')) {
|
||||
public void size(Player player, LocalSession session,
|
||||
@Switch(name = 'c', desc = "Get clipboard info instead")
|
||||
boolean clipboardInfo) throws WorldEditException {
|
||||
Region region;
|
||||
if (clipboardInfo) {
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
Region region = clipboard.getRegion();
|
||||
BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint());
|
||||
region = clipboard.getRegion();
|
||||
|
||||
BlockVector3 origin = clipboard.getOrigin();
|
||||
|
||||
player.print("Cuboid dimensions (max - min): " + size);
|
||||
player.print("Offset: " + origin);
|
||||
player.print("Cuboid distance: " + size.distance(BlockVector3.ONE));
|
||||
player.print("# of blocks: " + (int) (size.getX() * size.getY() * size.getZ()));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
region = session.getSelection(player.getWorld());
|
||||
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
player.print("Type: " + session.getRegionSelector(player.getWorld()).getTypeName());
|
||||
|
||||
for (String line : session.getRegionSelector(player.getWorld()).getInformationLines()) {
|
||||
player.print(line);
|
||||
}
|
||||
}
|
||||
BlockVector3 size = region.getMaximumPoint()
|
||||
.subtract(region.getMinimumPoint())
|
||||
.add(1, 1, 1);
|
||||
|
||||
player.print("Type: " + session.getRegionSelector(player.getWorld())
|
||||
.getTypeName());
|
||||
|
||||
for (String line : session.getRegionSelector(player.getWorld())
|
||||
.getInformationLines()) {
|
||||
player.print(line);
|
||||
}
|
||||
|
||||
player.print("Size: " + size);
|
||||
player.print("Cuboid distance: " + region.getMaximumPoint().distance(region.getMinimumPoint()));
|
||||
player.print("# of blocks: " + region.getArea());
|
||||
@ -626,48 +485,41 @@ public class SelectionCommands {
|
||||
|
||||
|
||||
@Command(
|
||||
aliases = { "/count" },
|
||||
usage = "<block>",
|
||||
flags = "f",
|
||||
desc = "Counts the number of a certain type of block",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "/count",
|
||||
desc = "Counts the number of a certain type of block"
|
||||
)
|
||||
@CommandPermissions("worldedit.analysis.count")
|
||||
public void count(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
public void count(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The block type(s) to count")
|
||||
String blocks,
|
||||
@Switch(name = 'f', desc = "Fuzzy, match states using a wildcard")
|
||||
boolean fuzzy) throws WorldEditException {
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setExtent(player.getExtent());
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
context.setRestricted(false);
|
||||
context.setPreferringWildcard(args.hasFlag('f'));
|
||||
context.setPreferringWildcard(fuzzy);
|
||||
|
||||
Set<BaseBlock> searchBlocks = we.getBlockFactory().parseFromListInput(args.getString(0), context);
|
||||
Set<BaseBlock> searchBlocks = we.getBlockFactory().parseFromListInput(blocks, context);
|
||||
int count = editSession.countBlocks(session.getSelection(player.getWorld()), searchBlocks);
|
||||
player.print("Counted: " + count);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/distr" },
|
||||
usage = "",
|
||||
desc = "Get the distribution of blocks in the selection",
|
||||
help =
|
||||
"Gets the distribution of blocks in the selection.\n" +
|
||||
"The -c flag gets the distribution of your clipboard.\n" +
|
||||
"The -d flag separates blocks by state",
|
||||
flags = "cd",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "/distr",
|
||||
desc = "Get the distribution of blocks in the selection"
|
||||
)
|
||||
@CommandPermissions("worldedit.analysis.distr")
|
||||
public void distr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException {
|
||||
|
||||
boolean separateStates = args.hasFlag('d');
|
||||
public void distr(Player player, LocalSession session, EditSession editSession,
|
||||
@Switch(name = 'c', desc = "Get the distribution of the clipboard instead")
|
||||
boolean clipboardDistr,
|
||||
@Switch(name = 'd', desc = "Separate blocks by state")
|
||||
boolean separateStates) throws WorldEditException {
|
||||
List<Countable<BlockState>> distribution;
|
||||
|
||||
if (args.hasFlag('c')) {
|
||||
if (clipboardDistr) {
|
||||
Clipboard clipboard = session.getClipboard().getClipboard(); // throws if missing
|
||||
BlockDistributionCounter count = new BlockDistributionCounter(clipboard, separateStates);
|
||||
RegionVisitor visitor = new RegionVisitor(clipboard.getRegion(), count);
|
||||
@ -707,53 +559,67 @@ public class SelectionCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/sel", ";", "/desel", "/deselect" },
|
||||
flags = "d",
|
||||
usage = "[cuboid|extend|poly|ellipsoid|sphere|cyl|convex]",
|
||||
desc = "Choose a region selector",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/sel",
|
||||
aliases = { ";", "/desel", "/deselect" },
|
||||
desc = "Choose a region selector"
|
||||
)
|
||||
public void select(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void select(Player player, LocalSession session,
|
||||
@Arg(desc = "Selector to switch to", def = "")
|
||||
SelectorChoice selector,
|
||||
@Switch(name = 'd', desc = "Set default selector")
|
||||
boolean setDefaultSelector) throws WorldEditException {
|
||||
final World world = player.getWorld();
|
||||
if (args.argsLength() == 0) {
|
||||
if (selector == null) {
|
||||
session.getRegionSelector(world).clear();
|
||||
session.dispatchCUISelection(player);
|
||||
player.print("Selection cleared.");
|
||||
return;
|
||||
}
|
||||
|
||||
final String typeName = args.getString(0);
|
||||
final RegionSelector oldSelector = session.getRegionSelector(world);
|
||||
|
||||
final RegionSelector selector;
|
||||
if (typeName.equalsIgnoreCase("cuboid")) {
|
||||
selector = new CuboidRegionSelector(oldSelector);
|
||||
final RegionSelector newSelector;
|
||||
switch (selector) {
|
||||
case CUBOID:
|
||||
newSelector = new CuboidRegionSelector(oldSelector);
|
||||
player.print("Cuboid: left click for point 1, right click for point 2");
|
||||
} else if (typeName.equalsIgnoreCase("extend")) {
|
||||
selector = new ExtendingCuboidRegionSelector(oldSelector);
|
||||
break;
|
||||
case EXTEND:
|
||||
newSelector = new ExtendingCuboidRegionSelector(oldSelector);
|
||||
player.print("Cuboid: left click for a starting point, right click to extend");
|
||||
} else if (typeName.equalsIgnoreCase("poly")) {
|
||||
selector = new Polygonal2DRegionSelector(oldSelector);
|
||||
break;
|
||||
case POLY: {
|
||||
newSelector = new Polygonal2DRegionSelector(oldSelector);
|
||||
player.print("2D polygon selector: Left/right click to add a point.");
|
||||
Optional<Integer> limit = ActorSelectorLimits.forActor(player).getPolygonVertexLimit();
|
||||
limit.ifPresent(integer -> player.print(integer + " points maximum."));
|
||||
} else if (typeName.equalsIgnoreCase("ellipsoid")) {
|
||||
selector = new EllipsoidRegionSelector(oldSelector);
|
||||
break;
|
||||
}
|
||||
case ELLIPSOID:
|
||||
newSelector = new EllipsoidRegionSelector(oldSelector);
|
||||
player.print("Ellipsoid selector: left click=center, right click to extend");
|
||||
} else if (typeName.equalsIgnoreCase("sphere")) {
|
||||
selector = new SphereRegionSelector(oldSelector);
|
||||
break;
|
||||
case SPHERE:
|
||||
newSelector = new SphereRegionSelector(oldSelector);
|
||||
player.print("Sphere selector: left click=center, right click to set radius");
|
||||
} else if (typeName.equalsIgnoreCase("cyl")) {
|
||||
selector = new CylinderRegionSelector(oldSelector);
|
||||
break;
|
||||
case CYL:
|
||||
newSelector = new CylinderRegionSelector(oldSelector);
|
||||
player.print("Cylindrical selector: Left click=center, right click to extend.");
|
||||
} else if (typeName.equalsIgnoreCase("convex") || typeName.equalsIgnoreCase("hull") || typeName.equalsIgnoreCase("polyhedron")) {
|
||||
selector = new ConvexPolyhedralRegionSelector(oldSelector);
|
||||
break;
|
||||
case CONVEX:
|
||||
case HULL:
|
||||
case POLYHEDRON: {
|
||||
newSelector = new ConvexPolyhedralRegionSelector(oldSelector);
|
||||
player.print("Convex polyhedral selector: Left click=First vertex, right click to add more.");
|
||||
Optional<Integer> limit = ActorSelectorLimits.forActor(player).getPolyhedronVertexLimit();
|
||||
limit.ifPresent(integer -> player.print(integer + " points maximum."));
|
||||
} else {
|
||||
CommandListBox box = new CommandListBox("Selection modes");
|
||||
break;
|
||||
}
|
||||
case UNKNOWN:
|
||||
default:
|
||||
CommandListBox box = new CommandListBox("Selection modes", null);
|
||||
box.setHidingHelp(true);
|
||||
TextComponentProducer contents = box.getContents();
|
||||
contents.append(SubtleFormat.wrap("Select one of the modes below:")).newline();
|
||||
|
||||
@ -765,14 +631,14 @@ public class SelectionCommands {
|
||||
box.appendCommand("cyl", "Select a cylinder", "//sel cyl");
|
||||
box.appendCommand("convex", "Select a convex polyhedral", "//sel convex");
|
||||
|
||||
player.print(box.create());
|
||||
player.print(box.create(1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.hasFlag('d')) {
|
||||
if (setDefaultSelector) {
|
||||
RegionSelectorType found = null;
|
||||
for (RegionSelectorType type : RegionSelectorType.values()) {
|
||||
if (type.getSelectorClass() == selector.getClass()) {
|
||||
if (type.getSelectorClass() == newSelector.getClass()) {
|
||||
found = type;
|
||||
break;
|
||||
}
|
||||
@ -786,7 +652,7 @@ public class SelectionCommands {
|
||||
}
|
||||
}
|
||||
|
||||
session.setRegionSelector(world, selector);
|
||||
session.setRegionSelector(world, newSelector);
|
||||
session.dispatchCUISelection(player);
|
||||
}
|
||||
|
||||
|
@ -21,31 +21,33 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.world.snapshot.InvalidSnapshotException;
|
||||
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||
import com.sk89q.worldedit.world.storage.MissingWorldException;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Snapshot commands.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class SnapshotCommands {
|
||||
|
||||
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
|
||||
private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
|
||||
|
||||
private final WorldEdit we;
|
||||
|
||||
@ -54,14 +56,13 @@ public class SnapshotCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "list" },
|
||||
usage = "[num]",
|
||||
desc = "List snapshots",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "list",
|
||||
desc = "List snapshots"
|
||||
)
|
||||
@CommandPermissions("worldedit.snapshots.list")
|
||||
public void list(Player player, CommandContext args) throws WorldEditException {
|
||||
public void list(Player player,
|
||||
@Arg(desc = "# of snapshots to list", def = "5")
|
||||
int num) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
@ -75,7 +76,7 @@ public class SnapshotCommands {
|
||||
|
||||
if (!snapshots.isEmpty()) {
|
||||
|
||||
int num = args.argsLength() > 0 ? Math.min(40, Math.max(5, args.getInteger(0))) : 5;
|
||||
num = Math.min(40, Math.max(5, num));
|
||||
|
||||
player.print("Snapshots for world: '" + player.getWorld().getName() + "'");
|
||||
for (byte i = 0; i < Math.min(num, snapshots.size()); i++) {
|
||||
@ -104,14 +105,13 @@ public class SnapshotCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "use" },
|
||||
usage = "<snapshot>",
|
||||
desc = "Choose a snapshot to use",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "use",
|
||||
desc = "Choose a snapshot to use"
|
||||
)
|
||||
@CommandPermissions("worldedit.snapshots.restore")
|
||||
public void use(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void use(Player player, LocalSession session,
|
||||
@Arg(desc = "Snapeshot to use")
|
||||
String name) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
@ -120,8 +120,6 @@ public class SnapshotCommands {
|
||||
return;
|
||||
}
|
||||
|
||||
String name = args.getString(0);
|
||||
|
||||
// Want the latest snapshot?
|
||||
if (name.equalsIgnoreCase("latest")) {
|
||||
try {
|
||||
@ -147,14 +145,13 @@ public class SnapshotCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "sel" },
|
||||
usage = "<index>",
|
||||
desc = "Choose the snapshot based on the list id",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "sel",
|
||||
desc = "Choose the snapshot based on the list id"
|
||||
)
|
||||
@CommandPermissions("worldedit.snapshots.restore")
|
||||
public void sel(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void sel(Player player, LocalSession session,
|
||||
@Arg(desc = "The list ID to select")
|
||||
int index) throws WorldEditException {
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
if (config.snapshotRepo == null) {
|
||||
@ -162,14 +159,6 @@ public class SnapshotCommands {
|
||||
return;
|
||||
}
|
||||
|
||||
int index = -1;
|
||||
try {
|
||||
index = Integer.parseInt(args.getString(0));
|
||||
} catch (NumberFormatException e) {
|
||||
player.printError("Invalid index, " + args.getString(0) + " is not a valid integer.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < 1) {
|
||||
player.printError("Invalid index, must be equal or higher then 1.");
|
||||
return;
|
||||
@ -194,14 +183,13 @@ public class SnapshotCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "before" },
|
||||
usage = "<date>",
|
||||
desc = "Choose the nearest snapshot before a date",
|
||||
min = 1,
|
||||
max = -1
|
||||
name = "before",
|
||||
desc = "Choose the nearest snapshot before a date"
|
||||
)
|
||||
@CommandPermissions("worldedit.snapshots.restore")
|
||||
public void before(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void before(Player player, LocalSession session,
|
||||
@Arg(desc = "The soonest date that may be used")
|
||||
ZonedDateTime date) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
@ -210,18 +198,12 @@ public class SnapshotCommands {
|
||||
return;
|
||||
}
|
||||
|
||||
Calendar date = session.detectDate(args.getJoinedStrings(0));
|
||||
|
||||
if (date == null) {
|
||||
player.printError("Could not detect the date inputted.");
|
||||
} else {
|
||||
try {
|
||||
Snapshot snapshot = config.snapshotRepo.getSnapshotBefore(date, player.getWorld().getName());
|
||||
|
||||
if (snapshot == null) {
|
||||
dateFormat.setTimeZone(session.getTimeZone());
|
||||
player.printError("Couldn't find a snapshot before "
|
||||
+ dateFormat.format(date.getTime()) + ".");
|
||||
+ dateFormat.withZone(session.getTimeZone()).format(date) + ".");
|
||||
} else {
|
||||
session.setSnapshot(snapshot);
|
||||
player.print("Snapshot set to: " + snapshot.getName());
|
||||
@ -230,17 +212,15 @@ public class SnapshotCommands {
|
||||
player.printError("No snapshots were found for this world.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "after" },
|
||||
usage = "<date>",
|
||||
desc = "Choose the nearest snapshot after a date",
|
||||
min = 1,
|
||||
max = -1
|
||||
name = "after",
|
||||
desc = "Choose the nearest snapshot after a date"
|
||||
)
|
||||
@CommandPermissions("worldedit.snapshots.restore")
|
||||
public void after(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void after(Player player, LocalSession session,
|
||||
@Arg(desc = "The soonest date that may be used")
|
||||
ZonedDateTime date) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
@ -249,17 +229,11 @@ public class SnapshotCommands {
|
||||
return;
|
||||
}
|
||||
|
||||
Calendar date = session.detectDate(args.getJoinedStrings(0));
|
||||
|
||||
if (date == null) {
|
||||
player.printError("Could not detect the date inputted.");
|
||||
} else {
|
||||
try {
|
||||
Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName());
|
||||
if (snapshot == null) {
|
||||
dateFormat.setTimeZone(session.getTimeZone());
|
||||
player.printError("Couldn't find a snapshot after "
|
||||
+ dateFormat.format(date.getTime()) + ".");
|
||||
+ dateFormat.withZone(session.getTimeZone()).format(date) + ".");
|
||||
} else {
|
||||
session.setSnapshot(snapshot);
|
||||
player.print("Snapshot set to: " + snapshot.getName());
|
||||
@ -268,6 +242,5 @@ public class SnapshotCommands {
|
||||
player.printError("No snapshots were found for this world.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,15 +19,14 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.Logging;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.DataException;
|
||||
@ -36,12 +35,16 @@ import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||
import com.sk89q.worldedit.world.snapshot.SnapshotRestore;
|
||||
import com.sk89q.worldedit.world.storage.ChunkStore;
|
||||
import com.sk89q.worldedit.world.storage.MissingWorldException;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
|
||||
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class SnapshotUtilCommands {
|
||||
|
||||
private final WorldEdit we;
|
||||
@ -51,15 +54,15 @@ public class SnapshotUtilCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "restore", "/restore" },
|
||||
usage = "[snapshot]",
|
||||
desc = "Restore the selection from a snapshot",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "restore",
|
||||
aliases = { "/restore" },
|
||||
desc = "Restore the selection from a snapshot"
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.snapshots.restore")
|
||||
public void restore(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
public void restore(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(name = "snapshot", desc = "The snapshot to restore", def = "")
|
||||
String snapshotName) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
@ -71,9 +74,9 @@ public class SnapshotUtilCommands {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
Snapshot snapshot;
|
||||
|
||||
if (args.argsLength() > 0) {
|
||||
if (snapshotName != null) {
|
||||
try {
|
||||
snapshot = config.snapshotRepo.getSnapshot(args.getString(0));
|
||||
snapshot = config.snapshotRepo.getSnapshot(snapshotName);
|
||||
} catch (InvalidSnapshotException e) {
|
||||
player.printError("That snapshot does not exist or is not available.");
|
||||
return;
|
||||
@ -110,7 +113,7 @@ public class SnapshotUtilCommands {
|
||||
}
|
||||
}
|
||||
|
||||
ChunkStore chunkStore = null;
|
||||
ChunkStore chunkStore;
|
||||
|
||||
// Load chunk store
|
||||
try {
|
||||
|
@ -19,9 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
@ -29,8 +26,14 @@ import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.tool.AreaPickaxe;
|
||||
import com.sk89q.worldedit.command.tool.RecursivePickaxe;
|
||||
import com.sk89q.worldedit.command.tool.SinglePickaxe;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class SuperPickaxeCommands {
|
||||
private final WorldEdit we;
|
||||
|
||||
@ -39,32 +42,26 @@ public class SuperPickaxeCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "single" },
|
||||
usage = "",
|
||||
desc = "Enable the single block super pickaxe mode",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "single",
|
||||
desc = "Enable the single block super pickaxe mode"
|
||||
)
|
||||
@CommandPermissions("worldedit.superpickaxe")
|
||||
public void single(Player player, LocalSession session) throws WorldEditException {
|
||||
|
||||
session.setSuperPickaxe(new SinglePickaxe());
|
||||
session.enableSuperPickAxe();
|
||||
player.print("Mode changed. Left click with a pickaxe. // to disable.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "area" },
|
||||
usage = "<radius>",
|
||||
desc = "Enable the area super pickaxe pickaxe mode",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "area",
|
||||
desc = "Enable the area super pickaxe pickaxe mode"
|
||||
)
|
||||
@CommandPermissions("worldedit.superpickaxe.area")
|
||||
public void area(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void area(Player player, LocalSession session,
|
||||
@Arg(desc = "The range of the area pickaxe")
|
||||
int range) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
int range = args.getInteger(0);
|
||||
|
||||
if (range > config.maxSuperPickaxeSize) {
|
||||
player.printError("Maximum range: " + config.maxSuperPickaxeSize);
|
||||
@ -77,17 +74,16 @@ public class SuperPickaxeCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "recur", "recursive" },
|
||||
usage = "<radius>",
|
||||
desc = "Enable the recursive super pickaxe pickaxe mode",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "recursive",
|
||||
aliases = { "recur" },
|
||||
desc = "Enable the recursive super pickaxe pickaxe mode"
|
||||
)
|
||||
@CommandPermissions("worldedit.superpickaxe.recursive")
|
||||
public void recursive(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void recursive(Player player, LocalSession session,
|
||||
@Arg(desc = "The range of the recursive pickaxe")
|
||||
double range) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
double range = args.getDouble(0);
|
||||
|
||||
if (range > config.maxSuperPickaxeSize) {
|
||||
player.printError("Maximum range: " + config.maxSuperPickaxeSize);
|
||||
|
@ -19,9 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
@ -35,12 +32,18 @@ import com.sk89q.worldedit.command.tool.FloodFillTool;
|
||||
import com.sk89q.worldedit.command.tool.LongRangeBuildTool;
|
||||
import com.sk89q.worldedit.command.tool.QueryTool;
|
||||
import com.sk89q.worldedit.command.tool.TreePlanter;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.util.HandSide;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class ToolCommands {
|
||||
private final WorldEdit we;
|
||||
|
||||
@ -49,11 +52,8 @@ public class ToolCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "none" },
|
||||
usage = "",
|
||||
desc = "Unbind a bound tool from your current item",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "none",
|
||||
desc = "Unbind a bound tool from your current item"
|
||||
)
|
||||
public void none(Player player, LocalSession session) throws WorldEditException {
|
||||
|
||||
@ -62,11 +62,8 @@ public class ToolCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "info" },
|
||||
usage = "",
|
||||
desc = "Block information tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "info",
|
||||
desc = "Block information tool"
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.info")
|
||||
public void info(Player player, LocalSession session) throws WorldEditException {
|
||||
@ -78,49 +75,34 @@ public class ToolCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "tree" },
|
||||
usage = "[type]",
|
||||
desc = "Tree generator tool",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "tree",
|
||||
desc = "Tree generator tool"
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.tree")
|
||||
public void tree(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
TreeGenerator.TreeType type = args.argsLength() > 0
|
||||
? TreeGenerator.lookup(args.getString(0))
|
||||
: TreeGenerator.TreeType.TREE;
|
||||
|
||||
if (type == null) {
|
||||
player.printError("Tree type '" + args.getString(0) + "' is unknown.");
|
||||
return;
|
||||
}
|
||||
|
||||
public void tree(Player player, LocalSession session,
|
||||
@Arg(desc = "Type of tree to generate", def = "tree")
|
||||
TreeGenerator.TreeType type) throws WorldEditException {
|
||||
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
|
||||
session.setTool(itemStack.getType(), new TreePlanter(type));
|
||||
player.print("Tree tool bound to " + itemStack.getType().getName() + ".");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "repl" },
|
||||
usage = "<block>",
|
||||
desc = "Block replacer tool",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "repl",
|
||||
desc = "Block replacer tool"
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.replacer")
|
||||
public void repl(Player player, LocalSession session, Pattern pattern) throws WorldEditException {
|
||||
public void repl(Player player, LocalSession session,
|
||||
@Arg(desc = "The pattern of blocks to place")
|
||||
Pattern pattern) throws WorldEditException {
|
||||
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
|
||||
session.setTool(itemStack.getType(), new BlockReplacer(pattern));
|
||||
player.print("Block replacer tool bound to " + itemStack.getType().getName() + ".");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "cycler" },
|
||||
usage = "",
|
||||
desc = "Block data cycler tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "cycler",
|
||||
desc = "Block data cycler tool"
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.data-cycler")
|
||||
public void cycler(Player player, LocalSession session) throws WorldEditException {
|
||||
@ -131,14 +113,16 @@ public class ToolCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "floodfill", "flood" },
|
||||
usage = "<pattern> <range>",
|
||||
desc = "Flood fill tool",
|
||||
min = 2,
|
||||
max = 2
|
||||
name = "floodfill",
|
||||
aliases = { "flood" },
|
||||
desc = "Flood fill tool"
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.flood-fill")
|
||||
public void floodFill(Player player, LocalSession session, Pattern pattern, int range) throws WorldEditException {
|
||||
public void floodFill(Player player, LocalSession session,
|
||||
@Arg(desc = "The pattern to flood fill")
|
||||
Pattern pattern,
|
||||
@Arg(desc = "The range to perform the fill")
|
||||
int range) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
@ -153,11 +137,8 @@ public class ToolCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "deltree" },
|
||||
usage = "",
|
||||
desc = "Floating tree remover tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "deltree",
|
||||
desc = "Floating tree remover tool"
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.deltree")
|
||||
public void deltree(Player player, LocalSession session) throws WorldEditException {
|
||||
@ -169,11 +150,8 @@ public class ToolCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "farwand" },
|
||||
usage = "",
|
||||
desc = "Wand at a distance tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "farwand",
|
||||
desc = "Wand at a distance tool"
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.farwand")
|
||||
public void farwand(Player player, LocalSession session) throws WorldEditException {
|
||||
@ -184,14 +162,16 @@ public class ToolCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "lrbuild", "/lrbuild" },
|
||||
usage = "<leftclick block> <rightclick block>",
|
||||
desc = "Long-range building tool",
|
||||
min = 2,
|
||||
max = 2
|
||||
name = "lrbuild",
|
||||
aliases = { "/lrbuild" },
|
||||
desc = "Long-range building tool"
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.lrbuild")
|
||||
public void longrangebuildtool(Player player, LocalSession session, Pattern secondary, Pattern primary) throws WorldEditException {
|
||||
public void longrangebuildtool(Player player, LocalSession session,
|
||||
@Arg(desc = "Block to set on left-click")
|
||||
Pattern primary,
|
||||
@Arg(desc = "Block to set on right-click")
|
||||
Pattern secondary) throws WorldEditException {
|
||||
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
|
||||
|
||||
session.setTool(itemStack.getType(), new LongRangeBuildTool(primary, secondary));
|
||||
|
@ -19,21 +19,23 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.util.HandSide;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
|
||||
/**
|
||||
* Tool commands.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class ToolUtilCommands {
|
||||
private final WorldEdit we;
|
||||
|
||||
@ -42,29 +44,23 @@ public class ToolUtilCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/", "," },
|
||||
usage = "[on|off]",
|
||||
desc = "Toggle the super pickaxe function",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "/",
|
||||
aliases = { "," },
|
||||
desc = "Toggle the super pickaxe function"
|
||||
)
|
||||
@CommandPermissions("worldedit.superpickaxe")
|
||||
public void togglePickaxe(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
|
||||
String newState = args.getString(0, null);
|
||||
if (session.hasSuperPickAxe()) {
|
||||
if ("on".equals(newState)) {
|
||||
player.printError("Super pick axe already enabled.");
|
||||
public void togglePickaxe(Player player, LocalSession session,
|
||||
@Arg(desc = "The new super pickaxe state", def = "")
|
||||
Boolean superPickaxe) throws WorldEditException {
|
||||
boolean hasSuperPickAxe = session.hasSuperPickAxe();
|
||||
if (superPickaxe != null && superPickaxe == hasSuperPickAxe) {
|
||||
player.printError("Super pickaxe already " + (superPickaxe ? "enabled" : "disabled") + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasSuperPickAxe) {
|
||||
session.disableSuperPickAxe();
|
||||
player.print("Super pickaxe disabled.");
|
||||
} else {
|
||||
if ("off".equals(newState)) {
|
||||
player.printError("Super pick axe already disabled.");
|
||||
return;
|
||||
}
|
||||
session.enableSuperPickAxe();
|
||||
player.print("Super pickaxe enabled.");
|
||||
}
|
||||
@ -72,14 +68,13 @@ public class ToolUtilCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "mask" },
|
||||
usage = "[mask]",
|
||||
desc = "Set the brush mask",
|
||||
min = 0,
|
||||
max = -1
|
||||
name = "mask",
|
||||
desc = "Set the brush mask"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.options.mask")
|
||||
public void mask(Player player, LocalSession session, @Optional Mask mask) throws WorldEditException {
|
||||
public void mask(Player player, LocalSession session,
|
||||
@Arg(desc = "The mask to set", def = "")
|
||||
Mask mask) throws WorldEditException {
|
||||
if (mask == null) {
|
||||
session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setMask(null);
|
||||
player.print("Brush mask disabled.");
|
||||
@ -90,46 +85,41 @@ public class ToolUtilCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "mat", "material" },
|
||||
usage = "[pattern]",
|
||||
desc = "Set the brush material",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "material",
|
||||
aliases = { "/material" },
|
||||
desc = "Set the brush material"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.options.material")
|
||||
public void material(Player player, LocalSession session, Pattern pattern) throws WorldEditException {
|
||||
public void material(Player player, LocalSession session,
|
||||
@Arg(desc = "The pattern of blocks to use")
|
||||
Pattern pattern) throws WorldEditException {
|
||||
session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setFill(pattern);
|
||||
player.print("Brush material set.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "range" },
|
||||
usage = "[pattern]",
|
||||
desc = "Set the brush range",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "range",
|
||||
desc = "Set the brush range"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.options.range")
|
||||
public void range(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
int range = args.getInteger(0);
|
||||
public void range(Player player, LocalSession session,
|
||||
@Arg(desc = "The range of the brush")
|
||||
int range) throws WorldEditException {
|
||||
session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setRange(range);
|
||||
player.print("Brush range set.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "size" },
|
||||
usage = "[pattern]",
|
||||
desc = "Set the brush size",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "size",
|
||||
desc = "Set the brush size"
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.options.size")
|
||||
public void size(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
public void size(Player player, LocalSession session,
|
||||
@Arg(desc = "The size of the brush")
|
||||
int size) throws WorldEditException {
|
||||
we.checkMaxBrushRadius(size);
|
||||
|
||||
int radius = args.getInteger(0);
|
||||
we.checkMaxBrushRadius(radius);
|
||||
|
||||
session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setSize(radius);
|
||||
session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setSize(size);
|
||||
player.print("Brush size set.");
|
||||
}
|
||||
}
|
||||
|
@ -19,30 +19,31 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
|
||||
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.CreatureButcher;
|
||||
import com.sk89q.worldedit.command.util.EntityRemover;
|
||||
import com.sk89q.worldedit.command.util.Logging;
|
||||
import com.sk89q.worldedit.command.util.PrintCommandHelp;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.CommandManager;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.function.EntityFunction;
|
||||
import com.sk89q.worldedit.function.mask.BlockTypeMask;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||
import com.sk89q.worldedit.internal.expression.Expression;
|
||||
@ -52,32 +53,27 @@ import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.CylinderRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.session.SessionOwner;
|
||||
import com.sk89q.worldedit.util.command.CommandCallable;
|
||||
import com.sk89q.worldedit.util.command.CommandMapping;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import com.sk89q.worldedit.util.command.PrimaryAliasComparator;
|
||||
import com.sk89q.worldedit.util.command.binding.Text;
|
||||
import com.sk89q.worldedit.util.formatting.component.CodeFormat;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandListBox;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
|
||||
import com.sk89q.worldedit.util.formatting.component.ErrorFormat;
|
||||
import com.sk89q.worldedit.util.formatting.component.SubtleFormat;
|
||||
import com.sk89q.worldedit.util.formatting.component.TextComponentProducer;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Utility commands.
|
||||
*/
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class UtilityCommands {
|
||||
|
||||
private final WorldEdit we;
|
||||
@ -87,357 +83,365 @@ public class UtilityCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/fill" },
|
||||
usage = "<block> <radius> [depth]",
|
||||
desc = "Fill a hole",
|
||||
min = 2,
|
||||
max = 3
|
||||
name = "/fill",
|
||||
desc = "Fill a hole"
|
||||
)
|
||||
@CommandPermissions("worldedit.fill")
|
||||
@Logging(PLACEMENT)
|
||||
public void fill(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
Pattern pattern = we.getPatternFactory().parseFromInput(args.getString(0), context);
|
||||
|
||||
double radius = Math.max(1, args.getDouble(1));
|
||||
public int fill(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The blocks to fill with")
|
||||
Pattern pattern,
|
||||
@Arg(desc = "The radius to fill in")
|
||||
double radius,
|
||||
@Arg(desc = "The depth to fill", def = "1")
|
||||
int depth) throws WorldEditException {
|
||||
radius = Math.max(1, radius);
|
||||
we.checkMaxRadius(radius);
|
||||
int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : 1;
|
||||
depth = Math.max(1, depth);
|
||||
|
||||
BlockVector3 pos = session.getPlacementPosition(player);
|
||||
int affected = editSession.fillXZ(pos, pattern, radius, depth, false);
|
||||
player.print(affected + " block(s) have been created.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/fillr" },
|
||||
usage = "<block> <radius> [depth]",
|
||||
desc = "Fill a hole recursively",
|
||||
min = 2,
|
||||
max = 3
|
||||
name = "/fillr",
|
||||
desc = "Fill a hole recursively"
|
||||
)
|
||||
@CommandPermissions("worldedit.fill.recursive")
|
||||
@Logging(PLACEMENT)
|
||||
public void fillr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
Pattern pattern = we.getPatternFactory().parseFromInput(args.getString(0), context);
|
||||
|
||||
double radius = Math.max(1, args.getDouble(1));
|
||||
public int fillr(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The blocks to fill with")
|
||||
Pattern pattern,
|
||||
@Arg(desc = "The radius to fill in")
|
||||
double radius,
|
||||
@Arg(desc = "The depth to fill", def = "")
|
||||
Integer depth) throws WorldEditException {
|
||||
radius = Math.max(1, radius);
|
||||
we.checkMaxRadius(radius);
|
||||
depth = depth == null ? Integer.MAX_VALUE : Math.max(1, depth);
|
||||
we.checkMaxRadius(radius);
|
||||
int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : Integer.MAX_VALUE;
|
||||
|
||||
BlockVector3 pos = session.getPlacementPosition(player);
|
||||
int affected = 0;
|
||||
if (pattern instanceof BlockPattern) {
|
||||
affected = editSession.fillXZ(pos, ((BlockPattern) pattern).getBlock(), radius, depth, true);
|
||||
} else {
|
||||
affected = editSession.fillXZ(pos, pattern, radius, depth, true);
|
||||
}
|
||||
int affected = editSession.fillXZ(pos, pattern, radius, depth, true);
|
||||
player.print(affected + " block(s) have been created.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/drain" },
|
||||
usage = "<radius>",
|
||||
flags = "w",
|
||||
desc = "Drain a pool",
|
||||
help = "Removes all connected water sources.\n" +
|
||||
" If -w is specified, also makes waterlogged blocks non-waterlogged.",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "/drain",
|
||||
desc = "Drain a pool"
|
||||
)
|
||||
@CommandPermissions("worldedit.drain")
|
||||
@Logging(PLACEMENT)
|
||||
public void drain(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
double radius = Math.max(0, args.getDouble(0));
|
||||
boolean waterlogged = args.hasFlag('w');
|
||||
public int drain(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The radius to drain")
|
||||
double radius,
|
||||
@Switch(name = 'w', desc = "Also un-waterlog blocks")
|
||||
boolean waterlogged) throws WorldEditException {
|
||||
radius = Math.max(0, radius);
|
||||
we.checkMaxRadius(radius);
|
||||
int affected = editSession.drainArea(
|
||||
session.getPlacementPosition(player), radius, waterlogged);
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/fixlava", "fixlava" },
|
||||
usage = "<radius>",
|
||||
desc = "Fix lava to be stationary",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "fixlava",
|
||||
aliases = { "/fixlava" },
|
||||
desc = "Fix lava to be stationary"
|
||||
)
|
||||
@CommandPermissions("worldedit.fixlava")
|
||||
@Logging(PLACEMENT)
|
||||
public void fixLava(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
double radius = Math.max(0, args.getDouble(0));
|
||||
public int fixLava(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The radius to fix in")
|
||||
double radius) throws WorldEditException {
|
||||
radius = Math.max(0, radius);
|
||||
we.checkMaxRadius(radius);
|
||||
int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.LAVA);
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/fixwater", "fixwater" },
|
||||
usage = "<radius>",
|
||||
desc = "Fix water to be stationary",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "fixwater",
|
||||
aliases = { "/fixwater" },
|
||||
desc = "Fix water to be stationary"
|
||||
)
|
||||
@CommandPermissions("worldedit.fixwater")
|
||||
@Logging(PLACEMENT)
|
||||
public void fixWater(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
double radius = Math.max(0, args.getDouble(0));
|
||||
public int fixWater(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The radius to fix in")
|
||||
double radius) throws WorldEditException {
|
||||
radius = Math.max(0, radius);
|
||||
we.checkMaxRadius(radius);
|
||||
int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.WATER);
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/removeabove", "removeabove" },
|
||||
usage = "[size] [height]",
|
||||
desc = "Remove blocks above your head.",
|
||||
min = 0,
|
||||
max = 2
|
||||
name = "removeabove",
|
||||
aliases = { "/removeabove" },
|
||||
desc = "Remove blocks above your head."
|
||||
)
|
||||
@CommandPermissions("worldedit.removeabove")
|
||||
@Logging(PLACEMENT)
|
||||
public void removeAbove(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1;
|
||||
public int removeAbove(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The apothem of the square to remove from", def = "1")
|
||||
int size,
|
||||
@Arg(desc = "The maximum height above you to remove from", def = "")
|
||||
Integer height) throws WorldEditException {
|
||||
size = Math.max(1, size);
|
||||
we.checkMaxRadius(size);
|
||||
World world = player.getWorld();
|
||||
int height = args.argsLength() > 1 ? Math.min((world.getMaxY() + 1), args.getInteger(1) + 2) : (world.getMaxY() + 1);
|
||||
height = height != null ? Math.min((world.getMaxY() + 1), height + 2) : (world.getMaxY() + 1);
|
||||
|
||||
int affected = editSession.removeAbove(
|
||||
session.getPlacementPosition(player), size, height);
|
||||
player.print(affected + " block(s) have been removed.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/removebelow", "removebelow" },
|
||||
usage = "[size] [height]",
|
||||
desc = "Remove blocks below you.",
|
||||
min = 0,
|
||||
max = 2
|
||||
name = "removebelow",
|
||||
aliases = { "/removebelow" },
|
||||
desc = "Remove blocks below you."
|
||||
)
|
||||
@CommandPermissions("worldedit.removebelow")
|
||||
@Logging(PLACEMENT)
|
||||
public void removeBelow(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1;
|
||||
public int removeBelow(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The apothem of the square to remove from", def = "1")
|
||||
int size,
|
||||
@Arg(desc = "The maximum height below you to remove from", def = "")
|
||||
Integer height) throws WorldEditException {
|
||||
size = Math.max(1, size);
|
||||
we.checkMaxRadius(size);
|
||||
World world = player.getWorld();
|
||||
int height = args.argsLength() > 1 ? Math.min((world.getMaxY() + 1), args.getInteger(1) + 2) : (world.getMaxY() + 1);
|
||||
height = height != null ? Math.min((-world.getMaxY() + 1), height + 2) : (world.getMaxY() + 1);
|
||||
|
||||
int affected = editSession.removeBelow(session.getPlacementPosition(player), size, height);
|
||||
player.print(affected + " block(s) have been removed.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/removenear", "removenear" },
|
||||
usage = "<block> [size]",
|
||||
desc = "Remove blocks near you.",
|
||||
min = 1,
|
||||
max = 2
|
||||
name = "removenear",
|
||||
aliases = { "/removenear" },
|
||||
desc = "Remove blocks near you."
|
||||
)
|
||||
@CommandPermissions("worldedit.removenear")
|
||||
@Logging(PLACEMENT)
|
||||
public void removeNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
public int removeNear(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The mask of blocks to remove")
|
||||
Mask mask,
|
||||
@Arg(desc = "The radius of the square to remove from", def = "50")
|
||||
int radius) throws WorldEditException {
|
||||
radius = Math.max(1, radius);
|
||||
we.checkMaxRadius(radius);
|
||||
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
context.setRestricted(false);
|
||||
context.setPreferringWildcard(false);
|
||||
|
||||
BaseBlock block = we.getBlockFactory().parseFromInput(args.getString(0), context);
|
||||
int size = Math.max(1, args.getInteger(1, 50));
|
||||
we.checkMaxRadius(size);
|
||||
|
||||
int affected = editSession.removeNear(session.getPlacementPosition(player), block.getBlockType(), size);
|
||||
int affected = editSession.removeNear(session.getPlacementPosition(player), mask, radius);
|
||||
player.print(affected + " block(s) have been removed.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/replacenear", "replacenear" },
|
||||
usage = "<size> <from-id> <to-id>",
|
||||
desc = "Replace nearby blocks",
|
||||
flags = "f",
|
||||
min = 3,
|
||||
max = 3
|
||||
name = "replacenear",
|
||||
aliases = { "/replacenear" },
|
||||
desc = "Replace nearby blocks"
|
||||
)
|
||||
@CommandPermissions("worldedit.replacenear")
|
||||
@Logging(PLACEMENT)
|
||||
public void replaceNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
int size = Math.max(1, args.getInteger(0));
|
||||
we.checkMaxRadius(size);
|
||||
int affected;
|
||||
Set<BaseBlock> from;
|
||||
Pattern to;
|
||||
|
||||
ParserContext context = new ParserContext();
|
||||
context.setActor(player);
|
||||
context.setWorld(player.getWorld());
|
||||
context.setSession(session);
|
||||
context.setRestricted(false);
|
||||
context.setPreferringWildcard(!args.hasFlag('f'));
|
||||
|
||||
if (args.argsLength() == 2) {
|
||||
from = null;
|
||||
context.setRestricted(true);
|
||||
to = we.getPatternFactory().parseFromInput(args.getString(1), context);
|
||||
} else {
|
||||
from = we.getBlockFactory().parseFromListInput(args.getString(1), context);
|
||||
context.setRestricted(true);
|
||||
to = we.getPatternFactory().parseFromInput(args.getString(2), context);
|
||||
}
|
||||
public int replaceNear(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The radius of the square to remove in")
|
||||
int radius,
|
||||
@Arg(desc = "The mask matching blocks to remove", def = "")
|
||||
Mask from,
|
||||
@Arg(desc = "The pattern of blocks to replace with")
|
||||
Pattern to) throws WorldEditException {
|
||||
radius = Math.max(1, radius);
|
||||
we.checkMaxRadius(radius);
|
||||
|
||||
BlockVector3 base = session.getPlacementPosition(player);
|
||||
BlockVector3 min = base.subtract(size, size, size);
|
||||
BlockVector3 max = base.add(size, size, size);
|
||||
BlockVector3 min = base.subtract(radius, radius, radius);
|
||||
BlockVector3 max = base.add(radius, radius, radius);
|
||||
Region region = new CuboidRegion(player.getWorld(), min, max);
|
||||
|
||||
if (to instanceof BlockPattern) {
|
||||
affected = editSession.replaceBlocks(region, from, ((BlockPattern) to).getBlock());
|
||||
} else {
|
||||
affected = editSession.replaceBlocks(region, from, to);
|
||||
if (from == null) {
|
||||
from = new ExistingBlockMask(editSession);
|
||||
}
|
||||
|
||||
int affected = editSession.replaceBlocks(region, from, to);
|
||||
player.print(affected + " block(s) have been replaced.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/snow", "snow" },
|
||||
usage = "[radius]",
|
||||
desc = "Simulates snow",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "snow",
|
||||
aliases = { "/snow" },
|
||||
desc = "Simulates snow"
|
||||
)
|
||||
@CommandPermissions("worldedit.snow")
|
||||
@Logging(PLACEMENT)
|
||||
public void snow(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
|
||||
public int snow(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The radius of the circle to snow in", def = "10")
|
||||
double size) throws WorldEditException {
|
||||
size = Math.max(1, size);
|
||||
we.checkMaxRadius(size);
|
||||
|
||||
int affected = editSession.simulateSnow(session.getPlacementPosition(player), size);
|
||||
player.print(affected + " surfaces covered. Let it snow~");
|
||||
player.print(affected + " surface(s) covered. Let it snow~");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"/thaw", "thaw"},
|
||||
usage = "[radius]",
|
||||
desc = "Thaws the area",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "thaw",
|
||||
aliases = { "/thaw" },
|
||||
desc = "Thaws the area"
|
||||
)
|
||||
@CommandPermissions("worldedit.thaw")
|
||||
@Logging(PLACEMENT)
|
||||
public void thaw(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
|
||||
public int thaw(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The radius of the circle to thaw in", def = "10")
|
||||
double size) throws WorldEditException {
|
||||
size = Math.max(1, size);
|
||||
we.checkMaxRadius(size);
|
||||
|
||||
int affected = editSession.thaw(session.getPlacementPosition(player), size);
|
||||
player.print(affected + " surfaces thawed.");
|
||||
player.print(affected + " surface(s) thawed.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/green", "green" },
|
||||
usage = "[radius]",
|
||||
desc = "Greens the area",
|
||||
help = "Converts dirt to grass blocks. -f also converts coarse dirt.",
|
||||
flags = "f",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "green",
|
||||
aliases = { "/green" },
|
||||
desc = "Converts dirt to grass blocks in the area"
|
||||
)
|
||||
@CommandPermissions("worldedit.green")
|
||||
@Logging(PLACEMENT)
|
||||
public void green(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
final double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
|
||||
public int green(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The radius of the circle to convert in", def = "10")
|
||||
double size,
|
||||
@Switch(name = 'f', desc = "Also convert coarse dirt")
|
||||
boolean convertCoarse) throws WorldEditException {
|
||||
size = Math.max(1, size);
|
||||
we.checkMaxRadius(size);
|
||||
final boolean onlyNormalDirt = !args.hasFlag('f');
|
||||
final boolean onlyNormalDirt = !convertCoarse;
|
||||
|
||||
final int affected = editSession.green(session.getPlacementPosition(player), size, onlyNormalDirt);
|
||||
player.print(affected + " surfaces greened.");
|
||||
player.print(affected + " surface(s) greened.");
|
||||
return affected;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/ex", "/ext", "/extinguish", "ex", "ext", "extinguish" },
|
||||
usage = "[radius]",
|
||||
desc = "Extinguish nearby fire",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "extinguish",
|
||||
aliases = { "/ex", "/ext", "/extinguish", "ex", "ext" },
|
||||
desc = "Extinguish nearby fire"
|
||||
)
|
||||
@CommandPermissions("worldedit.extinguish")
|
||||
@Logging(PLACEMENT)
|
||||
public void extinguish(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
public void extinguish(Player player, LocalSession session, EditSession editSession,
|
||||
@Arg(desc = "The radius of the square to remove in", def = "")
|
||||
Integer radius) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40;
|
||||
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0))
|
||||
: defaultRadius;
|
||||
int size = radius != null ? Math.max(1, radius) : defaultRadius;
|
||||
we.checkMaxRadius(size);
|
||||
|
||||
int affected = editSession.removeNear(session.getPlacementPosition(player), BlockTypes.FIRE, size);
|
||||
Mask mask = new BlockTypeMask(editSession, BlockTypes.FIRE);
|
||||
int affected = editSession.removeNear(session.getPlacementPosition(player), mask, size);
|
||||
player.print(affected + " block(s) have been removed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "butcher" },
|
||||
usage = "[radius]",
|
||||
flags = "plangbtfr",
|
||||
desc = "Kill all or nearby mobs",
|
||||
help =
|
||||
"Kills nearby mobs, based on radius, if none is given uses default in configuration.\n" +
|
||||
"Flags:\n" +
|
||||
" -p also kills pets.\n" +
|
||||
" -n also kills NPCs.\n" +
|
||||
" -g also kills Golems.\n" +
|
||||
" -a also kills animals.\n" +
|
||||
" -b also kills ambient mobs.\n" +
|
||||
" -t also kills mobs with name tags.\n" +
|
||||
" -f compounds all previous flags.\n" +
|
||||
" -r also destroys armor stands.\n" +
|
||||
" -l currently does nothing.",
|
||||
min = 0,
|
||||
max = 1
|
||||
name = "butcher",
|
||||
desc = "Kill all or nearby mobs"
|
||||
)
|
||||
@CommandPermissions("worldedit.butcher")
|
||||
@Logging(PLACEMENT)
|
||||
public void butcher(Actor actor, CommandContext args) throws WorldEditException {
|
||||
public int butcher(Actor actor,
|
||||
@Arg(desc = "Radius to kill mobs in", def = "")
|
||||
Integer radius,
|
||||
@Switch(name = 'p', desc = "Also kill pets")
|
||||
boolean killPets,
|
||||
@Switch(name = 'n', desc = "Also kill NPCs")
|
||||
boolean killNpcs,
|
||||
@Switch(name = 'g', desc = "Also kill golems")
|
||||
boolean killGolems,
|
||||
@Switch(name = 'a', desc = "Also kill animals")
|
||||
boolean killAnimals,
|
||||
@Switch(name = 'b', desc = "Also kill ambient mobs")
|
||||
boolean killAmbient,
|
||||
@Switch(name = 't', desc = "Also kill mobs with name tags")
|
||||
boolean killWithName,
|
||||
@Switch(name = 'f', desc = "Also kill all friendly mobs (Applies the flags `-abgnpt`)")
|
||||
boolean killFriendly,
|
||||
@Switch(name = 'r', desc = "Also destroy armor stands")
|
||||
boolean killArmorStands) throws WorldEditException {
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
Player player = actor instanceof Player ? (Player) actor : null;
|
||||
|
||||
// technically the default can be larger than the max, but that's not my problem
|
||||
int radius = config.butcherDefaultRadius;
|
||||
|
||||
// there might be a better way to do this but my brain is fried right now
|
||||
if (args.argsLength() > 0) { // user inputted radius, override the default
|
||||
radius = args.getInteger(0);
|
||||
if (radius < -1) {
|
||||
if (radius == null) {
|
||||
radius = config.butcherDefaultRadius;
|
||||
} else if (radius < -1) {
|
||||
actor.printError("Use -1 to remove all mobs in loaded chunks");
|
||||
return;
|
||||
}
|
||||
if (config.butcherMaxRadius != -1) { // clamp if there is a max
|
||||
if (radius == -1) {
|
||||
return 0;
|
||||
} else if (radius == -1) {
|
||||
if (config.butcherMaxRadius != -1) {
|
||||
radius = config.butcherMaxRadius;
|
||||
} else { // Math.min does not work if radius is -1 (actually highest possible value)
|
||||
}
|
||||
}
|
||||
if (config.butcherMaxRadius != -1) {
|
||||
radius = Math.min(radius, config.butcherMaxRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CreatureButcher flags = new CreatureButcher(actor);
|
||||
flags.fromCommand(args);
|
||||
flags.or(CreatureButcher.Flags.FRIENDLY, killFriendly); // No permission check here. Flags will instead be filtered by the subsequent calls.
|
||||
flags.or(CreatureButcher.Flags.PETS, killPets, "worldedit.butcher.pets");
|
||||
flags.or(CreatureButcher.Flags.NPCS, killNpcs, "worldedit.butcher.npcs");
|
||||
flags.or(CreatureButcher.Flags.GOLEMS, killGolems, "worldedit.butcher.golems");
|
||||
flags.or(CreatureButcher.Flags.ANIMALS, killAnimals, "worldedit.butcher.animals");
|
||||
flags.or(CreatureButcher.Flags.AMBIENT, killAmbient, "worldedit.butcher.ambient");
|
||||
flags.or(CreatureButcher.Flags.TAGGED, killWithName, "worldedit.butcher.tagged");
|
||||
flags.or(CreatureButcher.Flags.ARMOR_STAND, killArmorStands, "worldedit.butcher.armorstands");
|
||||
|
||||
int killed = killMatchingEntities(radius, player, flags::createFunction);
|
||||
|
||||
actor.print("Killed " + killed + (killed != 1 ? " mobs" : " mob") + (radius < 0 ? "" : " in a radius of " + radius) + ".");
|
||||
|
||||
return killed;
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "remove",
|
||||
aliases = { "rem", "rement" },
|
||||
desc = "Remove all entities of a type"
|
||||
)
|
||||
@CommandPermissions("worldedit.remove")
|
||||
@Logging(PLACEMENT)
|
||||
public int remove(Actor actor,
|
||||
@Arg(desc = "The type of entity to remove")
|
||||
EntityRemover remover,
|
||||
@Arg(desc = "The radius of the cuboid to remove from")
|
||||
int radius) throws WorldEditException {
|
||||
Player player = actor instanceof Player ? (Player) actor : null;
|
||||
|
||||
if (radius < -1) {
|
||||
actor.printError("Use -1 to remove all entities in loaded chunks");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int removed = killMatchingEntities(radius, player, remover::createFunction);
|
||||
|
||||
actor.print("Marked " + removed + (removed != 1 ? " entities" : " entity") + " for removal.");
|
||||
return removed;
|
||||
}
|
||||
|
||||
private int killMatchingEntities(Integer radius, Player player, Supplier<EntityFunction> func) throws IncompleteRegionException, MaxChangedBlocksException {
|
||||
List<EntityVisitor> visitors = new ArrayList<>();
|
||||
LocalSession session = null;
|
||||
EditSession editSession = null;
|
||||
@ -453,12 +457,12 @@ public class UtilityCommands {
|
||||
} else {
|
||||
entities = editSession.getEntities();
|
||||
}
|
||||
visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction()));
|
||||
visitors.add(new EntityVisitor(entities.iterator(), func.get()));
|
||||
} else {
|
||||
Platform platform = we.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
|
||||
for (World world : platform.getWorlds()) {
|
||||
List<? extends Entity> entities = world.getEntities();
|
||||
visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction()));
|
||||
visitors.add(new EntityVisitor(entities.iterator(), func.get()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,89 +472,35 @@ public class UtilityCommands {
|
||||
killed += visitor.getAffected();
|
||||
}
|
||||
|
||||
actor.print("Killed " + killed + (killed != 1 ? " mobs" : " mob") + (radius < 0 ? "" : " in a radius of " + radius) + ".");
|
||||
|
||||
if (editSession != null) {
|
||||
session.remember(editSession);
|
||||
editSession.flushSession();
|
||||
}
|
||||
return killed;
|
||||
}
|
||||
|
||||
// get the formatter with the system locale. in the future, if we can get a local from a player, we can use that
|
||||
private static final DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.getDefault());
|
||||
static {
|
||||
formatter.applyPattern("#,##0.#####"); // pattern is locale-insensitive. this can translate to "1.234,56789"
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "remove", "rem", "rement" },
|
||||
usage = "<type> <radius>",
|
||||
desc = "Remove all entities of a type",
|
||||
min = 2,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.remove")
|
||||
@Logging(PLACEMENT)
|
||||
public void remove(Actor actor, CommandContext args) throws WorldEditException, CommandException {
|
||||
String typeStr = args.getString(0);
|
||||
int radius = args.getInteger(1);
|
||||
Player player = actor instanceof Player ? (Player) actor : null;
|
||||
|
||||
if (radius < -1) {
|
||||
actor.printError("Use -1 to remove all entities in loaded chunks");
|
||||
return;
|
||||
}
|
||||
|
||||
EntityRemover remover = new EntityRemover();
|
||||
remover.fromString(typeStr);
|
||||
|
||||
List<EntityVisitor> visitors = new ArrayList<>();
|
||||
LocalSession session = null;
|
||||
EditSession editSession = null;
|
||||
|
||||
if (player != null) {
|
||||
session = we.getSessionManager().get(player);
|
||||
BlockVector3 center = session.getPlacementPosition(player);
|
||||
editSession = session.createEditSession(player);
|
||||
List<? extends Entity> entities;
|
||||
if (radius >= 0) {
|
||||
CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius);
|
||||
entities = editSession.getEntities(region);
|
||||
} else {
|
||||
entities = editSession.getEntities();
|
||||
}
|
||||
visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction()));
|
||||
} else {
|
||||
Platform platform = we.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
|
||||
for (World world : platform.getWorlds()) {
|
||||
List<? extends Entity> entities = world.getEntities();
|
||||
visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction()));
|
||||
}
|
||||
}
|
||||
|
||||
int removed = 0;
|
||||
for (EntityVisitor visitor : visitors) {
|
||||
Operations.completeLegacy(visitor);
|
||||
removed += visitor.getAffected();
|
||||
}
|
||||
|
||||
actor.print("Marked " + removed + (removed != 1 ? " entities" : " entity") + " for removal.");
|
||||
|
||||
if (editSession != null) {
|
||||
session.remember(editSession);
|
||||
editSession.flushSession();
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/calc", "/calculate", "/eval", "/evaluate", "/solve" },
|
||||
usage = "<expression>",
|
||||
name = "/calculate",
|
||||
aliases = { "/calc", "/eval", "/evaluate", "/solve" },
|
||||
desc = "Evaluate a mathematical expression"
|
||||
)
|
||||
@CommandPermissions("worldedit.calc")
|
||||
public void calc(Actor actor, @Text String input) throws CommandException {
|
||||
public void calc(Actor actor,
|
||||
@Arg(desc = "Expression to evaluate", variable = true)
|
||||
List<String> input) {
|
||||
try {
|
||||
Expression expression = Expression.compile(input);
|
||||
if (actor instanceof SessionOwner) {
|
||||
actor.print("= " + expression.evaluate(
|
||||
new double[]{}, WorldEdit.getInstance().getSessionManager().get((SessionOwner) actor).getTimeout()));
|
||||
} else {
|
||||
actor.print("= " + expression.evaluate());
|
||||
}
|
||||
Expression expression = Expression.compile(String.join(" ", input));
|
||||
double result = expression.evaluate(
|
||||
new double[]{}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout());
|
||||
String formatted = formatter.format(result);
|
||||
actor.print(SubtleFormat.wrap(input + " = ")
|
||||
.append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE)));
|
||||
} catch (EvaluationException e) {
|
||||
actor.printError(String.format(
|
||||
"'%s' could not be evaluated (error: %s)", input, e.getMessage()));
|
||||
@ -561,152 +511,16 @@ public class UtilityCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/help" },
|
||||
usage = "[<command>]",
|
||||
desc = "Displays help for WorldEdit commands",
|
||||
min = 0,
|
||||
max = -1
|
||||
name = "/help",
|
||||
desc = "Displays help for WorldEdit commands"
|
||||
)
|
||||
@CommandPermissions("worldedit.help")
|
||||
public void help(Actor actor, CommandContext args) throws WorldEditException {
|
||||
help(args, we, actor);
|
||||
}
|
||||
|
||||
private static CommandMapping detectCommand(Dispatcher dispatcher, String command, boolean isRootLevel) {
|
||||
CommandMapping mapping;
|
||||
|
||||
// First try the command as entered
|
||||
mapping = dispatcher.get(command);
|
||||
if (mapping != null) {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
// Then if we're looking at root commands and the user didn't use
|
||||
// any slashes, let's try double slashes and then single slashes.
|
||||
// However, be aware that there exists different single slash
|
||||
// and double slash commands in WorldEdit
|
||||
if (isRootLevel && !command.contains("/")) {
|
||||
mapping = dispatcher.get("//" + command);
|
||||
if (mapping != null) {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
mapping = dispatcher.get("/" + command);
|
||||
if (mapping != null) {
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void help(CommandContext args, WorldEdit we, Actor actor) {
|
||||
CommandCallable callable = we.getPlatformManager().getCommandManager().getDispatcher();
|
||||
|
||||
int page = 0;
|
||||
final int perPage = actor instanceof Player ? 8 : 20; // More pages for console
|
||||
int effectiveLength = args.argsLength();
|
||||
|
||||
// Detect page from args
|
||||
try {
|
||||
if (args.argsLength() > 0) {
|
||||
page = args.getInteger(args.argsLength() - 1);
|
||||
if (page <= 0) {
|
||||
page = 1;
|
||||
} else {
|
||||
page--;
|
||||
}
|
||||
|
||||
effectiveLength--;
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
|
||||
boolean isRootLevel = true;
|
||||
List<String> visited = new ArrayList<>();
|
||||
|
||||
// Drill down to the command
|
||||
for (int i = 0; i < effectiveLength; i++) {
|
||||
String command = args.getString(i);
|
||||
|
||||
if (callable instanceof Dispatcher) {
|
||||
// Chop off the beginning / if we're are the root level
|
||||
if (isRootLevel && command.length() > 1 && command.charAt(0) == '/') {
|
||||
command = command.substring(1);
|
||||
}
|
||||
|
||||
CommandMapping mapping = detectCommand((Dispatcher) callable, command, isRootLevel);
|
||||
if (mapping != null) {
|
||||
callable = mapping.getCallable();
|
||||
} else {
|
||||
if (isRootLevel) {
|
||||
actor.printError(String.format("The command '%s' could not be found.", args.getString(i)));
|
||||
return;
|
||||
} else {
|
||||
actor.printError(String.format("The sub-command '%s' under '%s' could not be found.",
|
||||
command, Joiner.on(" ").join(visited)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
visited.add(args.getString(i));
|
||||
isRootLevel = false;
|
||||
} else {
|
||||
actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)",
|
||||
Joiner.on(" ").join(visited), command));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the message
|
||||
if (callable instanceof Dispatcher) {
|
||||
Dispatcher dispatcher = (Dispatcher) callable;
|
||||
|
||||
// Get a list of aliases
|
||||
List<CommandMapping> aliases = new ArrayList<>(dispatcher.getCommands());
|
||||
aliases.sort(new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN));
|
||||
|
||||
// Calculate pagination
|
||||
int offset = perPage * page;
|
||||
int pageTotal = (int) Math.ceil(aliases.size() / (double) perPage);
|
||||
|
||||
// Box
|
||||
CommandListBox box = new CommandListBox(String.format("Help: page %d/%d ", page + 1, pageTotal));
|
||||
TextComponentProducer tip = new TextComponentProducer();
|
||||
tip.getBuilder().content("").color(TextColor.GRAY);
|
||||
TextComponentProducer contents = box.getContents();
|
||||
|
||||
if (offset >= aliases.size()) {
|
||||
tip.append(ErrorFormat.wrap(String.format("There is no page %d (total number of pages is %d).", page + 1, pageTotal))).newline();
|
||||
} else {
|
||||
List<CommandMapping> list = aliases.subList(offset, Math.min(offset + perPage, aliases.size()));
|
||||
|
||||
tip.append("Type ");
|
||||
tip.append(CodeFormat.wrap("//help "));
|
||||
tip.append("<command> [<page>] for more information.");
|
||||
tip.newline();
|
||||
|
||||
// Add each command
|
||||
for (CommandMapping mapping : list) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (isRootLevel) {
|
||||
builder.append("/");
|
||||
}
|
||||
if (!visited.isEmpty()) {
|
||||
builder.append(Joiner.on(" ").join(visited));
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append(mapping.getPrimaryAlias());
|
||||
box.appendCommand(builder.toString(), mapping.getDescription().getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
contents.append(tip.create());
|
||||
actor.print(box.create());
|
||||
} else {
|
||||
CommandUsageBox box = new CommandUsageBox(callable, Joiner.on(" ").join(visited));
|
||||
actor.print(box.create());
|
||||
}
|
||||
public void help(Actor actor,
|
||||
@Arg(desc = "The page to retrieve", def = "1")
|
||||
int page,
|
||||
@Arg(desc = "The command to retrieve help for", def = "", variable = true)
|
||||
List<String> command) throws WorldEditException {
|
||||
PrintCommandHelp.help(command, page, we, actor);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,12 +20,12 @@
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.command.util.PrintCommandHelp;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
@ -36,17 +36,25 @@ import com.sk89q.worldedit.util.paste.ActorCallbackPaste;
|
||||
import com.sk89q.worldedit.util.report.ConfigReport;
|
||||
import com.sk89q.worldedit.util.report.ReportList;
|
||||
import com.sk89q.worldedit.util.report.SystemInfoReport;
|
||||
import org.enginehub.piston.annotation.Command;
|
||||
import org.enginehub.piston.annotation.CommandContainer;
|
||||
import org.enginehub.piston.annotation.param.Arg;
|
||||
import org.enginehub.piston.annotation.param.Switch;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.TextStyle;
|
||||
import java.time.zone.ZoneRulesException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||
public class WorldEditCommands {
|
||||
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
|
||||
private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
|
||||
|
||||
private final WorldEdit we;
|
||||
|
||||
@ -55,15 +63,13 @@ public class WorldEditCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "version", "ver" },
|
||||
usage = "",
|
||||
desc = "Get WorldEdit version",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "version",
|
||||
aliases = { "ver" },
|
||||
desc = "Get WorldEdit version"
|
||||
)
|
||||
public void version(Actor actor) throws WorldEditException {
|
||||
actor.print("WorldEdit version " + WorldEdit.getVersion());
|
||||
actor.print("https://github.com/sk89q/worldedit/");
|
||||
actor.print("https://github.com/EngineHub/worldedit/");
|
||||
|
||||
PlatformManager pm = we.getPlatformManager();
|
||||
|
||||
@ -80,11 +86,8 @@ public class WorldEditCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "reload" },
|
||||
usage = "",
|
||||
desc = "Reload configuration",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "reload",
|
||||
desc = "Reload configuration"
|
||||
)
|
||||
@CommandPermissions("worldedit.reload")
|
||||
public void reload(Actor actor) throws WorldEditException {
|
||||
@ -93,9 +96,14 @@ public class WorldEditCommands {
|
||||
actor.print("Configuration reloaded!");
|
||||
}
|
||||
|
||||
@Command(aliases = {"report"}, desc = "Writes a report on WorldEdit", flags = "p", max = 0)
|
||||
@Command(
|
||||
name = "report",
|
||||
desc = "Writes a report on WorldEdit"
|
||||
)
|
||||
@CommandPermissions({"worldedit.report"})
|
||||
public void report(Actor actor, CommandContext args) throws WorldEditException {
|
||||
public void report(Actor actor,
|
||||
@Switch(name = 'p', desc = "Pastebins the report")
|
||||
boolean pastebin) throws WorldEditException {
|
||||
ReportList report = new ReportList("Report");
|
||||
report.add(new SystemInfoReport());
|
||||
report.add(new ConfigReport());
|
||||
@ -109,21 +117,18 @@ public class WorldEditCommands {
|
||||
actor.printError("Failed to write report: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (args.hasFlag('p')) {
|
||||
if (pastebin) {
|
||||
actor.checkPermission("worldedit.report.pastebin");
|
||||
ActorCallbackPaste.pastebin(
|
||||
we.getSupervisor(), actor, result, "WorldEdit report: %s.report",
|
||||
WorldEdit.getInstance().getPlatformManager().getCommandManager().getExceptionConverter()
|
||||
WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getExceptionConverter()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "cui" },
|
||||
usage = "",
|
||||
desc = "Complete CUI handshake (internal usage)",
|
||||
min = 0,
|
||||
max = 0
|
||||
name = "cui",
|
||||
desc = "Complete CUI handshake (internal usage)"
|
||||
)
|
||||
public void cui(Player player, LocalSession session) throws WorldEditException {
|
||||
session.setCUISupport(true);
|
||||
@ -131,29 +136,34 @@ public class WorldEditCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "tz" },
|
||||
usage = "[timezone]",
|
||||
desc = "Set your timezone for snapshots",
|
||||
min = 1,
|
||||
max = 1
|
||||
name = "tz",
|
||||
desc = "Set your timezone for snapshots"
|
||||
)
|
||||
public void tz(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
TimeZone tz = TimeZone.getTimeZone(args.getString(0));
|
||||
public void tz(Player player, LocalSession session,
|
||||
@Arg(desc = "The timezone to set")
|
||||
String timezone) throws WorldEditException {
|
||||
try {
|
||||
ZoneId tz = ZoneId.of(timezone);
|
||||
session.setTimezone(tz);
|
||||
player.print("Timezone set for this session to: " + tz.getDisplayName());
|
||||
player.print("The current time in that timezone is: "
|
||||
+ dateFormat.format(Calendar.getInstance(tz).getTime()));
|
||||
player.print("Timezone set for this session to: " + tz.getDisplayName(
|
||||
TextStyle.FULL, Locale.ENGLISH
|
||||
));
|
||||
player.print("The current time in that timezone is: " + dateFormat.format(ZonedDateTime.now(tz)));
|
||||
} catch (ZoneRulesException e) {
|
||||
player.printError("Invalid timezone");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "help" },
|
||||
usage = "[<command>]",
|
||||
desc = "Displays help for WorldEdit commands",
|
||||
min = 0,
|
||||
max = -1
|
||||
name = "help",
|
||||
desc = "Displays help for WorldEdit commands"
|
||||
)
|
||||
@CommandPermissions("worldedit.help")
|
||||
public void help(Actor actor, CommandContext args) throws WorldEditException {
|
||||
UtilityCommands.help(args, we, actor);
|
||||
public void help(Actor actor,
|
||||
@Arg(desc = "The page to retrieve", def = "1")
|
||||
int page,
|
||||
@Arg(desc = "The command to retrieve help for", def = "", variable = true)
|
||||
List<String> command) throws WorldEditException {
|
||||
PrintCommandHelp.help(command, page, we, actor);
|
||||
}
|
||||
}
|
||||
|
@ -17,13 +17,16 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.command;
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.sk89q.worldedit.util.command.parametric.ParameterException;
|
||||
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
|
||||
/**
|
||||
* Thrown when there is a missing parameter.
|
||||
* Key-interface for {@link InjectedValueAccess} for the String arguments.
|
||||
*/
|
||||
public class MissingParameterException extends ParameterException {
|
||||
public interface Arguments {
|
||||
|
||||
String get();
|
||||
|
||||
}
|
@ -17,29 +17,29 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.command.argument;
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.converter.MultiKeyConverter;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
public class BooleanConverter {
|
||||
|
||||
public final class ArgumentUtils {
|
||||
|
||||
private ArgumentUtils() {
|
||||
public static void register(CommandManager commandManager) {
|
||||
commandManager.registerConverter(Key.of(Boolean.class),
|
||||
MultiKeyConverter.builder(
|
||||
ImmutableSetMultimap.<Boolean, String>builder()
|
||||
.putAll(false, "off", "f", "false", "n", "no")
|
||||
.putAll(true, "on", "t", "true", "y", "yes")
|
||||
.build()
|
||||
)
|
||||
.errorMessage(arg -> "Not a boolean value: " + arg)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
public static List<String> getMatchingSuggestions(Collection<String> items, String s) {
|
||||
if (s.isEmpty()) {
|
||||
return Lists.newArrayList(items);
|
||||
}
|
||||
List<String> suggestions = Lists.newArrayList();
|
||||
for (String item : items) {
|
||||
if (item.toLowerCase().startsWith(s)) {
|
||||
suggestions.add(item);
|
||||
}
|
||||
}
|
||||
return suggestions;
|
||||
private BooleanConverter() {
|
||||
}
|
||||
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class BooleanFlag implements CommandExecutor<Boolean> {
|
||||
|
||||
private final String description;
|
||||
|
||||
public BooleanFlag(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import org.enginehub.piston.converter.ArgumentConverter;
|
||||
import org.enginehub.piston.converter.ConversionResult;
|
||||
import org.enginehub.piston.converter.SuccessfulConversion;
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.sk89q.worldedit.util.formatting.text.Component.space;
|
||||
|
||||
public class CommaSeparatedValuesConverter<T> implements ArgumentConverter<T> {
|
||||
|
||||
public static <T> CommaSeparatedValuesConverter<T> wrap(ArgumentConverter<T> delegate) {
|
||||
return wrapAndLimit(delegate, -1);
|
||||
}
|
||||
|
||||
public static <T> CommaSeparatedValuesConverter<T> wrapAndLimit(ArgumentConverter<T> delegate, int maximum) {
|
||||
return new CommaSeparatedValuesConverter<>(delegate, maximum);
|
||||
}
|
||||
|
||||
private static final Splitter COMMA = Splitter.on(',');
|
||||
|
||||
private final ArgumentConverter<T> delegate;
|
||||
private final int maximum;
|
||||
|
||||
private CommaSeparatedValuesConverter(ArgumentConverter<T> delegate, int maximum) {
|
||||
checkArgument(maximum == -1 || maximum > 1,
|
||||
"Maximum must be bigger than 1, or exactly -1");
|
||||
this.delegate = delegate;
|
||||
this.maximum = maximum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component describeAcceptableArguments() {
|
||||
TextComponent.Builder result = TextComponent.builder("");
|
||||
if (maximum > -1) {
|
||||
result.append(TextComponent.of("up to "))
|
||||
.append(Component.of(maximum))
|
||||
.append(space());
|
||||
}
|
||||
result.append(TextComponent.of("comma separated values of: "))
|
||||
.append(delegate.describeAcceptableArguments());
|
||||
return result.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(String input) {
|
||||
String lastInput = Iterables.getLast(COMMA.split(input), "");
|
||||
return delegate.getSuggestions(lastInput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversionResult<T> convert(String argument, InjectedValueAccess context) {
|
||||
ImmutableList.Builder<T> result = ImmutableList.builder();
|
||||
for (String input : COMMA.split(argument)) {
|
||||
ConversionResult<T> temp = delegate.convert(input, context);
|
||||
if (!temp.isSuccessful()) {
|
||||
return temp;
|
||||
}
|
||||
result.addAll(temp.get());
|
||||
}
|
||||
return SuccessfulConversion.from(result.build());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.auto.value.AutoAnnotation;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.sk89q.worldedit.UnknownDirectionException;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
||||
import com.sk89q.worldedit.internal.annotation.MultiDirection;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.converter.ArgumentConverter;
|
||||
import org.enginehub.piston.converter.ConversionResult;
|
||||
import org.enginehub.piston.converter.FailedConversion;
|
||||
import org.enginehub.piston.converter.SuccessfulConversion;
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix;
|
||||
|
||||
public class DirectionConverter implements ArgumentConverter<BlockVector3> {
|
||||
|
||||
@AutoAnnotation
|
||||
private static Direction direction(boolean includeDiagonals) {
|
||||
return new AutoAnnotation_DirectionConverter_direction(includeDiagonals);
|
||||
}
|
||||
|
||||
@AutoAnnotation
|
||||
private static MultiDirection multiDirection(boolean includeDiagonals) {
|
||||
return new AutoAnnotation_DirectionConverter_multiDirection(includeDiagonals);
|
||||
}
|
||||
|
||||
public static void register(WorldEdit worldEdit, CommandManager commandManager) {
|
||||
for (boolean includeDiagonals : new boolean[] { false, true }) {
|
||||
DirectionConverter directionConverter = new DirectionConverter(worldEdit, includeDiagonals);
|
||||
commandManager.registerConverter(
|
||||
Key.of(BlockVector3.class, direction(includeDiagonals)),
|
||||
directionConverter
|
||||
);
|
||||
commandManager.registerConverter(
|
||||
Key.of(BlockVector3.class, multiDirection(includeDiagonals)),
|
||||
CommaSeparatedValuesConverter.wrap(directionConverter)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static final ImmutableSet<String> NON_DIAGONALS = ImmutableSet.of(
|
||||
"north", "south", "east", "west", "up", "down"
|
||||
);
|
||||
private static final ImmutableSet<String> RELATIVE = ImmutableSet.of(
|
||||
"me", "forward", "back", "left", "right"
|
||||
);
|
||||
private static final ImmutableSet<String> DIAGONALS = ImmutableSet.of(
|
||||
"northeast", "northwest", "southeast", "southwest"
|
||||
);
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
private final boolean includeDiagonals;
|
||||
private final ImmutableList<String> suggestions;
|
||||
|
||||
private DirectionConverter(WorldEdit worldEdit, boolean includeDiagonals) {
|
||||
this.worldEdit = worldEdit;
|
||||
this.includeDiagonals = includeDiagonals;
|
||||
suggestions = ImmutableList.<String>builder()
|
||||
.addAll(NON_DIAGONALS)
|
||||
.addAll(RELATIVE)
|
||||
.addAll(includeDiagonals ? DIAGONALS : ImmutableList.of())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversionResult<BlockVector3> convert(String argument, InjectedValueAccess context) {
|
||||
Player player = context.injectedValue(Key.of(Player.class))
|
||||
.orElseThrow(() -> new IllegalStateException("No player available"));
|
||||
try {
|
||||
return SuccessfulConversion.fromSingle(includeDiagonals
|
||||
? worldEdit.getDiagonalDirection(player, argument)
|
||||
: worldEdit.getDirection(player, argument));
|
||||
} catch (UnknownDirectionException e) {
|
||||
return FailedConversion.from(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component describeAcceptableArguments() {
|
||||
return TextComponent.of("`me` to use facing direction, or any "
|
||||
+ (includeDiagonals ? "direction" : "non-diagonal direction"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(String input) {
|
||||
return limitByPrefix(suggestions.stream(), input);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
|
||||
import java.util.concurrent.locks.StampedLock;
|
||||
|
||||
/**
|
||||
* Lazily-created {@link EditSession}.
|
||||
*/
|
||||
public class EditSessionHolder {
|
||||
|
||||
private final StampedLock lock = new StampedLock();
|
||||
private final WorldEdit worldEdit;
|
||||
private final Player player;
|
||||
|
||||
public EditSessionHolder(WorldEdit worldEdit, Player player) {
|
||||
this.worldEdit = worldEdit;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
private EditSession session;
|
||||
|
||||
/**
|
||||
* Get the session, but does not create it if it doesn't exist.
|
||||
*/
|
||||
public EditSession getSession() {
|
||||
long stamp = lock.tryOptimisticRead();
|
||||
EditSession result = session;
|
||||
if (!lock.validate(stamp)) {
|
||||
stamp = lock.readLock();
|
||||
try {
|
||||
result = session;
|
||||
} finally {
|
||||
lock.unlockRead(stamp);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public EditSession getOrCreateSession() {
|
||||
// use the already-generated result if possible
|
||||
EditSession result = getSession();
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
// otherwise, acquire write lock
|
||||
long stamp = lock.writeLock();
|
||||
try {
|
||||
// check session field again -- maybe another writer hit it in between
|
||||
result = session;
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
// now we can do the actual creation
|
||||
LocalSession localSession = worldEdit.getSessionManager().get(player);
|
||||
EditSession editSession = localSession.createEditSession(player);
|
||||
editSession.enableStandardMode();
|
||||
localSession.tellVersion(player);
|
||||
return session = editSession;
|
||||
} finally {
|
||||
lock.unlockWrite(stamp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.sk89q.worldedit.command.util.EntityRemover;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.converter.ArgumentConverter;
|
||||
import org.enginehub.piston.converter.ConversionResult;
|
||||
import org.enginehub.piston.converter.FailedConversion;
|
||||
import org.enginehub.piston.converter.SuccessfulConversion;
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
public class EntityRemoverConverter implements ArgumentConverter<EntityRemover> {
|
||||
|
||||
public static void register(CommandManager commandManager) {
|
||||
commandManager.registerConverter(Key.of(EntityRemover.class), new EntityRemoverConverter());
|
||||
}
|
||||
|
||||
private EntityRemoverConverter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component describeAcceptableArguments() {
|
||||
return TextComponent.of(
|
||||
"projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversionResult<EntityRemover> convert(String argument, InjectedValueAccess context) {
|
||||
try {
|
||||
return SuccessfulConversion.fromSingle(EntityRemover.fromString(argument));
|
||||
} catch (Exception e) {
|
||||
return FailedConversion.from(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.converter.ArgumentConverter;
|
||||
import org.enginehub.piston.converter.MultiKeyConverter;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class EnumConverter {
|
||||
|
||||
public static void register(CommandManager commandManager) {
|
||||
commandManager.registerConverter(Key.of(SelectorChoice.class),
|
||||
basic(SelectorChoice.class, SelectorChoice.UNKNOWN));
|
||||
commandManager.registerConverter(Key.of(TreeGenerator.TreeType.class),
|
||||
full(TreeGenerator.TreeType.class,
|
||||
t -> ImmutableSet.copyOf(t.lookupKeys),
|
||||
null));
|
||||
commandManager.registerConverter(Key.of(EditSession.ReorderMode.class),
|
||||
full(EditSession.ReorderMode.class,
|
||||
r -> ImmutableSet.of(r.getDisplayName()),
|
||||
null));
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>> ArgumentConverter<E> basic(Class<E> enumClass) {
|
||||
return full(enumClass, e -> ImmutableSet.of(e.name()), null);
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>> ArgumentConverter<E> basic(Class<E> enumClass, E unknownValue) {
|
||||
return full(enumClass, e -> ImmutableSet.of(e.name()), unknownValue);
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>> ArgumentConverter<E> full(Class<E> enumClass,
|
||||
Function<E, Set<String>> lookupKeys,
|
||||
@Nullable E unknownValue) {
|
||||
return MultiKeyConverter.from(
|
||||
EnumSet.allOf(enumClass),
|
||||
lookupKeys,
|
||||
unknownValue
|
||||
);
|
||||
}
|
||||
|
||||
private EnumConverter() {
|
||||
}
|
||||
|
||||
}
|
@ -17,27 +17,35 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.command.parametric;
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
/**
|
||||
* Thrown if there is an error with a parameter.
|
||||
*/
|
||||
public class ParameterException extends Exception {
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public ParameterException() {
|
||||
super();
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public final class ExpandAmount {
|
||||
|
||||
public static ExpandAmount vert() {
|
||||
return new ExpandAmount(null);
|
||||
}
|
||||
|
||||
public ParameterException(String message) {
|
||||
super(message);
|
||||
public static ExpandAmount from(int amount) {
|
||||
return new ExpandAmount(amount);
|
||||
}
|
||||
|
||||
public ParameterException(Throwable cause) {
|
||||
super(cause);
|
||||
@Nullable
|
||||
private final Integer amount;
|
||||
|
||||
private ExpandAmount(@Nullable Integer amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public ParameterException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
public boolean isVert() {
|
||||
return amount == null;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return checkNotNull(amount, "This amount is vertical, i.e. undefined");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.converter.ArgumentConverter;
|
||||
import org.enginehub.piston.converter.ArgumentConverters;
|
||||
import org.enginehub.piston.converter.ConversionResult;
|
||||
import org.enginehub.piston.converter.SuccessfulConversion;
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix;
|
||||
|
||||
public class ExpandAmountConverter implements ArgumentConverter<ExpandAmount> {
|
||||
|
||||
public static void register(CommandManager commandManager) {
|
||||
commandManager.registerConverter(Key.of(ExpandAmount.class), new ExpandAmountConverter());
|
||||
}
|
||||
|
||||
private final ArgumentConverter<Integer> integerConverter =
|
||||
ArgumentConverters.get(TypeToken.of(int.class));
|
||||
|
||||
private ExpandAmountConverter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component describeAcceptableArguments() {
|
||||
return TextComponent.of("`vert` or " + integerConverter.describeAcceptableArguments());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(String input) {
|
||||
return limitByPrefix(Stream.concat(
|
||||
Stream.of("vert"), integerConverter.getSuggestions(input).stream()
|
||||
), input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversionResult<ExpandAmount> convert(String argument, InjectedValueAccess context) {
|
||||
if (argument.equalsIgnoreCase("vert")
|
||||
|| argument.equalsIgnoreCase("vertical")) {
|
||||
return SuccessfulConversion.fromSingle(ExpandAmount.vert());
|
||||
}
|
||||
return integerConverter.convert(argument, context).mapSingle(ExpandAmount::from);
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.converter.ArgumentConverter;
|
||||
import org.enginehub.piston.converter.ConversionResult;
|
||||
import org.enginehub.piston.converter.FailedConversion;
|
||||
import org.enginehub.piston.converter.SuccessfulConversion;
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FactoryConverter<T> implements ArgumentConverter<T> {
|
||||
|
||||
public static void register(WorldEdit worldEdit, CommandManager commandManager) {
|
||||
commandManager.registerConverter(Key.of(Pattern.class),
|
||||
new FactoryConverter<>(worldEdit, WorldEdit::getPatternFactory, "pattern"));
|
||||
commandManager.registerConverter(Key.of(Mask.class),
|
||||
new FactoryConverter<>(worldEdit, WorldEdit::getMaskFactory, "mask"));
|
||||
commandManager.registerConverter(Key.of(BaseItem.class),
|
||||
new FactoryConverter<>(worldEdit, WorldEdit::getItemFactory, "item"));
|
||||
}
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
private final Function<WorldEdit, AbstractFactory<T>> factoryExtractor;
|
||||
private final String description;
|
||||
|
||||
private FactoryConverter(WorldEdit worldEdit,
|
||||
Function<WorldEdit, AbstractFactory<T>> factoryExtractor,
|
||||
String description) {
|
||||
this.worldEdit = worldEdit;
|
||||
this.factoryExtractor = factoryExtractor;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversionResult<T> convert(String argument, InjectedValueAccess context) {
|
||||
Actor actor = context.injectedValue(Key.of(Actor.class))
|
||||
.orElseThrow(() -> new IllegalStateException("No actor"));
|
||||
LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor);
|
||||
|
||||
ParserContext parserContext = new ParserContext();
|
||||
parserContext.setActor(actor);
|
||||
if (actor instanceof Entity) {
|
||||
Extent extent = ((Entity) actor).getExtent();
|
||||
if (extent instanceof World) {
|
||||
parserContext.setWorld((World) extent);
|
||||
}
|
||||
}
|
||||
parserContext.setSession(session);
|
||||
|
||||
try {
|
||||
return SuccessfulConversion.fromSingle(
|
||||
factoryExtractor.apply(worldEdit).parseFromInput(argument, parserContext)
|
||||
);
|
||||
} catch (InputParseException e) {
|
||||
return FailedConversion.from(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component describeAcceptableArguments() {
|
||||
return TextComponent.of("any " + description);
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
public class ItemParser extends SimpleCommand<BaseItem> {
|
||||
|
||||
private final StringParser stringParser;
|
||||
|
||||
public ItemParser(String name) {
|
||||
stringParser = addParameter(new StringParser(name, "The item name", null));
|
||||
}
|
||||
|
||||
public ItemParser(String name, String defaultSuggestion) {
|
||||
stringParser = addParameter(new StringParser(name, "The item name", defaultSuggestion));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseItem call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
String itemString = stringParser.call(args, locals);
|
||||
|
||||
Actor actor = locals.get(Actor.class);
|
||||
LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor);
|
||||
|
||||
ParserContext parserContext = new ParserContext();
|
||||
parserContext.setActor(actor);
|
||||
if (actor instanceof Entity) {
|
||||
Extent extent = ((Entity) actor).getExtent();
|
||||
if (extent instanceof World) {
|
||||
parserContext.setWorld((World) extent);
|
||||
}
|
||||
}
|
||||
parserContext.setSession(session);
|
||||
|
||||
try {
|
||||
return WorldEdit.getInstance().getItemFactory().parseFromInput(itemString, parserContext);
|
||||
} catch (InputParseException e) {
|
||||
throw new CommandException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Match an item";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean testPermission0(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.EditContext;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
public class ItemUseParser extends SimpleCommand<Contextual<RegionFunction>> {
|
||||
|
||||
private final ItemParser itemParser = addParameter(new ItemParser("item", "minecraft:bone_meal"));
|
||||
|
||||
@Override
|
||||
public Contextual<RegionFunction> call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
BaseItem item = itemParser.call(args, locals);
|
||||
return new ItemUseFactory(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Applies an item";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean testPermission0(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final class ItemUseFactory implements Contextual<RegionFunction> {
|
||||
private final BaseItem item;
|
||||
|
||||
private ItemUseFactory(BaseItem item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionFunction createFromContext(EditContext input) {
|
||||
World world = ((EditSession) input.getDestination()).getWorld();
|
||||
return new ItemUseFunction(world, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "application of the item " + item.getType() + ":" + item.getNbtData();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ItemUseFunction implements RegionFunction {
|
||||
private final World world;
|
||||
private final BaseItem item;
|
||||
|
||||
private ItemUseFunction(World world, BaseItem item) {
|
||||
this.world = world;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(BlockVector3 position) throws WorldEditException {
|
||||
return world.useItem(position, item, Direction.UP);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
|
||||
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class NumberParser implements CommandExecutor<Number> {
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final String defaultSuggestion;
|
||||
|
||||
public NumberParser(String name, String description) {
|
||||
this(name, description, null);
|
||||
}
|
||||
|
||||
public NumberParser(String name, String description, String defaultSuggestion) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.defaultSuggestion = defaultSuggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
try {
|
||||
String next = args.next();
|
||||
try {
|
||||
return Double.parseDouble(next);
|
||||
} catch (NumberFormatException ignored) {
|
||||
throw new CommandException("The value for <" + name + "> should be a number. '" + next + "' is not a number.");
|
||||
}
|
||||
} catch (MissingArgumentException e) {
|
||||
throw new CommandException("Missing value for <" + name + "> (try a number).");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
|
||||
String value = args.next();
|
||||
return value.isEmpty() && defaultSuggestion != null ? Lists.newArrayList(defaultSuggestion) : Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "<" + name + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
public class PatternParser extends SimpleCommand<Pattern> {
|
||||
|
||||
private final StringParser stringParser;
|
||||
|
||||
public PatternParser(String name) {
|
||||
stringParser = addParameter(new StringParser(name, "The pattern"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
String patternString = stringParser.call(args, locals);
|
||||
|
||||
Actor actor = locals.get(Actor.class);
|
||||
LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor);
|
||||
|
||||
ParserContext parserContext = new ParserContext();
|
||||
parserContext.setActor(actor);
|
||||
if (actor instanceof Entity) {
|
||||
Extent extent = ((Entity) actor).getExtent();
|
||||
if (extent instanceof World) {
|
||||
parserContext.setWorld((World) extent);
|
||||
}
|
||||
}
|
||||
parserContext.setSession(session);
|
||||
|
||||
try {
|
||||
return WorldEdit.getInstance().getPatternFactory().parseFromInput(patternString, parserContext);
|
||||
} catch (InputParseException e) {
|
||||
throw new CommandException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Choose a pattern";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission0(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.sk89q.worldedit.regions.factory.CuboidRegionFactory;
|
||||
import com.sk89q.worldedit.regions.factory.CylinderRegionFactory;
|
||||
import com.sk89q.worldedit.regions.factory.RegionFactory;
|
||||
import com.sk89q.worldedit.regions.factory.SphereRegionFactory;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.converter.MultiKeyConverter;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
public class RegionFactoryConverter {
|
||||
|
||||
public static void register(CommandManager commandManager) {
|
||||
commandManager.registerConverter(Key.of(RegionFactory.class),
|
||||
MultiKeyConverter.builder(
|
||||
ImmutableSetMultimap.<RegionFactory, String>builder()
|
||||
.put(new CuboidRegionFactory(), "cuboid")
|
||||
.put(new SphereRegionFactory(), "sphere")
|
||||
.putAll(new CylinderRegionFactory(1), "cyl", "cylinder")
|
||||
.build()
|
||||
)
|
||||
.errorMessage(arg -> "Not a known region type: " + arg)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
private RegionFactoryConverter() {
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.regions.factory.CuboidRegionFactory;
|
||||
import com.sk89q.worldedit.regions.factory.CylinderRegionFactory;
|
||||
import com.sk89q.worldedit.regions.factory.RegionFactory;
|
||||
import com.sk89q.worldedit.regions.factory.SphereRegionFactory;
|
||||
import com.sk89q.worldedit.util.command.argument.ArgumentUtils;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
|
||||
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RegionFactoryParser implements CommandExecutor<RegionFactory> {
|
||||
|
||||
@Override
|
||||
public RegionFactory call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
try {
|
||||
String type = args.next();
|
||||
|
||||
switch (type) {
|
||||
case "cuboid":
|
||||
return new CuboidRegionFactory();
|
||||
case "sphere":
|
||||
return new SphereRegionFactory();
|
||||
case "cyl":
|
||||
case "cylinder":
|
||||
return new CylinderRegionFactory(1); // TODO: Adjustable height
|
||||
|
||||
default:
|
||||
throw new CommandException("Unknown shape type: " + type + " (try one of " + getUsage() + ")");
|
||||
}
|
||||
} catch (MissingArgumentException e) {
|
||||
throw new CommandException("Missing shape type (try one of " + getUsage() + ")");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
|
||||
return ArgumentUtils.getMatchingSuggestions(Lists.newArrayList("cuboid", "sphere", "cyl"), args.next());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "(cuboid | sphere | cyl)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Defines a region";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.sk89q.worldedit.registry.Registry;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BlockCategory;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.entity.EntityType;
|
||||
import com.sk89q.worldedit.world.fluid.FluidCategory;
|
||||
import com.sk89q.worldedit.world.fluid.FluidType;
|
||||
import com.sk89q.worldedit.world.gamemode.GameMode;
|
||||
import com.sk89q.worldedit.world.item.ItemCategory;
|
||||
import com.sk89q.worldedit.world.item.ItemType;
|
||||
import com.sk89q.worldedit.world.weather.WeatherType;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.converter.ArgumentConverter;
|
||||
import org.enginehub.piston.converter.ConversionResult;
|
||||
import org.enginehub.piston.converter.FailedConversion;
|
||||
import org.enginehub.piston.converter.SuccessfulConversion;
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix;
|
||||
|
||||
public class RegistryConverter<V> implements ArgumentConverter<V> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void register(CommandManager commandManager) {
|
||||
ImmutableList.of(
|
||||
BlockType.class,
|
||||
BlockCategory.class,
|
||||
ItemType.class,
|
||||
ItemCategory.class,
|
||||
BiomeType.class,
|
||||
EntityType.class,
|
||||
FluidType.class,
|
||||
FluidCategory.class,
|
||||
GameMode.class,
|
||||
WeatherType.class
|
||||
).stream()
|
||||
.map(c -> (Class<Object>) c)
|
||||
.forEach(registryType ->
|
||||
commandManager.registerConverter(Key.of(registryType), from(registryType))
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <V> RegistryConverter<V> from(Class<V> registryType) {
|
||||
try {
|
||||
Field registryField = registryType.getDeclaredField("REGISTRY");
|
||||
Registry<V> registry = (Registry<V>) registryField.get(null);
|
||||
return new RegistryConverter<>(registryType, registry);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new IllegalArgumentException("Not a registry-backed type: " + registryType.getName());
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("Registry field inaccessible on " + registryType.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private final Registry<V> registry;
|
||||
private final TextComponent choices;
|
||||
|
||||
private RegistryConverter(Class<V> clazz, Registry<V> registry) {
|
||||
this.registry = registry;
|
||||
this.choices = TextComponent.of("any " + registry.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component describeAcceptableArguments() {
|
||||
return this.choices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversionResult<V> convert(String argument, InjectedValueAccess injectedValueAccess) {
|
||||
V result = registry.get(argument);
|
||||
return result == null
|
||||
? FailedConversion.from(new IllegalArgumentException(
|
||||
"Not a valid " + registry.getName() + ": " + argument))
|
||||
: SuccessfulConversion.fromSingle(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(String input) {
|
||||
return limitByPrefix(registry.keySet().stream(), input);
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import static com.sk89q.worldedit.util.GuavaUtil.firstNonNull;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.extent.NullExtent;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.EditContext;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.block.BlockReplace;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
|
||||
|
||||
|
||||
public class ReplaceParser extends SimpleCommand<Contextual<? extends RegionFunction>> {
|
||||
|
||||
private final PatternParser fillArg = addParameter(new PatternParser("fillPattern"));
|
||||
|
||||
@Override
|
||||
public Contextual<RegionFunction> call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
Pattern fill = fillArg.call(args, locals);
|
||||
return new ReplaceFactory(fill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Replaces blocks";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean testPermission0(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class ReplaceFactory implements Contextual<RegionFunction> {
|
||||
private final Pattern fill;
|
||||
|
||||
private ReplaceFactory(Pattern fill) {
|
||||
this.fill = fill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionFunction createFromContext(EditContext context) {
|
||||
return new BlockReplace(
|
||||
firstNonNull(context.getDestination(), new NullExtent()),
|
||||
firstNonNull(context.getFill(), fill));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "replace blocks";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -17,23 +17,17 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.command.argument;
|
||||
|
||||
public class ArgumentParseException extends ArgumentException {
|
||||
|
||||
public ArgumentParseException() {
|
||||
}
|
||||
|
||||
public ArgumentParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ArgumentParseException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ArgumentParseException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
public enum SelectorChoice {
|
||||
CUBOID,
|
||||
EXTEND,
|
||||
POLY,
|
||||
ELLIPSOID,
|
||||
SPHERE,
|
||||
CYL,
|
||||
CONVEX,
|
||||
HULL,
|
||||
POLYHEDRON,
|
||||
UNKNOWN
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
|
||||
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class StringParser implements CommandExecutor<String> {
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final String defaultSuggestion;
|
||||
|
||||
public StringParser(String name, String description) {
|
||||
this(name, description, null);
|
||||
}
|
||||
|
||||
public StringParser(String name, String description, String defaultSuggestion) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.defaultSuggestion = defaultSuggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
try {
|
||||
return args.next();
|
||||
} catch (MissingArgumentException e) {
|
||||
throw new CommandException("Missing value for <" + name + ">.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
|
||||
String value = args.next();
|
||||
return value.isEmpty() && defaultSuggestion != null ? Lists.newArrayList(defaultSuggestion) : Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "<" + name + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.EditContext;
|
||||
import com.sk89q.worldedit.function.generator.ForestGenerator;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||
import com.sk89q.worldedit.util.command.argument.ArgumentUtils;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.argument.MissingArgumentException;
|
||||
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class TreeGeneratorParser implements CommandExecutor<Contextual<ForestGenerator>> {
|
||||
|
||||
private final String name;
|
||||
|
||||
public TreeGeneratorParser(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private String getOptionsList() {
|
||||
return Joiner.on(" | ").join(Arrays.asList(TreeType.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Contextual<ForestGenerator> call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
try {
|
||||
String input = args.next();
|
||||
TreeType type = TreeGenerator.lookup(input);
|
||||
if (type != null) {
|
||||
return new GeneratorFactory(type);
|
||||
} else {
|
||||
throw new CommandException("Unknown value for <" + name + "> (try one of " + getOptionsList() + ").");
|
||||
}
|
||||
} catch (MissingArgumentException e) {
|
||||
throw new CommandException("Missing value for <" + name + "> (try one of " + getOptionsList() + ").");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException {
|
||||
String s = args.next();
|
||||
return s.isEmpty() ? Lists.newArrayList(TreeType.getPrimaryAliases()) : ArgumentUtils.getMatchingSuggestions(TreeType.getAliases(), s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "<" + name + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Choose a tree generator";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final class GeneratorFactory implements Contextual<ForestGenerator> {
|
||||
private final TreeType type;
|
||||
|
||||
private GeneratorFactory(TreeType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForestGenerator createFromContext(EditContext input) {
|
||||
return new ForestGenerator((EditSession) input.getDestination(), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "tree of type " + type;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector2;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.converter.ArgumentConverter;
|
||||
import org.enginehub.piston.converter.ArgumentConverters;
|
||||
import org.enginehub.piston.converter.ConversionResult;
|
||||
import org.enginehub.piston.converter.FailedConversion;
|
||||
import org.enginehub.piston.converter.SuccessfulConversion;
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class VectorConverter<C, T> implements ArgumentConverter<T> {
|
||||
public static void register(CommandManager commandManager) {
|
||||
CommaSeparatedValuesConverter<Integer> intConverter = CommaSeparatedValuesConverter.wrap(ArgumentConverters.get(TypeToken.of(int.class)));
|
||||
CommaSeparatedValuesConverter<Double> doubleConverter = CommaSeparatedValuesConverter.wrap(ArgumentConverters.get(TypeToken.of(double.class)));
|
||||
commandManager.registerConverter(Key.of(BlockVector2.class),
|
||||
new VectorConverter<>(
|
||||
intConverter,
|
||||
2,
|
||||
cmps -> BlockVector2.at(cmps.get(0), cmps.get(1)),
|
||||
"block vector with x and z"
|
||||
));
|
||||
commandManager.registerConverter(Key.of(Vector2.class),
|
||||
new VectorConverter<>(
|
||||
doubleConverter,
|
||||
2,
|
||||
cmps -> Vector2.at(cmps.get(0), cmps.get(1)),
|
||||
"vector with x and z"
|
||||
));
|
||||
commandManager.registerConverter(Key.of(BlockVector3.class),
|
||||
new VectorConverter<>(
|
||||
intConverter,
|
||||
3,
|
||||
cmps -> BlockVector3.at(cmps.get(0), cmps.get(1), cmps.get(2)),
|
||||
"block vector with x, y, and z"
|
||||
));
|
||||
commandManager.registerConverter(Key.of(Vector3.class),
|
||||
new VectorConverter<>(
|
||||
doubleConverter,
|
||||
3,
|
||||
cmps -> Vector3.at(cmps.get(0), cmps.get(1), cmps.get(2)),
|
||||
"vector with x, y, and z"
|
||||
));
|
||||
}
|
||||
|
||||
private final ArgumentConverter<C> componentConverter;
|
||||
private final int componentCount;
|
||||
private final Function<List<C>, T> vectorConstructor;
|
||||
private final String acceptableArguments;
|
||||
|
||||
|
||||
private VectorConverter(ArgumentConverter<C> componentConverter,
|
||||
int componentCount,
|
||||
Function<List<C>, T> vectorConstructor,
|
||||
String acceptableArguments) {
|
||||
this.componentConverter = componentConverter;
|
||||
this.componentCount = componentCount;
|
||||
this.vectorConstructor = vectorConstructor;
|
||||
this.acceptableArguments = acceptableArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component describeAcceptableArguments() {
|
||||
return TextComponent.of("any " + acceptableArguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversionResult<T> convert(String argument, InjectedValueAccess context) {
|
||||
ConversionResult<C> components = componentConverter.convert(argument, context);
|
||||
if (!components.isSuccessful()) {
|
||||
return components.failureAsAny();
|
||||
}
|
||||
if (components.get().size() != componentCount) {
|
||||
return FailedConversion.from(new IllegalArgumentException(
|
||||
"Must have exactly " + componentCount + " vector components"));
|
||||
}
|
||||
T vector = vectorConstructor.apply(ImmutableList.copyOf(components.get()));
|
||||
return SuccessfulConversion.fromSingle(vector);
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.converter.ArgumentConverter;
|
||||
import org.enginehub.piston.converter.ConversionResult;
|
||||
import org.enginehub.piston.converter.FailedConversion;
|
||||
import org.enginehub.piston.converter.SuccessfulConversion;
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class ZonedDateTimeConverter implements ArgumentConverter<ZonedDateTime> {
|
||||
|
||||
public static void register(CommandManager commandManager) {
|
||||
commandManager.registerConverter(Key.of(ZonedDateTime.class), new ZonedDateTimeConverter());
|
||||
}
|
||||
|
||||
private ZonedDateTimeConverter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component describeAcceptableArguments() {
|
||||
return TextComponent.of("any date");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversionResult<ZonedDateTime> convert(String argument, InjectedValueAccess context) {
|
||||
LocalSession session = context.injectedValue(Key.of(LocalSession.class))
|
||||
.orElseThrow(() -> new IllegalStateException("Need a local session"));
|
||||
Calendar date = session.detectDate(argument);
|
||||
if (date == null) {
|
||||
return FailedConversion.from(new IllegalArgumentException("Not a date: " + argument));
|
||||
}
|
||||
return SuccessfulConversion.fromSingle(date.toInstant().atZone(ZoneOffset.UTC));
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@org.enginehub.piston.util.NonnullByDefault
|
||||
package com.sk89q.worldedit.command.argument;
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.composition;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.command.argument.RegionFunctionParser;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.factory.Apply;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
|
||||
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
|
||||
|
||||
public class ApplyCommand extends SimpleCommand<Contextual<? extends Operation>> {
|
||||
|
||||
private final CommandExecutor<Contextual<? extends RegionFunction>> functionParser;
|
||||
private final String description;
|
||||
|
||||
public ApplyCommand() {
|
||||
this(new RegionFunctionParser(), "Applies a function to every block");
|
||||
}
|
||||
|
||||
public ApplyCommand(CommandExecutor<Contextual<? extends RegionFunction>> functionParser, String description) {
|
||||
checkNotNull(functionParser, "functionParser");
|
||||
checkNotNull(description, "description");
|
||||
this.functionParser = functionParser;
|
||||
this.description = description;
|
||||
addParameter(functionParser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Apply call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
Contextual<? extends RegionFunction> function = functionParser.call(args, locals);
|
||||
return new Apply(function);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean testPermission0(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.composition;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.minecraft.util.commands.WrappedCommandException;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.argument.BooleanFlag;
|
||||
import com.sk89q.worldedit.command.argument.StringParser;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.factory.Deform;
|
||||
import com.sk89q.worldedit.function.factory.Deform.Mode;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.composition.FlagParser.Flag;
|
||||
import com.sk89q.worldedit.util.command.composition.FlagParser.FlagData;
|
||||
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
|
||||
|
||||
public class DeformCommand extends SimpleCommand<Contextual<? extends Operation>> {
|
||||
|
||||
private final Flag<Boolean> rawCoordsFlag = addFlag('r', new BooleanFlag("Raw coords mode"));
|
||||
private final Flag<Boolean> offsetFlag = addFlag('o', new BooleanFlag("Offset mode"));
|
||||
private final StringParser expressionParser = addParameter(new StringParser("expression", "Expression to apply", "y-=0.2"));
|
||||
|
||||
@Override
|
||||
public Deform call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
FlagData flagData = getFlagParser().call(args, locals);
|
||||
String expression = expressionParser.call(args, locals);
|
||||
boolean rawCoords = rawCoordsFlag.get(flagData, false);
|
||||
boolean offset = offsetFlag.get(flagData, false);
|
||||
|
||||
Deform deform = new Deform(expression);
|
||||
|
||||
if (rawCoords) {
|
||||
deform.setMode(Mode.RAW_COORD);
|
||||
} else if (offset) {
|
||||
deform.setMode(Mode.OFFSET);
|
||||
Player player = (Player) locals.get(Actor.class);
|
||||
LocalSession session = WorldEdit.getInstance().getSessionManager().get(locals.get(Actor.class));
|
||||
try {
|
||||
deform.setOffset(session.getPlacementPosition(player).toVector3());
|
||||
} catch (IncompleteRegionException e) {
|
||||
throw new WrappedCommandException(e);
|
||||
}
|
||||
} else {
|
||||
deform.setMode(Mode.UNIT_CUBE);
|
||||
}
|
||||
|
||||
return deform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Apply math expression to area";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean testPermission0(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.composition;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.command.argument.NumberParser;
|
||||
import com.sk89q.worldedit.command.argument.RegionFunctionParser;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.factory.Paint;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
|
||||
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
|
||||
|
||||
public class PaintCommand extends SimpleCommand<Paint> {
|
||||
|
||||
private final NumberParser densityCommand = addParameter(new NumberParser("density", "0-100", "20"));
|
||||
private final CommandExecutor<? extends Contextual<? extends RegionFunction>> functionParser;
|
||||
|
||||
public PaintCommand() {
|
||||
this(new RegionFunctionParser());
|
||||
}
|
||||
|
||||
public PaintCommand(CommandExecutor<? extends Contextual<? extends RegionFunction>> functionParser) {
|
||||
this.functionParser = functionParser;
|
||||
addParameter(functionParser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paint call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
double density = densityCommand.call(args, locals).doubleValue() / 100.0;
|
||||
Contextual<? extends RegionFunction> function = functionParser.call(args, locals);
|
||||
return new Paint(function, density);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Applies a function to surfaces";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean testPermission0(CommandLocals locals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.composition;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.EditContext;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
|
||||
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SelectionCommand extends SimpleCommand<Operation> {
|
||||
|
||||
private final CommandExecutor<Contextual<? extends Operation>> delegate;
|
||||
private final String permission;
|
||||
|
||||
public SelectionCommand(CommandExecutor<Contextual<? extends Operation>> delegate, String permission) {
|
||||
checkNotNull(delegate, "delegate");
|
||||
checkNotNull(permission, "permission");
|
||||
this.delegate = delegate;
|
||||
this.permission = permission;
|
||||
addParameter(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operation call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
if (!testPermission(locals)) {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
|
||||
Contextual<? extends Operation> operationFactory = delegate.call(args, locals);
|
||||
|
||||
Actor actor = locals.get(Actor.class);
|
||||
if (actor instanceof Player) {
|
||||
try {
|
||||
Player player = (Player) actor;
|
||||
LocalSession session = WorldEdit.getInstance().getSessionManager().get(player);
|
||||
Region selection = session.getSelection(player.getWorld());
|
||||
|
||||
EditSession editSession = session.createEditSession(player);
|
||||
editSession.enableStandardMode();
|
||||
locals.put(EditSession.class, editSession);
|
||||
session.tellVersion(player);
|
||||
|
||||
EditContext editContext = new EditContext();
|
||||
editContext.setDestination(locals.get(EditSession.class));
|
||||
editContext.setRegion(selection);
|
||||
editContext.setSession(session);
|
||||
|
||||
Operation operation = operationFactory.createFromContext(editContext);
|
||||
Operations.completeBlindly(operation);
|
||||
|
||||
List<String> messages = Lists.newArrayList();
|
||||
operation.addStatusMessages(messages);
|
||||
if (messages.isEmpty()) {
|
||||
actor.print("Operation completed.");
|
||||
} else {
|
||||
actor.print("Operation completed (" + Joiner.on(", ").join(messages) + ").");
|
||||
}
|
||||
|
||||
return operation;
|
||||
} catch (IncompleteRegionException e) {
|
||||
WorldEdit.getInstance().getPlatformManager().getCommandManager().getExceptionConverter().convert(e);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
throw new CommandException("This command can only be used by players.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return delegate.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean testPermission0(CommandLocals locals) {
|
||||
return locals.get(Actor.class).hasPermission(permission);
|
||||
}
|
||||
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.composition;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.MaxBrushRadiusException;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.argument.NumberParser;
|
||||
import com.sk89q.worldedit.command.argument.RegionFactoryParser;
|
||||
import com.sk89q.worldedit.command.tool.BrushTool;
|
||||
import com.sk89q.worldedit.command.tool.InvalidToolBindException;
|
||||
import com.sk89q.worldedit.command.tool.brush.OperationFactoryBrush;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.regions.factory.RegionFactory;
|
||||
import com.sk89q.worldedit.util.HandSide;
|
||||
import com.sk89q.worldedit.util.command.argument.CommandArgs;
|
||||
import com.sk89q.worldedit.util.command.composition.CommandExecutor;
|
||||
import com.sk89q.worldedit.util.command.composition.SimpleCommand;
|
||||
|
||||
public class ShapedBrushCommand extends SimpleCommand<Object> {
|
||||
|
||||
private final CommandExecutor<? extends Contextual<? extends Operation>> delegate;
|
||||
private final String permission;
|
||||
|
||||
private final RegionFactoryParser regionFactoryParser = addParameter(new RegionFactoryParser());
|
||||
private final NumberParser radiusCommand = addParameter(new NumberParser("size", "The size of the brush", "5"));
|
||||
|
||||
public ShapedBrushCommand(CommandExecutor<? extends Contextual<? extends Operation>> delegate, String permission) {
|
||||
checkNotNull(delegate, "delegate");
|
||||
this.permission = permission;
|
||||
this.delegate = delegate;
|
||||
addParameter(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(CommandArgs args, CommandLocals locals) throws CommandException {
|
||||
if (!testPermission(locals)) {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
|
||||
RegionFactory regionFactory = regionFactoryParser.call(args, locals);
|
||||
int radius = radiusCommand.call(args, locals).intValue();
|
||||
Contextual<? extends Operation> factory = delegate.call(args, locals);
|
||||
|
||||
Player player = (Player) locals.get(Actor.class);
|
||||
LocalSession session = WorldEdit.getInstance().getSessionManager().get(player);
|
||||
|
||||
try {
|
||||
WorldEdit.getInstance().checkMaxBrushRadius(radius);
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
|
||||
tool.setSize(radius);
|
||||
tool.setFill(null);
|
||||
tool.setBrush(new OperationFactoryBrush(factory, regionFactory, session), permission);
|
||||
} catch (MaxBrushRadiusException | InvalidToolBindException e) {
|
||||
WorldEdit.getInstance().getPlatformManager().getCommandManager().getExceptionConverter().convert(e);
|
||||
}
|
||||
|
||||
player.print("Set brush to " + factory);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return delegate.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission0(CommandLocals locals) {
|
||||
Actor sender = locals.get(Actor.class);
|
||||
if (sender == null) {
|
||||
throw new RuntimeException("Uh oh! No 'Actor' specified so that we can check permissions");
|
||||
} else {
|
||||
return sender.hasPermission(permission);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.factory;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.function.ItemUseFunction;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.EditContext;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
public final class ItemUseFactory implements Contextual<RegionFunction> {
|
||||
private final BaseItem item;
|
||||
|
||||
public ItemUseFactory(BaseItem item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionFunction createFromContext(EditContext input) {
|
||||
World world = ((EditSession) input.getDestination()).getWorld();
|
||||
return new ItemUseFunction(world, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "application of the item " + item.getType() + ":" + item.getNbtData();
|
||||
}
|
||||
}
|
@ -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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.factory;
|
||||
|
||||
import com.sk89q.worldedit.extent.NullExtent;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.EditContext;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.block.BlockReplace;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
|
||||
import static com.sk89q.worldedit.util.GuavaUtil.firstNonNull;
|
||||
|
||||
public class ReplaceFactory implements Contextual<RegionFunction> {
|
||||
private final Pattern fill;
|
||||
|
||||
public ReplaceFactory(Pattern fill) {
|
||||
this.fill = fill;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionFunction createFromContext(EditContext context) {
|
||||
return new BlockReplace(
|
||||
firstNonNull(context.getDestination(), new NullExtent()),
|
||||
firstNonNull(context.getFill(), fill));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "replace blocks";
|
||||
}
|
||||
}
|
@ -17,22 +17,28 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.command;
|
||||
package com.sk89q.worldedit.command.factory;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.function.EditContext;
|
||||
import com.sk89q.worldedit.function.generator.ForestGenerator;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
public final class TreeGeneratorFactory implements Contextual<ForestGenerator> {
|
||||
private final TreeGenerator.TreeType type;
|
||||
|
||||
/**
|
||||
* Always returns an empty list of suggestions.
|
||||
*/
|
||||
public class NullCompleter implements CommandCompleter {
|
||||
public TreeGeneratorFactory(TreeGenerator.TreeType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
|
||||
return Collections.emptyList();
|
||||
public ForestGenerator createFromContext(EditContext input) {
|
||||
return new ForestGenerator((EditSession) input.getDestination(), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "tree of type " + type;
|
||||
}
|
||||
}
|
@ -24,12 +24,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.util.command.parametric.ExceptionConverter;
|
||||
import com.sk89q.worldedit.internal.command.exception.ExceptionConverter;
|
||||
import com.sk89q.worldedit.util.task.FutureForwardingTask;
|
||||
import com.sk89q.worldedit.util.task.Supervisor;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
|
||||
public class AsyncCommandHelper {
|
||||
|
||||
@ -85,7 +86,8 @@ public class AsyncCommandHelper {
|
||||
.exceptionConverter(exceptionConverter)
|
||||
.onSuccess(format(success))
|
||||
.onFailure(format(failure))
|
||||
.build());
|
||||
.build(),
|
||||
ForkJoinPool.commonPool());
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -96,7 +98,8 @@ public class AsyncCommandHelper {
|
||||
new MessageFutureCallback.Builder(sender)
|
||||
.exceptionConverter(exceptionConverter)
|
||||
.onFailure(format(failure))
|
||||
.build());
|
||||
.build(),
|
||||
ForkJoinPool.commonPool());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -17,28 +17,23 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.command.binding;
|
||||
package com.sk89q.worldedit.command.util;
|
||||
|
||||
import org.enginehub.piston.annotation.CommandCondition;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicates a command flag, such as {@code /command -f}.
|
||||
*
|
||||
* <p>If used on a boolean type, then the flag will be a non-value flag. If
|
||||
* used on any other type, then the flag will be a value flag.</p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.PARAMETER)
|
||||
public @interface Switch {
|
||||
@CommandCondition(CommandPermissionsConditionGenerator.class)
|
||||
public @interface CommandPermissions {
|
||||
|
||||
/**
|
||||
* The flag character.
|
||||
* A list of permissions. Only one permission has to be met
|
||||
* for the command to be permitted.
|
||||
*
|
||||
* @return the flag character (A-Z a-z 0-9 is acceptable)
|
||||
* @return a list of permissions strings
|
||||
*/
|
||||
char value();
|
||||
String[] value();
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.util;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.enginehub.piston.Command;
|
||||
import org.enginehub.piston.gen.CommandConditionGenerator;
|
||||
import org.enginehub.piston.gen.CommandRegistration;
|
||||
import org.enginehub.piston.util.NonnullByDefault;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@NonnullByDefault
|
||||
public final class CommandPermissionsConditionGenerator implements CommandConditionGenerator {
|
||||
|
||||
public interface Registration {
|
||||
Registration commandPermissionsConditionGenerator(CommandPermissionsConditionGenerator generator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Command.Condition generateCondition(Method commandMethod) {
|
||||
CommandPermissions annotation = commandMethod.getAnnotation(CommandPermissions.class);
|
||||
checkNotNull(annotation, "Annotation is missing from commandMethod");
|
||||
Set<String> permissions = ImmutableSet.copyOf(annotation.value());
|
||||
return new PermissionCondition(permissions);
|
||||
}
|
||||
}
|
@ -19,7 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.command.util;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityProperties;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.function.EntityFunction;
|
||||
@ -29,7 +28,7 @@ import com.sk89q.worldedit.function.EntityFunction;
|
||||
*/
|
||||
public class CreatureButcher {
|
||||
|
||||
final class Flags {
|
||||
public final class Flags {
|
||||
@SuppressWarnings("PointlessBitwiseExpression")
|
||||
public static final int PETS = 1 << 0;
|
||||
public static final int NPCS = 1 << 1;
|
||||
@ -39,7 +38,6 @@ public class CreatureButcher {
|
||||
public static final int TAGGED = 1 << 5;
|
||||
public static final int FRIENDLY = PETS | NPCS | ANIMALS | GOLEMS | AMBIENT | TAGGED;
|
||||
public static final int ARMOR_STAND = 1 << 6;
|
||||
public static final int WITH_LIGHTNING = 1 << 20;
|
||||
|
||||
private Flags() {
|
||||
}
|
||||
@ -64,19 +62,6 @@ public class CreatureButcher {
|
||||
}
|
||||
}
|
||||
|
||||
public void fromCommand(CommandContext args) {
|
||||
or(Flags.FRIENDLY , args.hasFlag('f')); // No permission check here. Flags will instead be filtered by the subsequent calls.
|
||||
or(Flags.PETS , args.hasFlag('p'), "worldedit.butcher.pets");
|
||||
or(Flags.NPCS , args.hasFlag('n'), "worldedit.butcher.npcs");
|
||||
or(Flags.GOLEMS , args.hasFlag('g'), "worldedit.butcher.golems");
|
||||
or(Flags.ANIMALS , args.hasFlag('a'), "worldedit.butcher.animals");
|
||||
or(Flags.AMBIENT , args.hasFlag('b'), "worldedit.butcher.ambient");
|
||||
or(Flags.TAGGED , args.hasFlag('t'), "worldedit.butcher.tagged");
|
||||
or(Flags.ARMOR_STAND , args.hasFlag('r'), "worldedit.butcher.armorstands");
|
||||
|
||||
or(Flags.WITH_LIGHTNING, args.hasFlag('l'), "worldedit.butcher.lightning");
|
||||
}
|
||||
|
||||
public EntityFunction createFunction() {
|
||||
return entity -> {
|
||||
boolean killPets = (flags & Flags.PETS) != 0;
|
||||
|
@ -19,15 +19,13 @@
|
||||
|
||||
package com.sk89q.worldedit.command.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityProperties;
|
||||
import com.sk89q.worldedit.function.EntityFunction;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* The implementation of /remove.
|
||||
@ -125,17 +123,21 @@ public class EntityRemover {
|
||||
}
|
||||
}
|
||||
|
||||
private Type type;
|
||||
|
||||
public void fromString(String str) throws CommandException {
|
||||
public static EntityRemover fromString(String str) {
|
||||
Type type = Type.findByPattern(str);
|
||||
if (type != null) {
|
||||
this.type = type;
|
||||
return new EntityRemover(type);
|
||||
} else {
|
||||
throw new CommandException("Acceptable types: projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all");
|
||||
throw new IllegalArgumentException("Acceptable types: projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all");
|
||||
}
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
|
||||
private EntityRemover(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public EntityFunction createFunction() {
|
||||
final Type type = this.type;
|
||||
checkNotNull(type, "type can't be null");
|
||||
|
@ -20,7 +20,7 @@
|
||||
//$Id$
|
||||
|
||||
|
||||
package com.sk89q.minecraft.util.commands;
|
||||
package com.sk89q.worldedit.command.util;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
@ -22,9 +22,9 @@ package com.sk89q.worldedit.command.util;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.util.command.parametric.ExceptionConverter;
|
||||
import com.sk89q.worldedit.internal.command.exception.ExceptionConverter;
|
||||
import org.enginehub.piston.exception.CommandException;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.util;
|
||||
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import org.enginehub.piston.Command;
|
||||
import org.enginehub.piston.CommandParameters;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public final class PermissionCondition implements Command.Condition {
|
||||
|
||||
private static final Key<Actor> ACTOR_KEY = Key.of(Actor.class);
|
||||
|
||||
private final Set<String> permissions;
|
||||
|
||||
public PermissionCondition(Set<String> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public Set<String> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean satisfied(CommandParameters parameters) {
|
||||
return parameters.injectedValue(ACTOR_KEY)
|
||||
.map(actor -> permissions.stream().anyMatch(actor::hasPermission))
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.util;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandListBox;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
|
||||
import com.sk89q.worldedit.util.formatting.component.InvalidComponentException;
|
||||
import org.enginehub.piston.Command;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.sk89q.worldedit.internal.command.CommandUtil.byCleanName;
|
||||
import static com.sk89q.worldedit.internal.command.CommandUtil.getSubCommands;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* Implementation of the //help command.
|
||||
*/
|
||||
// Stored in a separate class to prevent import conflicts, and because it's aliased via /we help.
|
||||
public class PrintCommandHelp {
|
||||
|
||||
private static Command detectCommand(CommandManager manager, String command) {
|
||||
Optional<Command> mapping;
|
||||
|
||||
// First try the command as entered
|
||||
mapping = manager.getCommand(command);
|
||||
if (mapping.isPresent()) {
|
||||
return mapping.get();
|
||||
}
|
||||
|
||||
// If tried with slashes, try dropping a slash
|
||||
if (command.startsWith("/")) {
|
||||
mapping = manager.getCommand(command.substring(1));
|
||||
return mapping.orElse(null);
|
||||
}
|
||||
|
||||
// Otherwise, check /command, since that's common
|
||||
mapping = manager.getCommand("/" + command);
|
||||
return mapping.orElse(null);
|
||||
}
|
||||
|
||||
public static void help(List<String> commandPath, int page, WorldEdit we, Actor actor) throws InvalidComponentException {
|
||||
CommandManager manager = we.getPlatformManager().getPlatformCommandManager().getCommandManager();
|
||||
|
||||
if (commandPath.isEmpty()) {
|
||||
printCommands(page, manager.getAllCommands(), actor, ImmutableList.of());
|
||||
return;
|
||||
}
|
||||
|
||||
List<Command> visited = new ArrayList<>();
|
||||
Command currentCommand = detectCommand(manager, commandPath.get(0));
|
||||
if (currentCommand == null) {
|
||||
actor.printError(String.format("The command '%s' could not be found.", commandPath.get(0)));
|
||||
return;
|
||||
}
|
||||
visited.add(currentCommand);
|
||||
|
||||
// Drill down to the command
|
||||
for (int i = 1; i < commandPath.size(); i++) {
|
||||
String subCommand = commandPath.get(i);
|
||||
Map<String, Command> subCommands = getSubCommands(currentCommand);
|
||||
|
||||
if (subCommands.isEmpty()) {
|
||||
actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)",
|
||||
Joiner.on(" ").join(visited.stream().map(Command::getName).iterator()), subCommand));
|
||||
// full help for single command
|
||||
CommandUsageBox box = new CommandUsageBox(visited, visited.stream()
|
||||
.map(Command::getName).collect(Collectors.joining(" ")));
|
||||
actor.print(box.create());
|
||||
return;
|
||||
}
|
||||
|
||||
if (subCommands.containsKey(subCommand)) {
|
||||
currentCommand = subCommands.get(subCommand);
|
||||
visited.add(currentCommand);
|
||||
} else {
|
||||
actor.printError(String.format("The sub-command '%s' under '%s' could not be found.",
|
||||
subCommand, Joiner.on(" ").join(visited.stream().map(Command::getName).iterator())));
|
||||
// list subcommands for currentCommand
|
||||
CommandUsageBox box = new CommandUsageBox(visited, visited.stream()
|
||||
.map(Command::getName).collect(Collectors.joining(" ")));
|
||||
actor.print(box.create());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Command> subCommands = getSubCommands(currentCommand);
|
||||
|
||||
if (subCommands.isEmpty()) {
|
||||
// Create the message
|
||||
CommandUsageBox box = new CommandUsageBox(visited, visited.stream()
|
||||
.map(Command::getName).collect(Collectors.joining(" ")));
|
||||
actor.print(box.create());
|
||||
} else {
|
||||
printCommands(page, subCommands.values().stream(), actor, visited);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printCommands(int page, Stream<Command> commandStream, Actor actor,
|
||||
List<Command> commandList) throws InvalidComponentException {
|
||||
// Get a list of aliases
|
||||
List<Command> commands = commandStream
|
||||
.sorted(byCleanName())
|
||||
.collect(toList());
|
||||
|
||||
String used = commandList.isEmpty() ? null
|
||||
: Joiner.on(" ").join(commandList.stream().map(Command::getName).iterator());
|
||||
CommandListBox box = new CommandListBox(
|
||||
(used == null ? "Help" : "Subcommands: " + used),
|
||||
"//help %page%" + (used == null ? "" : " " + used));
|
||||
if (!actor.isPlayer()) {
|
||||
box.formatForConsole();
|
||||
}
|
||||
|
||||
for (Command mapping : commands) {
|
||||
String alias = (commandList.isEmpty() ? "/" : "") + mapping.getName();
|
||||
String command = Stream.concat(commandList.stream(), Stream.of(mapping))
|
||||
.map(Command::getName)
|
||||
.collect(Collectors.joining(" ", "/", ""));
|
||||
box.appendCommand(alias, mapping.getDescription(), command);
|
||||
}
|
||||
|
||||
actor.print(box.create(page));
|
||||
}
|
||||
|
||||
private PrintCommandHelp() {
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.session.SessionOwner;
|
||||
import com.sk89q.worldedit.util.Identifiable;
|
||||
import com.sk89q.worldedit.util.auth.Subject;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@ -77,11 +77,11 @@ public interface Actor extends Identifiable, SessionOwner, Subject {
|
||||
void printError(String msg);
|
||||
|
||||
/**
|
||||
* Print a {@link TextComponent}.
|
||||
* Print a {@link Component}.
|
||||
*
|
||||
* @param component The component to print
|
||||
*/
|
||||
void print(TextComponent component);
|
||||
void print(Component component);
|
||||
|
||||
/**
|
||||
* Returns true if the actor can destroy bedrock.
|
||||
|
@ -17,20 +17,22 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.command.parametric;
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.sk89q.worldedit.util.command.SimpleDescription;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import com.google.auto.value.AutoAnnotation;
|
||||
import com.sk89q.worldedit.internal.annotation.Radii;
|
||||
|
||||
/**
|
||||
* An abstract listener.
|
||||
* Holder for generated annotation classes.
|
||||
*/
|
||||
public abstract class AbstractInvokeListener implements InvokeListener {
|
||||
class Annotations {
|
||||
|
||||
@Override
|
||||
public void updateDescription(Object object, Method method,
|
||||
ParameterData[] parameters, SimpleDescription description) {
|
||||
@AutoAnnotation
|
||||
static Radii radii(int value) {
|
||||
return new AutoAnnotation_Annotations_radii(value);
|
||||
}
|
||||
|
||||
private Annotations() {
|
||||
}
|
||||
|
||||
}
|
@ -50,12 +50,12 @@ public enum Capability {
|
||||
USER_COMMANDS {
|
||||
@Override
|
||||
void initialize(PlatformManager platformManager, Platform platform) {
|
||||
platformManager.getCommandManager().register(platform);
|
||||
platformManager.getPlatformCommandManager().registerCommandsWith(platform);
|
||||
}
|
||||
|
||||
@Override
|
||||
void unload(PlatformManager platformManager, Platform platform) {
|
||||
platformManager.getCommandManager().unregister();
|
||||
platformManager.getPlatformCommandManager().removeCommands();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1,378 +0,0 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldedit.util.command.composition.LegacyCommandAdapter.adapt;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||
import com.sk89q.minecraft.util.commands.WrappedCommandException;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.BiomeCommands;
|
||||
import com.sk89q.worldedit.command.BrushCommands;
|
||||
import com.sk89q.worldedit.command.ChunkCommands;
|
||||
import com.sk89q.worldedit.command.ClipboardCommands;
|
||||
import com.sk89q.worldedit.command.GeneralCommands;
|
||||
import com.sk89q.worldedit.command.GenerationCommands;
|
||||
import com.sk89q.worldedit.command.HistoryCommands;
|
||||
import com.sk89q.worldedit.command.NavigationCommands;
|
||||
import com.sk89q.worldedit.command.RegionCommands;
|
||||
import com.sk89q.worldedit.command.SchematicCommands;
|
||||
import com.sk89q.worldedit.command.ScriptingCommands;
|
||||
import com.sk89q.worldedit.command.SelectionCommands;
|
||||
import com.sk89q.worldedit.command.SnapshotCommands;
|
||||
import com.sk89q.worldedit.command.SnapshotUtilCommands;
|
||||
import com.sk89q.worldedit.command.SuperPickaxeCommands;
|
||||
import com.sk89q.worldedit.command.ToolCommands;
|
||||
import com.sk89q.worldedit.command.ToolUtilCommands;
|
||||
import com.sk89q.worldedit.command.UtilityCommands;
|
||||
import com.sk89q.worldedit.command.WorldEditCommands;
|
||||
import com.sk89q.worldedit.command.argument.ReplaceParser;
|
||||
import com.sk89q.worldedit.command.argument.TreeGeneratorParser;
|
||||
import com.sk89q.worldedit.command.composition.ApplyCommand;
|
||||
import com.sk89q.worldedit.command.composition.DeformCommand;
|
||||
import com.sk89q.worldedit.command.composition.PaintCommand;
|
||||
import com.sk89q.worldedit.command.composition.SelectionCommand;
|
||||
import com.sk89q.worldedit.command.composition.ShapedBrushCommand;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.event.platform.CommandEvent;
|
||||
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.factory.Deform;
|
||||
import com.sk89q.worldedit.function.factory.Deform.Mode;
|
||||
import com.sk89q.worldedit.internal.command.ActorAuthorizer;
|
||||
import com.sk89q.worldedit.internal.command.CommandLoggingHandler;
|
||||
import com.sk89q.worldedit.internal.command.UserCommandCompleter;
|
||||
import com.sk89q.worldedit.internal.command.WorldEditBinding;
|
||||
import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter;
|
||||
import com.sk89q.worldedit.session.request.Request;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import com.sk89q.worldedit.util.command.InvalidUsageException;
|
||||
import com.sk89q.worldedit.util.command.composition.ProvidedValue;
|
||||
import com.sk89q.worldedit.util.command.fluent.CommandGraph;
|
||||
import com.sk89q.worldedit.util.command.parametric.ExceptionConverter;
|
||||
import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler;
|
||||
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
|
||||
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
|
||||
import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
|
||||
import com.sk89q.worldedit.util.logging.LogFormat;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Handles the registration and invocation of commands.
|
||||
*
|
||||
* <p>This class is primarily for internal usage.</p>
|
||||
*/
|
||||
public final class CommandManager {
|
||||
|
||||
public static final Pattern COMMAND_CLEAN_PATTERN = Pattern.compile("^[/]+");
|
||||
private static final Logger log = LoggerFactory.getLogger(CommandManager.class);
|
||||
private static final java.util.logging.Logger commandLog =
|
||||
java.util.logging.Logger.getLogger(CommandManager.class.getCanonicalName() + ".CommandLog");
|
||||
private static final Pattern numberFormatExceptionPattern = Pattern.compile("^For input string: \"(.*)\"$");
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
private final PlatformManager platformManager;
|
||||
private final Dispatcher dispatcher;
|
||||
private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler();
|
||||
private final ExceptionConverter exceptionConverter;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit the WorldEdit instance
|
||||
*/
|
||||
CommandManager(final WorldEdit worldEdit, PlatformManager platformManager) {
|
||||
checkNotNull(worldEdit);
|
||||
checkNotNull(platformManager);
|
||||
this.worldEdit = worldEdit;
|
||||
this.platformManager = platformManager;
|
||||
this.exceptionConverter = new WorldEditExceptionConverter(worldEdit);
|
||||
|
||||
// Register this instance for command events
|
||||
worldEdit.getEventBus().register(this);
|
||||
|
||||
// Setup the logger
|
||||
commandLog.addHandler(dynamicHandler);
|
||||
|
||||
// Set up the commands manager
|
||||
ParametricBuilder builder = new ParametricBuilder();
|
||||
builder.setAuthorizer(new ActorAuthorizer());
|
||||
builder.setDefaultCompleter(new UserCommandCompleter(platformManager));
|
||||
builder.addBinding(new WorldEditBinding(worldEdit));
|
||||
builder.addInvokeListener(new LegacyCommandsHandler());
|
||||
builder.addInvokeListener(new CommandLoggingHandler(worldEdit, commandLog));
|
||||
|
||||
dispatcher = new CommandGraph()
|
||||
.builder(builder)
|
||||
.commands()
|
||||
.registerMethods(new BiomeCommands(worldEdit))
|
||||
.registerMethods(new ChunkCommands(worldEdit))
|
||||
.registerMethods(new ClipboardCommands(worldEdit))
|
||||
.registerMethods(new GeneralCommands(worldEdit))
|
||||
.registerMethods(new GenerationCommands(worldEdit))
|
||||
.registerMethods(new HistoryCommands(worldEdit))
|
||||
.registerMethods(new NavigationCommands(worldEdit))
|
||||
.registerMethods(new RegionCommands(worldEdit))
|
||||
.registerMethods(new ScriptingCommands(worldEdit))
|
||||
.registerMethods(new SelectionCommands(worldEdit))
|
||||
.registerMethods(new SnapshotUtilCommands(worldEdit))
|
||||
.registerMethods(new ToolUtilCommands(worldEdit))
|
||||
.registerMethods(new ToolCommands(worldEdit))
|
||||
.registerMethods(new UtilityCommands(worldEdit))
|
||||
.register(adapt(new SelectionCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within selection"), "worldedit.region.set")), "/set")
|
||||
.group("worldedit", "we")
|
||||
.describeAs("WorldEdit commands")
|
||||
.registerMethods(new WorldEditCommands(worldEdit))
|
||||
.parent()
|
||||
.group("schematic", "schem", "/schematic", "/schem")
|
||||
.describeAs("Schematic commands for saving/loading areas")
|
||||
.registerMethods(new SchematicCommands(worldEdit))
|
||||
.parent()
|
||||
.group("snapshot", "snap")
|
||||
.describeAs("Schematic commands for saving/loading areas")
|
||||
.registerMethods(new SnapshotCommands(worldEdit))
|
||||
.parent()
|
||||
.group("brush", "br")
|
||||
.describeAs("Brushing commands")
|
||||
.registerMethods(new BrushCommands(worldEdit))
|
||||
.register(adapt(new ShapedBrushCommand(new DeformCommand(), "worldedit.brush.deform")), "deform")
|
||||
.register(adapt(new ShapedBrushCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within region"), "worldedit.brush.set")), "set")
|
||||
.register(adapt(new ShapedBrushCommand(new PaintCommand(), "worldedit.brush.paint")), "paint")
|
||||
.register(adapt(new ShapedBrushCommand(new ApplyCommand(), "worldedit.brush.apply")), "apply")
|
||||
.register(adapt(new ShapedBrushCommand(new PaintCommand(new TreeGeneratorParser("treeType")), "worldedit.brush.forest")), "forest")
|
||||
.register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y-=1", Mode.RAW_COORD), "Raise one block"), "worldedit.brush.raise")), "raise")
|
||||
.register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y+=1", Mode.RAW_COORD), "Lower one block"), "worldedit.brush.lower")), "lower")
|
||||
.parent()
|
||||
.group("superpickaxe", "pickaxe", "sp")
|
||||
.describeAs("Super-pickaxe commands")
|
||||
.registerMethods(new SuperPickaxeCommands(worldEdit))
|
||||
.parent()
|
||||
.group("tool")
|
||||
.describeAs("Bind functions to held items")
|
||||
.registerMethods(new ToolCommands(worldEdit))
|
||||
.parent()
|
||||
.graph()
|
||||
.getDispatcher();
|
||||
}
|
||||
|
||||
public ExceptionConverter getExceptionConverter() {
|
||||
return exceptionConverter;
|
||||
}
|
||||
|
||||
void register(Platform platform) {
|
||||
log.info("Registering commands with " + platform.getClass().getCanonicalName());
|
||||
|
||||
LocalConfiguration config = platform.getConfiguration();
|
||||
boolean logging = config.logCommands;
|
||||
String path = config.logFile;
|
||||
|
||||
// Register log
|
||||
if (!logging || path.isEmpty()) {
|
||||
dynamicHandler.setHandler(null);
|
||||
commandLog.setLevel(Level.OFF);
|
||||
} else {
|
||||
File file = new File(config.getWorkingDirectory(), path);
|
||||
commandLog.setLevel(Level.ALL);
|
||||
|
||||
log.info("Logging WorldEdit commands to " + file.getAbsolutePath());
|
||||
|
||||
try {
|
||||
dynamicHandler.setHandler(new FileHandler(file.getAbsolutePath(), true));
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not use command log file " + path + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
dynamicHandler.setFormatter(new LogFormat(config.logFormat));
|
||||
}
|
||||
|
||||
platform.registerCommands(dispatcher);
|
||||
}
|
||||
|
||||
void unregister() {
|
||||
dynamicHandler.setHandler(null);
|
||||
}
|
||||
|
||||
public String[] commandDetection(String[] split) {
|
||||
// Quick script shortcut
|
||||
if (split[0].matches("^[^/].*\\.js$")) {
|
||||
String[] newSplit = new String[split.length + 1];
|
||||
System.arraycopy(split, 0, newSplit, 1, split.length);
|
||||
newSplit[0] = "cs";
|
||||
newSplit[1] = newSplit[1];
|
||||
split = newSplit;
|
||||
}
|
||||
|
||||
String searchCmd = split[0].toLowerCase();
|
||||
|
||||
// Try to detect the command
|
||||
if (!dispatcher.contains(searchCmd)) {
|
||||
if (worldEdit.getConfiguration().noDoubleSlash && dispatcher.contains("/" + searchCmd)) {
|
||||
split[0] = "/" + split[0];
|
||||
} else if (searchCmd.length() >= 2 && searchCmd.charAt(0) == '/' && dispatcher.contains(searchCmd.substring(1))) {
|
||||
split[0] = split[0].substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
return split;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleCommand(CommandEvent event) {
|
||||
Request.reset();
|
||||
|
||||
Actor actor = platformManager.createProxyActor(event.getActor());
|
||||
String[] split = commandDetection(event.getArguments().split(" "));
|
||||
|
||||
// No command found!
|
||||
if (!dispatcher.contains(split[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
LocalSession session = worldEdit.getSessionManager().get(actor);
|
||||
Request.request().setSession(session);
|
||||
if (actor instanceof Entity) {
|
||||
Extent extent = ((Entity) actor).getExtent();
|
||||
if (extent instanceof World) {
|
||||
Request.request().setWorld(((World) extent));
|
||||
}
|
||||
}
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
CommandLocals locals = new CommandLocals();
|
||||
locals.put(Actor.class, actor);
|
||||
locals.put("arguments", event.getArguments());
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
// This is a bit of a hack, since the call method can only throw CommandExceptions
|
||||
// everything needs to be wrapped at least once. Which means to handle all WorldEdit
|
||||
// exceptions without writing a hook into every dispatcher, we need to unwrap these
|
||||
// exceptions and rethrow their converted form, if their is one.
|
||||
try {
|
||||
dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]);
|
||||
} catch (Throwable t) {
|
||||
// Use the exception converter to convert the exception if any of its causes
|
||||
// can be converted, otherwise throw the original exception
|
||||
Throwable next = t;
|
||||
do {
|
||||
exceptionConverter.convert(next);
|
||||
next = next.getCause();
|
||||
} while (next != null);
|
||||
|
||||
throw t;
|
||||
}
|
||||
} catch (CommandPermissionsException e) {
|
||||
actor.printError("You are not permitted to do that. Are you in the right mode?");
|
||||
} catch (InvalidUsageException e) {
|
||||
if (e.isFullHelpSuggested()) {
|
||||
actor.print(new CommandUsageBox(e.getCommand(), e.getCommandUsed("/", ""), locals).create());
|
||||
String message = e.getMessage();
|
||||
if (message != null) {
|
||||
actor.printError(message);
|
||||
}
|
||||
} else {
|
||||
String message = e.getMessage();
|
||||
actor.printError(message != null ? message : "The command was not used properly (no more help available).");
|
||||
actor.printError("Usage: " + e.getSimpleUsageString("/"));
|
||||
}
|
||||
} catch (WrappedCommandException e) {
|
||||
Throwable t = e.getCause();
|
||||
actor.printError("Please report this error: [See console]");
|
||||
actor.printRaw(t.getClass().getName() + ": " + t.getMessage());
|
||||
log.error("An unexpected error while handling a WorldEdit command", t);
|
||||
} catch (CommandException e) {
|
||||
String message = e.getMessage();
|
||||
if (message != null) {
|
||||
actor.printError(e.getMessage());
|
||||
} else {
|
||||
actor.printError("An unknown error has occurred! Please see console.");
|
||||
log.error("An unknown error occurred", e);
|
||||
}
|
||||
} finally {
|
||||
EditSession editSession = locals.get(EditSession.class);
|
||||
|
||||
if (editSession != null) {
|
||||
session.remember(editSession);
|
||||
editSession.flushSession();
|
||||
|
||||
if (config.profile) {
|
||||
long time = System.currentTimeMillis() - start;
|
||||
int changed = editSession.getBlockChangeCount();
|
||||
if (time > 0) {
|
||||
double throughput = changed / (time / 1000.0);
|
||||
actor.printDebug((time / 1000.0) + "s elapsed (history: "
|
||||
+ changed + " changed; "
|
||||
+ Math.round(throughput) + " blocks/sec).");
|
||||
} else {
|
||||
actor.printDebug((time / 1000.0) + "s elapsed.");
|
||||
}
|
||||
}
|
||||
|
||||
worldEdit.flushBlockBag(actor, editSession);
|
||||
}
|
||||
Request.reset();
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleCommandSuggestion(CommandSuggestionEvent event) {
|
||||
try {
|
||||
CommandLocals locals = new CommandLocals();
|
||||
locals.put(Actor.class, event.getActor());
|
||||
locals.put("arguments", event.getArguments());
|
||||
event.setSuggestions(dispatcher.getSuggestions(event.getArguments(), locals));
|
||||
} catch (CommandException e) {
|
||||
event.getActor().printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command dispatcher instance.
|
||||
*
|
||||
* @return the command dispatcher
|
||||
*/
|
||||
public Dispatcher getDispatcher() {
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
public static java.util.logging.Logger getLogger() {
|
||||
return commandLog;
|
||||
}
|
||||
|
||||
}
|
@ -21,14 +21,13 @@ package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.registry.Registries;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a platform that WorldEdit has been implemented for.
|
||||
@ -104,11 +103,11 @@ public interface Platform {
|
||||
@Nullable World matchWorld(World world);
|
||||
|
||||
/**
|
||||
* Register the commands contained within the given command dispatcher.
|
||||
* Register the commands contained within the given command manager.
|
||||
*
|
||||
* @param dispatcher the dispatcher
|
||||
* @param commandManager the command manager
|
||||
*/
|
||||
void registerCommands(Dispatcher dispatcher);
|
||||
void registerCommands(CommandManager commandManager);
|
||||
|
||||
/**
|
||||
* Register game hooks.
|
||||
|
@ -0,0 +1,591 @@
|
||||
/*
|
||||
* 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 Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.ApplyBrushCommands;
|
||||
import com.sk89q.worldedit.command.BiomeCommands;
|
||||
import com.sk89q.worldedit.command.BiomeCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.BrushCommands;
|
||||
import com.sk89q.worldedit.command.BrushCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.ChunkCommands;
|
||||
import com.sk89q.worldedit.command.ChunkCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.ClipboardCommands;
|
||||
import com.sk89q.worldedit.command.ClipboardCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.GeneralCommands;
|
||||
import com.sk89q.worldedit.command.GeneralCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.GenerationCommands;
|
||||
import com.sk89q.worldedit.command.GenerationCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.HistoryCommands;
|
||||
import com.sk89q.worldedit.command.HistoryCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.NavigationCommands;
|
||||
import com.sk89q.worldedit.command.NavigationCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.PaintBrushCommands;
|
||||
import com.sk89q.worldedit.command.RegionCommands;
|
||||
import com.sk89q.worldedit.command.RegionCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.SchematicCommands;
|
||||
import com.sk89q.worldedit.command.SchematicCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.ScriptingCommands;
|
||||
import com.sk89q.worldedit.command.ScriptingCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.SelectionCommands;
|
||||
import com.sk89q.worldedit.command.SelectionCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.SnapshotCommands;
|
||||
import com.sk89q.worldedit.command.SnapshotCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.SnapshotUtilCommands;
|
||||
import com.sk89q.worldedit.command.SnapshotUtilCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.SuperPickaxeCommands;
|
||||
import com.sk89q.worldedit.command.SuperPickaxeCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.ToolCommands;
|
||||
import com.sk89q.worldedit.command.ToolCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.ToolUtilCommands;
|
||||
import com.sk89q.worldedit.command.ToolUtilCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.UtilityCommands;
|
||||
import com.sk89q.worldedit.command.UtilityCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.WorldEditCommands;
|
||||
import com.sk89q.worldedit.command.WorldEditCommandsRegistration;
|
||||
import com.sk89q.worldedit.command.argument.Arguments;
|
||||
import com.sk89q.worldedit.command.argument.BooleanConverter;
|
||||
import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter;
|
||||
import com.sk89q.worldedit.command.argument.DirectionConverter;
|
||||
import com.sk89q.worldedit.command.argument.EntityRemoverConverter;
|
||||
import com.sk89q.worldedit.command.argument.EnumConverter;
|
||||
import com.sk89q.worldedit.command.argument.ExpandAmountConverter;
|
||||
import com.sk89q.worldedit.command.argument.FactoryConverter;
|
||||
import com.sk89q.worldedit.command.argument.RegionFactoryConverter;
|
||||
import com.sk89q.worldedit.command.argument.RegistryConverter;
|
||||
import com.sk89q.worldedit.command.argument.VectorConverter;
|
||||
import com.sk89q.worldedit.command.argument.ZonedDateTimeConverter;
|
||||
import com.sk89q.worldedit.command.util.PermissionCondition;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.event.platform.CommandEvent;
|
||||
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.internal.annotation.Selection;
|
||||
import com.sk89q.worldedit.internal.command.CommandLoggingHandler;
|
||||
import com.sk89q.worldedit.internal.command.exception.WorldEditExceptionConverter;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.session.request.Request;
|
||||
import com.sk89q.worldedit.internal.command.CommandArgParser;
|
||||
import com.sk89q.worldedit.internal.command.CommandRegistrationHandler;
|
||||
import com.sk89q.worldedit.internal.command.exception.ExceptionConverter;
|
||||
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
|
||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||
import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
|
||||
import com.sk89q.worldedit.util.logging.LogFormat;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import org.enginehub.piston.ColorConfig;
|
||||
import org.enginehub.piston.Command;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
import org.enginehub.piston.DefaultCommandManagerService;
|
||||
import org.enginehub.piston.converter.ArgumentConverters;
|
||||
import org.enginehub.piston.exception.CommandException;
|
||||
import org.enginehub.piston.exception.CommandExecutionException;
|
||||
import org.enginehub.piston.exception.ConditionFailedException;
|
||||
import org.enginehub.piston.exception.UsageException;
|
||||
import org.enginehub.piston.gen.CommandRegistration;
|
||||
import org.enginehub.piston.inject.InjectedValueStore;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
import org.enginehub.piston.inject.MapBackedValueStore;
|
||||
import org.enginehub.piston.inject.MemoizingValueAccess;
|
||||
import org.enginehub.piston.inject.MergedValueAccess;
|
||||
import org.enginehub.piston.part.SubCommandPart;
|
||||
import org.enginehub.piston.util.HelpGenerator;
|
||||
import org.enginehub.piston.util.ValueProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Handles the registration and invocation of commands.
|
||||
*
|
||||
* <p>This class is primarily for internal usage.</p>
|
||||
*/
|
||||
public final class PlatformCommandManager {
|
||||
|
||||
public static final Pattern COMMAND_CLEAN_PATTERN = Pattern.compile("^[/]+");
|
||||
private static final Logger log = LoggerFactory.getLogger(PlatformCommandManager.class);
|
||||
private static final java.util.logging.Logger COMMAND_LOG =
|
||||
java.util.logging.Logger.getLogger("com.sk89q.worldedit.CommandLog");
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
private final PlatformManager platformManager;
|
||||
private final CommandManager commandManager;
|
||||
private final InjectedValueStore globalInjectedValues;
|
||||
private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler();
|
||||
private final WorldEditExceptionConverter exceptionConverter;
|
||||
private final CommandRegistrationHandler registration;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit the WorldEdit instance
|
||||
*/
|
||||
PlatformCommandManager(final WorldEdit worldEdit, PlatformManager platformManager) {
|
||||
checkNotNull(worldEdit);
|
||||
checkNotNull(platformManager);
|
||||
this.worldEdit = worldEdit;
|
||||
this.platformManager = platformManager;
|
||||
this.exceptionConverter = new WorldEditExceptionConverter(worldEdit);
|
||||
this.commandManager = DefaultCommandManagerService.getInstance()
|
||||
.newCommandManager();
|
||||
this.globalInjectedValues = MapBackedValueStore.create();
|
||||
this.registration = new CommandRegistrationHandler(
|
||||
ImmutableList.of(
|
||||
new CommandLoggingHandler(worldEdit, COMMAND_LOG)
|
||||
));
|
||||
// setup separate from main constructor
|
||||
// ensures that everything is definitely assigned
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
// Register this instance for command events
|
||||
worldEdit.getEventBus().register(this);
|
||||
|
||||
// Setup the logger
|
||||
COMMAND_LOG.addHandler(dynamicHandler);
|
||||
|
||||
// Set up the commands manager
|
||||
registerAlwaysInjectedValues();
|
||||
registerArgumentConverters();
|
||||
registerAllCommands();
|
||||
}
|
||||
|
||||
private void registerArgumentConverters() {
|
||||
DirectionConverter.register(worldEdit, commandManager);
|
||||
FactoryConverter.register(worldEdit, commandManager);
|
||||
for (int count = 2; count <= 3; count++) {
|
||||
commandManager.registerConverter(Key.of(double.class, Annotations.radii(count)),
|
||||
CommaSeparatedValuesConverter.wrapAndLimit(ArgumentConverters.get(
|
||||
TypeToken.of(double.class)
|
||||
), count)
|
||||
);
|
||||
}
|
||||
VectorConverter.register(commandManager);
|
||||
EnumConverter.register(commandManager);
|
||||
RegistryConverter.register(commandManager);
|
||||
ExpandAmountConverter.register(commandManager);
|
||||
ZonedDateTimeConverter.register(commandManager);
|
||||
BooleanConverter.register(commandManager);
|
||||
EntityRemoverConverter.register(commandManager);
|
||||
RegionFactoryConverter.register(commandManager);
|
||||
}
|
||||
|
||||
private void registerAlwaysInjectedValues() {
|
||||
globalInjectedValues.injectValue(Key.of(Region.class, Selection.class),
|
||||
context -> {
|
||||
LocalSession localSession = context.injectedValue(Key.of(LocalSession.class))
|
||||
.orElseThrow(() -> new IllegalStateException("No LocalSession"));
|
||||
return context.injectedValue(Key.of(Player.class))
|
||||
.map(player -> {
|
||||
try {
|
||||
return localSession.getSelection(player.getWorld());
|
||||
} catch (IncompleteRegionException e) {
|
||||
exceptionConverter.convert(e);
|
||||
throw new AssertionError("Should have thrown a new exception.");
|
||||
}
|
||||
});
|
||||
});
|
||||
globalInjectedValues.injectValue(Key.of(EditSession.class),
|
||||
context -> {
|
||||
LocalSession localSession = context.injectedValue(Key.of(LocalSession.class))
|
||||
.orElseThrow(() -> new IllegalStateException("No LocalSession"));
|
||||
return context.injectedValue(Key.of(Player.class))
|
||||
.map(player -> {
|
||||
EditSession editSession = localSession.createEditSession(player);
|
||||
editSession.enableStandardMode();
|
||||
return editSession;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private <CI> void registerSubCommands(String name, List<String> aliases, String desc,
|
||||
CommandRegistration<CI> registration, CI instance) {
|
||||
registerSubCommands(name, aliases, desc, registration, instance, m -> {});
|
||||
}
|
||||
|
||||
private <CI> void registerSubCommands(String name, List<String> aliases, String desc,
|
||||
CommandRegistration<CI> registration, CI instance,
|
||||
Consumer<CommandManager> additionalConfig) {
|
||||
commandManager.register(name, cmd -> {
|
||||
cmd.aliases(aliases);
|
||||
cmd.description(TextComponent.of(desc));
|
||||
cmd.action(Command.Action.NULL_ACTION);
|
||||
|
||||
CommandManager manager = DefaultCommandManagerService.getInstance()
|
||||
.newCommandManager();
|
||||
this.registration.register(
|
||||
manager,
|
||||
registration,
|
||||
instance
|
||||
);
|
||||
additionalConfig.accept(manager);
|
||||
|
||||
cmd.addPart(SubCommandPart.builder(TranslatableComponent.of("worldedit.argument.action"),
|
||||
TextComponent.of("Sub-command to run."))
|
||||
.withCommands(manager.getAllCommands().collect(Collectors.toList()))
|
||||
.required()
|
||||
.build());
|
||||
});
|
||||
}
|
||||
|
||||
private void registerAllCommands() {
|
||||
registerSubCommands(
|
||||
"schematic",
|
||||
ImmutableList.of("schem", "/schematic", "/schem"),
|
||||
"Schematic commands for saving/loading areas",
|
||||
SchematicCommandsRegistration.builder(),
|
||||
new SchematicCommands(worldEdit)
|
||||
);
|
||||
registerSubCommands(
|
||||
"snapshot",
|
||||
ImmutableList.of("snap"),
|
||||
"Snapshot commands for saving/loading snapshots",
|
||||
SnapshotCommandsRegistration.builder(),
|
||||
new SnapshotCommands(worldEdit)
|
||||
);
|
||||
registerSubCommands(
|
||||
"superpickaxe",
|
||||
ImmutableList.of("pickaxe", "sp"),
|
||||
"Super-pickaxe commands",
|
||||
SuperPickaxeCommandsRegistration.builder(),
|
||||
new SuperPickaxeCommands(worldEdit)
|
||||
);
|
||||
registerSubCommands(
|
||||
"brush",
|
||||
ImmutableList.of("br"),
|
||||
"Brushing commands",
|
||||
BrushCommandsRegistration.builder(),
|
||||
new BrushCommands(worldEdit),
|
||||
manager -> {
|
||||
PaintBrushCommands.register(manager, registration);
|
||||
ApplyBrushCommands.register(manager, registration);
|
||||
}
|
||||
);
|
||||
registerSubCommands(
|
||||
"worldedit",
|
||||
ImmutableList.of("we"),
|
||||
"WorldEdit commands",
|
||||
WorldEditCommandsRegistration.builder(),
|
||||
new WorldEditCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
BiomeCommandsRegistration.builder(),
|
||||
new BiomeCommands()
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
ChunkCommandsRegistration.builder(),
|
||||
new ChunkCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
ClipboardCommandsRegistration.builder(),
|
||||
new ClipboardCommands()
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
GeneralCommandsRegistration.builder(),
|
||||
new GeneralCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
GenerationCommandsRegistration.builder(),
|
||||
new GenerationCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
HistoryCommandsRegistration.builder(),
|
||||
new HistoryCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
NavigationCommandsRegistration.builder(),
|
||||
new NavigationCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
RegionCommandsRegistration.builder(),
|
||||
new RegionCommands()
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
ScriptingCommandsRegistration.builder(),
|
||||
new ScriptingCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
SelectionCommandsRegistration.builder(),
|
||||
new SelectionCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
SnapshotUtilCommandsRegistration.builder(),
|
||||
new SnapshotUtilCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
ToolCommandsRegistration.builder(),
|
||||
new ToolCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
ToolUtilCommandsRegistration.builder(),
|
||||
new ToolUtilCommands(worldEdit)
|
||||
);
|
||||
this.registration.register(
|
||||
commandManager,
|
||||
UtilityCommandsRegistration.builder(),
|
||||
new UtilityCommands(worldEdit)
|
||||
);
|
||||
}
|
||||
|
||||
public ExceptionConverter getExceptionConverter() {
|
||||
return exceptionConverter;
|
||||
}
|
||||
|
||||
void registerCommandsWith(Platform platform) {
|
||||
log.info("Registering commands with " + platform.getClass().getCanonicalName());
|
||||
|
||||
LocalConfiguration config = platform.getConfiguration();
|
||||
boolean logging = config.logCommands;
|
||||
String path = config.logFile;
|
||||
|
||||
// Register log
|
||||
if (!logging || path.isEmpty()) {
|
||||
dynamicHandler.setHandler(null);
|
||||
COMMAND_LOG.setLevel(Level.OFF);
|
||||
} else {
|
||||
File file = new File(config.getWorkingDirectory(), path);
|
||||
COMMAND_LOG.setLevel(Level.ALL);
|
||||
|
||||
log.info("Logging WorldEdit commands to " + file.getAbsolutePath());
|
||||
|
||||
try {
|
||||
dynamicHandler.setHandler(new FileHandler(file.getAbsolutePath(), true));
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not use command log file " + path + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
dynamicHandler.setFormatter(new LogFormat(config.logFormat));
|
||||
}
|
||||
|
||||
platform.registerCommands(commandManager);
|
||||
}
|
||||
|
||||
void removeCommands() {
|
||||
dynamicHandler.setHandler(null);
|
||||
}
|
||||
|
||||
public String[] commandDetection(String[] split) {
|
||||
// Quick script shortcut
|
||||
if (split[0].matches("^[^/].*\\.js$")) {
|
||||
String[] newSplit = new String[split.length + 1];
|
||||
System.arraycopy(split, 0, newSplit, 1, split.length);
|
||||
newSplit[0] = "cs";
|
||||
newSplit[1] = newSplit[1];
|
||||
split = newSplit;
|
||||
}
|
||||
|
||||
String searchCmd = split[0].toLowerCase();
|
||||
|
||||
// Try to detect the command
|
||||
if (!commandManager.containsCommand(searchCmd)) {
|
||||
if (worldEdit.getConfiguration().noDoubleSlash && commandManager.containsCommand("/" + searchCmd)) {
|
||||
split[0] = "/" + split[0];
|
||||
} else if (searchCmd.length() >= 2 && searchCmd.charAt(0) == '/' && commandManager.containsCommand(searchCmd.substring(1))) {
|
||||
split[0] = split[0].substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
return split;
|
||||
}
|
||||
|
||||
private String[] parseArgs(String input) {
|
||||
return new CommandArgParser(input).parseArgs().toArray(String[]::new);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleCommand(CommandEvent event) {
|
||||
Request.reset();
|
||||
|
||||
Actor actor = platformManager.createProxyActor(event.getActor());
|
||||
String[] split = commandDetection(parseArgs(event.getArguments().substring(1)));
|
||||
|
||||
// No command found!
|
||||
if (!commandManager.containsCommand(split[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
LocalSession session = worldEdit.getSessionManager().get(actor);
|
||||
Request.request().setSession(session);
|
||||
if (actor instanceof Entity) {
|
||||
Extent extent = ((Entity) actor).getExtent();
|
||||
if (extent instanceof World) {
|
||||
Request.request().setWorld(((World) extent));
|
||||
}
|
||||
}
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
InjectedValueStore store = MapBackedValueStore.create();
|
||||
store.injectValue(Key.of(Actor.class), ValueProvider.constant(actor));
|
||||
if (actor instanceof Player) {
|
||||
store.injectValue(Key.of(Player.class), ValueProvider.constant((Player) actor));
|
||||
} else {
|
||||
store.injectValue(Key.of(Player.class), context -> {
|
||||
throw new CommandException(TextComponent.of("This command must be used with a player."), ImmutableList.of());
|
||||
});
|
||||
}
|
||||
store.injectValue(Key.of(Arguments.class), ValueProvider.constant(event::getArguments));
|
||||
store.injectValue(Key.of(LocalSession.class),
|
||||
context -> {
|
||||
LocalSession localSession = worldEdit.getSessionManager().get(actor);
|
||||
localSession.tellVersion(actor);
|
||||
return Optional.of(localSession);
|
||||
});
|
||||
|
||||
MemoizingValueAccess context = MemoizingValueAccess.wrap(
|
||||
MergedValueAccess.of(store, globalInjectedValues)
|
||||
);
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
// This is a bit of a hack, since the call method can only throw CommandExceptions
|
||||
// everything needs to be wrapped at least once. Which means to handle all WorldEdit
|
||||
// exceptions without writing a hook into every dispatcher, we need to unwrap these
|
||||
// exceptions and rethrow their converted form, if their is one.
|
||||
try {
|
||||
commandManager.execute(context, ImmutableList.copyOf(split));
|
||||
} catch (Throwable t) {
|
||||
// Use the exception converter to convert the exception if any of its causes
|
||||
// can be converted, otherwise throw the original exception
|
||||
Throwable next = t;
|
||||
do {
|
||||
exceptionConverter.convert(next);
|
||||
next = next.getCause();
|
||||
} while (next != null);
|
||||
|
||||
throw t;
|
||||
}
|
||||
} catch (ConditionFailedException e) {
|
||||
if (e.getCondition() instanceof PermissionCondition) {
|
||||
actor.printError("You are not permitted to do that. Are you in the right mode?");
|
||||
}
|
||||
} catch (UsageException e) {
|
||||
actor.print(TextComponent.builder("")
|
||||
.color(TextColor.RED)
|
||||
.append(e.getRichMessage())
|
||||
.build());
|
||||
ImmutableList<Command> cmd = e.getCommands();
|
||||
if (!cmd.isEmpty()) {
|
||||
actor.print(TextComponent.builder("Usage: ")
|
||||
.color(TextColor.RED)
|
||||
.append(TextComponent.of("/", ColorConfig.getMainText()))
|
||||
.append(HelpGenerator.create(e.getCommandParseResult()).getUsage())
|
||||
.build());
|
||||
}
|
||||
} catch (CommandExecutionException e) {
|
||||
handleUnknownException(actor, e.getCause());
|
||||
} catch (CommandException e) {
|
||||
actor.print(TextComponent.builder("")
|
||||
.color(TextColor.RED)
|
||||
.append(e.getRichMessage())
|
||||
.build());
|
||||
} catch (Throwable t) {
|
||||
handleUnknownException(actor, t);
|
||||
} finally {
|
||||
Optional<EditSession> editSessionOpt =
|
||||
context.snapshotMemory().injectedValue(Key.of(EditSession.class));
|
||||
|
||||
if (editSessionOpt.isPresent()) {
|
||||
EditSession editSession = editSessionOpt.get();
|
||||
session.remember(editSession);
|
||||
editSession.flushSession();
|
||||
|
||||
if (config.profile) {
|
||||
long time = System.currentTimeMillis() - start;
|
||||
int changed = editSession.getBlockChangeCount();
|
||||
if (time > 0) {
|
||||
double throughput = changed / (time / 1000.0);
|
||||
actor.printDebug((time / 1000.0) + "s elapsed (history: "
|
||||
+ changed + " changed; "
|
||||
+ Math.round(throughput) + " blocks/sec).");
|
||||
} else {
|
||||
actor.printDebug((time / 1000.0) + "s elapsed.");
|
||||
}
|
||||
}
|
||||
|
||||
worldEdit.flushBlockBag(actor, editSession);
|
||||
}
|
||||
Request.reset();
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
private void handleUnknownException(Actor actor, Throwable t) {
|
||||
actor.printError("Please report this error: [See console]");
|
||||
actor.printRaw(t.getClass().getName() + ": " + t.getMessage());
|
||||
log.error("An unexpected error while handling a WorldEdit command", t);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleCommandSuggestion(CommandSuggestionEvent event) {
|
||||
try {
|
||||
globalInjectedValues.injectValue(Key.of(Actor.class), ValueProvider.constant(event.getActor()));
|
||||
globalInjectedValues.injectValue(Key.of(Arguments.class), ValueProvider.constant(event::getArguments));
|
||||
// TODO suggestions
|
||||
} catch (CommandException e) {
|
||||
event.getActor().printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the command manager instance.
|
||||
*
|
||||
* @return the command manager
|
||||
*/
|
||||
public CommandManager getCommandManager() {
|
||||
return commandManager;
|
||||
}
|
||||
|
||||
}
|
@ -68,7 +68,7 @@ public class PlatformManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PlatformManager.class);
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
private final CommandManager commandManager;
|
||||
private final PlatformCommandManager platformCommandManager;
|
||||
private final List<Platform> platforms = new ArrayList<>();
|
||||
private final Map<Capability, Platform> preferences = new EnumMap<>(Capability.class);
|
||||
private @Nullable String firstSeenVersion;
|
||||
@ -83,7 +83,7 @@ public class PlatformManager {
|
||||
public PlatformManager(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
this.commandManager = new CommandManager(worldEdit, this);
|
||||
this.platformCommandManager = new PlatformCommandManager(worldEdit, this);
|
||||
|
||||
// Register this instance for events
|
||||
worldEdit.getEventBus().register(this);
|
||||
@ -277,8 +277,8 @@ public class PlatformManager {
|
||||
*
|
||||
* @return the command manager
|
||||
*/
|
||||
public CommandManager getCommandManager() {
|
||||
return commandManager;
|
||||
public PlatformCommandManager getPlatformCommandManager() {
|
||||
return platformCommandManager;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,10 +31,10 @@ import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.HandSide;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.gamemode.GameMode;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@ -134,7 +134,7 @@ class PlayerProxy extends AbstractPlayerActor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(TextComponent component) {
|
||||
public void print(Component component) {
|
||||
basePlayer.print(component);
|
||||
}
|
||||
|
||||
|
@ -102,10 +102,11 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
return readVersion1(schematicTag);
|
||||
} else if (version == 2) {
|
||||
int dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue();
|
||||
if (dataVersion > WorldEdit.getInstance().getPlatformManager()
|
||||
.queryCapability(Capability.WORLD_EDITING).getDataVersion()) {
|
||||
// maybe should just warn? simple schematics may be compatible still.
|
||||
throw new IOException("Schematic was made in a newer Minecraft version. Data may be incompatible.");
|
||||
int liveDataVersion = WorldEdit.getInstance().getPlatformManager()
|
||||
.queryCapability(Capability.WORLD_EDITING).getDataVersion();
|
||||
if (dataVersion > liveDataVersion) {
|
||||
log.warn("Schematic was made in a newer Minecraft version ({} > {}). Data may be incompatible.",
|
||||
dataVersion, liveDataVersion);
|
||||
}
|
||||
BlockArrayClipboard clip = readVersion1(schematicTag);
|
||||
return readVersion2(clip, schematicTag);
|
||||
|
@ -17,24 +17,26 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.argument;
|
||||
package com.sk89q.worldedit.function;
|
||||
|
||||
import com.sk89q.worldedit.function.Contextual;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.util.command.composition.BranchingCommand;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
public class RegionFunctionParser extends BranchingCommand<Contextual<? extends RegionFunction>> {
|
||||
public final class ItemUseFunction implements RegionFunction {
|
||||
private final World world;
|
||||
private final BaseItem item;
|
||||
|
||||
public RegionFunctionParser() {
|
||||
super("functionTpe");
|
||||
putOption(new TreeGeneratorParser("treeType"), "forest");
|
||||
putOption(new ItemUseParser(), "item");
|
||||
putOption(new ReplaceParser(), "set");
|
||||
public ItemUseFunction(World world, BaseItem item) {
|
||||
this.world = world;
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Choose a block function";
|
||||
public boolean apply(BlockVector3 position) throws WorldEditException {
|
||||
return world.useItem(position, item, Direction.UP);
|
||||
}
|
||||
|
||||
}
|
@ -19,7 +19,8 @@
|
||||
|
||||
package com.sk89q.worldedit.internal.annotation;
|
||||
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import org.enginehub.piston.inject.InjectAnnotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@ -27,10 +28,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotates a {@link Vector3} parameter to inject a direction.
|
||||
* Annotates a {@link BlockVector3} parameter to inject a direction.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.PARAMETER)
|
||||
@InjectAnnotation
|
||||
public @interface Direction {
|
||||
|
||||
String AIM = "me";
|
||||
|
@ -17,7 +17,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.command.parametric;
|
||||
package com.sk89q.worldedit.internal.annotation;
|
||||
|
||||
import org.enginehub.piston.inject.InjectAnnotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@ -25,17 +27,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicates an optional parameter.
|
||||
* Annotates a {@code List<BlockVector3>} parameter to inject multiple direction.
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Optional {
|
||||
|
||||
/**
|
||||
* The default value to use if no value is set.
|
||||
*
|
||||
* @return a string value, or an empty list
|
||||
*/
|
||||
String[] value() default {};
|
||||
|
||||
@Target(ElementType.PARAMETER)
|
||||
@InjectAnnotation
|
||||
public @interface MultiDirection {
|
||||
boolean includeDiagonals() default false;
|
||||
}
|
@ -17,29 +17,24 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.util.command.binding;
|
||||
package com.sk89q.worldedit.internal.annotation;
|
||||
|
||||
import org.enginehub.piston.inject.InjectAnnotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Used to validate a string.
|
||||
*
|
||||
* @see PrimitiveBindings where this validation is used
|
||||
* Annotates a {@code double} parameter to inject multiple radii values.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.PARAMETER)
|
||||
public @interface Validate {
|
||||
|
||||
@InjectAnnotation
|
||||
public @interface Radii {
|
||||
/**
|
||||
* An optional regular expression that must match the string.
|
||||
*
|
||||
* @see Pattern regular expression class
|
||||
* @return the pattern
|
||||
* Number of radii values to inject at maximum. May inject less.
|
||||
*/
|
||||
String regex() default "";
|
||||
|
||||
int value();
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
|
||||
package com.sk89q.worldedit.internal.annotation;
|
||||
|
||||
import org.enginehub.piston.inject.InjectAnnotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@ -29,6 +31,6 @@ import java.lang.annotation.Target;
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.PARAMETER)
|
||||
@InjectAnnotation
|
||||
public @interface Selection {
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user