Merge remote-tracking branch 'upstream/master' into merge

This commit is contained in:
Jesse Boyd 2019-11-19 21:23:47 +00:00
commit 2c9f192baf
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
272 changed files with 16041 additions and 6107 deletions

View File

@ -1,3 +1,5 @@
import java.util.Properties
plugins {
`kotlin-dsl`
kotlin("jvm") version embeddedKotlinVersion
@ -6,6 +8,18 @@ plugins {
repositories {
jcenter()
gradlePluginPortal()
maven {
name = "Forge Maven"
url = uri("https://files.minecraftforge.net/maven")
}
maven {
name = "Fabric"
url = uri("https://maven.fabricmc.net/")
}
maven {
name = "sponge"
url = uri("https://repo.spongepowered.org/maven")
}
}
configurations.all {
@ -19,10 +33,24 @@ configurations.all {
}
}
val properties = Properties().also { props ->
project.projectDir.resolveSibling("gradle.properties").bufferedReader().use {
props.load(it)
}
}
val loomVersion: String = properties.getProperty("loom.version")
val mixinVersion: String = properties.getProperty("mixin.version")
dependencies {
implementation(gradleApi())
implementation("gradle.plugin.net.minecrell:licenser:0.4.1")
implementation("org.ajoberstar.grgit:grgit-gradle:3.1.1")
implementation("com.github.jengelman.gradle.plugins:shadow:5.1.0")
implementation("net.ltgt.apt-eclipse:net.ltgt.apt-eclipse.gradle.plugin:0.21")
implementation("net.ltgt.apt-idea:net.ltgt.apt-idea.gradle.plugin:0.21")
implementation("org.jfrog.buildinfo:build-info-extractor-gradle:4.9.7")
implementation("gradle.plugin.org.spongepowered:spongegradle:0.9.0")
implementation("net.minecraftforge.gradle:ForgeGradle:3.0.143")
implementation("net.fabricmc:fabric-loom:$loomVersion")
implementation("net.fabricmc:sponge-mixin:$mixinVersion")
}

View File

@ -0,0 +1,40 @@
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.named
import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention
import org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask
private const val ARTIFACTORY_CONTEXT_URL = "artifactory_contextUrl"
private const val ARTIFACTORY_USER = "artifactory_user"
private const val ARTIFACTORY_PASSWORD = "artifactory_password"
fun Project.applyRootArtifactoryConfig() {
if (!project.hasProperty(ARTIFACTORY_CONTEXT_URL)) ext[ARTIFACTORY_CONTEXT_URL] = "http://localhost"
if (!project.hasProperty(ARTIFACTORY_USER)) ext[ARTIFACTORY_USER] = "guest"
if (!project.hasProperty(ARTIFACTORY_PASSWORD)) ext[ARTIFACTORY_PASSWORD] = ""
apply(plugin = "com.jfrog.artifactory")
configure<ArtifactoryPluginConvention> {
setContextUrl("${project.property(ARTIFACTORY_CONTEXT_URL)}")
clientConfig.publisher.run {
repoKey = when {
"${project.version}".contains("SNAPSHOT") -> "libs-snapshot-local"
else -> "libs-release-local"
}
username = "${project.property(ARTIFACTORY_USER)}"
password = "${project.property(ARTIFACTORY_PASSWORD)}"
isMaven = true
isIvy = false
}
}
tasks.named<ArtifactoryTask>("artifactoryPublish") {
isSkip = true
}
}
fun Project.applyCommonArtifactoryConfig() {
tasks.named<ArtifactoryTask>("artifactoryPublish") {
publishConfigs("archives")
}
}

View File

@ -1,3 +1,5 @@
import org.gradle.api.Project
object Versions {
const val TEXT = "3.0.1"
const val TEXT_EXTRAS = "3.0.2"
@ -6,3 +8,12 @@ object Versions {
const val JUNIT = "5.5.0"
const val MOCKITO = "3.0.0"
}
// Properties that need a project reference to resolve:
class ProjectVersions(project: Project) {
val loom = project.rootProject.property("loom.version")
val mixin = project.rootProject.property("mixin.version")
}
val Project.versions
get() = ProjectVersions(this)

View File

@ -44,12 +44,21 @@
<allow pkg="com.google.auto"/>
<allow pkg="it.unimi.dsi.fastutil"/>
<subpackage name="internal.expression">
<allow pkg="org.antlr.v4"/>
</subpackage>
<subpackage name="bukkit">
<allow pkg="org.bukkit"/>
<allow pkg="org.bstats.bukkit"/>
<allow pkg="io.papermc.lib"/>
</subpackage>
<subpackage name="cli">
<allow pkg="org.apache.logging.log4j"/>
<allow pkg="org.apache.commons.cli" />
</subpackage>
<subpackage name="forge">
<allow pkg="cpw"/>
<allow pkg="net.minecraft"/>
@ -63,6 +72,18 @@
<allow pkg="com.mojang.datafixers" />
</subpackage>
<subpackage name="fabric">
<allow pkg="net.minecraft"/>
<allow pkg="net.fabricmc"/>
<allow pkg="com.mojang.authlib"/>
<allow pkg="org.apache.logging.log4j"/>
<allow pkg="org.lwjgl"/>
<allow pkg="io.netty.buffer"/>
<allow pkg="org.spongepowered" />
<allow pkg="com.mojang.brigadier" />
<allow pkg="com.mojang.datafixers" />
</subpackage>
<subpackage name="sponge">
<allow pkg="net.minecraft"/>
<allow pkg="com.google.inject" />

View File

@ -11,4 +11,4 @@ that you have installed WorldEdit.
In order to be able to use CraftScripts, you must install the Rhino JavaScript library.
The installation page linked above has information about that. More information
about scripts in general can be found at
https://worldedit.enginehub.org/en/latest/usage/other/craftscripts/
https://worldedit.enginehub.org/en/latest/usage/other/craftscripts/

View File

@ -6,4 +6,4 @@ org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError
org.gradle.daemon=true
org.gradle.configureondemand=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.caching=true

Binary file not shown.

22
gradlew vendored
View File

@ -1,5 +1,21 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@ -109,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`

18
gradlew.bat vendored
View File

@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

View File

@ -31,6 +31,7 @@ import com.sk89q.worldedit.bukkit.adapter.IBukkitAdapter;
import com.sk89q.worldedit.bukkit.adapter.SimpleBukkitAdapter;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.extension.platform.PlayerProxy;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
@ -51,15 +52,431 @@ import com.sk89q.worldedit.world.item.ItemTypes;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.Objects;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import java.util.EnumMap;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Adapts between Bukkit and WorldEdit equivalent objects.
*/
public class BukkitAdapter {
private BukkitAdapter() {
}
private static final ParserContext TO_BLOCK_CONTEXT = new ParserContext();
static {
TO_BLOCK_CONTEXT.setRestricted(false);
}
/**
* Checks equality between a WorldEdit BlockType and a Bukkit Material
*
* @param blockType The WorldEdit BlockType
* @param type The Bukkit Material
* @return If they are equal
*/
public static boolean equals(BlockType blockType, Material type) {
return Objects.equals(blockType.getId(), type.getKey().toString());
}
/**
* Convert any WorldEdit world into an equivalent wrapped Bukkit world.
*
* <p>If a matching world cannot be found, a {@link RuntimeException}
* will be thrown.</p>
*
* @param world the world
* @return a wrapped Bukkit world
*/
public static BukkitWorld asBukkitWorld(World world) {
if (world instanceof BukkitWorld) {
return (BukkitWorld) world;
} else {
BukkitWorld bukkitWorld = WorldEditPlugin.getInstance().getInternalPlatform().matchWorld(world);
if (bukkitWorld == null) {
throw new RuntimeException("World '" + world.getName() + "' has no matching version in Bukkit");
}
return bukkitWorld;
}
}
/**
* Create a WorldEdit world from a Bukkit world.
*
* @param world the Bukkit world
* @return a WorldEdit world
*/
public static World adapt(org.bukkit.World world) {
checkNotNull(world);
return new BukkitWorld(world);
}
/**
* Create a WorldEdit Player from a Bukkit Player.
*
* @param player The Bukkit player
* @return The WorldEdit player
*/
public static BukkitPlayer adapt(Player player) {
return WorldEditPlugin.getInstance().wrapPlayer(player);
}
/**
* Create a Bukkit Player from a WorldEdit Player.
*
* @param player The WorldEdit player
* @return The Bukkit player
*/
public static Player adapt(com.sk89q.worldedit.entity.Player player) {
return ((BukkitPlayer) player).getPlayer();
}
/**
* Create a Bukkit world from a WorldEdit world.
*
* @param world the WorldEdit world
* @return a Bukkit world
*/
public static org.bukkit.World adapt(World world) {
checkNotNull(world);
if (world instanceof BukkitWorld) {
return ((BukkitWorld) world).getWorld();
} else {
org.bukkit.World match = Bukkit.getServer().getWorld(world.getName());
if (match != null) {
return match;
} else {
throw new IllegalArgumentException("Can't find a Bukkit world for " + world.getName());
}
}
}
/**
* Create a WorldEdit location from a Bukkit location.
*
* @param location the Bukkit location
* @return a WorldEdit location
*/
public static Location adapt(org.bukkit.Location location) {
checkNotNull(location);
Vector3 position = asVector(location);
return new com.sk89q.worldedit.util.Location(
adapt(location.getWorld()),
position,
location.getYaw(),
location.getPitch());
}
/**
* Create a Bukkit location from a WorldEdit location.
*
* @param location the WorldEdit location
* @return a Bukkit location
*/
public static org.bukkit.Location adapt(Location location) {
checkNotNull(location);
Vector3 position = location.toVector();
return new org.bukkit.Location(
adapt((World) location.getExtent()),
position.getX(), position.getY(), position.getZ(),
location.getYaw(),
location.getPitch());
}
/**
* Create a Bukkit location from a WorldEdit position with a Bukkit world.
*
* @param world the Bukkit world
* @param position the WorldEdit position
* @return a Bukkit location
*/
public static org.bukkit.Location adapt(org.bukkit.World world, Vector3 position) {
checkNotNull(world);
checkNotNull(position);
return new org.bukkit.Location(
world,
position.getX(), position.getY(), position.getZ());
}
/**
* Create a Bukkit location from a WorldEdit position with a Bukkit world.
*
* @param world the Bukkit world
* @param position the WorldEdit position
* @return a Bukkit location
*/
public static org.bukkit.Location adapt(org.bukkit.World world, BlockVector3 position) {
checkNotNull(world);
checkNotNull(position);
return new org.bukkit.Location(
world,
position.getX(), position.getY(), position.getZ());
}
/**
* Create a Bukkit location from a WorldEdit location with a Bukkit world.
*
* @param world the Bukkit world
* @param location the WorldEdit location
* @return a Bukkit location
*/
public static org.bukkit.Location adapt(org.bukkit.World world, Location location) {
checkNotNull(world);
checkNotNull(location);
return new org.bukkit.Location(
world,
location.getX(), location.getY(), location.getZ(),
location.getYaw(),
location.getPitch());
}
/**
* Create a WorldEdit Vector from a Bukkit location.
*
* @param location The Bukkit location
* @return a WorldEdit vector
*/
public static Vector3 asVector(org.bukkit.Location location) {
checkNotNull(location);
return Vector3.at(location.getX(), location.getY(), location.getZ());
}
/**
* Create a WorldEdit BlockVector from a Bukkit location.
*
* @param location The Bukkit location
* @return a WorldEdit vector
*/
public static BlockVector3 asBlockVector(org.bukkit.Location location) {
checkNotNull(location);
return BlockVector3.at(location.getX(), location.getY(), location.getZ());
}
/**
* Create a WorldEdit entity from a Bukkit entity.
*
* @param entity the Bukkit entity
* @return a WorldEdit entity
*/
public static Entity adapt(org.bukkit.entity.Entity entity) {
checkNotNull(entity);
return new BukkitEntity(entity);
}
/**
* Create a Bukkit Material form a WorldEdit ItemType
*
* @param itemType The WorldEdit ItemType
* @return The Bukkit Material
*/
public static Material adapt(ItemType itemType) {
checkNotNull(itemType);
if (!itemType.getId().startsWith("minecraft:")) {
throw new IllegalArgumentException("Bukkit only supports Minecraft items");
}
return Material.getMaterial(itemType.getId().substring(10).toUpperCase(Locale.ROOT));
}
/**
* Create a Bukkit Material form a WorldEdit BlockType
*
* @param blockType The WorldEdit BlockType
* @return The Bukkit Material
*/
public static Material adapt(BlockType blockType) {
checkNotNull(blockType);
if (!blockType.getId().startsWith("minecraft:")) {
throw new IllegalArgumentException("Bukkit only supports Minecraft blocks");
}
return Material.getMaterial(blockType.getId().substring(10).toUpperCase(Locale.ROOT));
}
/**
* Create a WorldEdit GameMode from a Bukkit one.
*
* @param gameMode Bukkit GameMode
* @return WorldEdit GameMode
*/
public static GameMode adapt(org.bukkit.GameMode gameMode) {
checkNotNull(gameMode);
return GameModes.get(gameMode.name().toLowerCase(Locale.ROOT));
}
/**
* Create a WorldEdit BiomeType from a Bukkit one.
*
* @param biome Bukkit Biome
* @return WorldEdit BiomeType
*/
public static BiomeType adapt(Biome biome) {
return BiomeTypes.get(biome.name().toLowerCase(Locale.ROOT));
}
public static Biome adapt(BiomeType biomeType) {
if (!biomeType.getId().startsWith("minecraft:")) {
throw new IllegalArgumentException("Bukkit only supports vanilla biomes");
}
try {
return Biome.valueOf(biomeType.getId().substring(10).toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException e) {
return null;
}
}
/**
* Create a WorldEdit EntityType from a Bukkit one.
*
* @param entityType Bukkit EntityType
* @return WorldEdit EntityType
*/
public static EntityType adapt(org.bukkit.entity.EntityType entityType) {
final String name = entityType.getName();
if (name == null) {
return null;
}
return EntityTypes.get(name.toLowerCase(Locale.ROOT));
}
public static org.bukkit.entity.EntityType adapt(EntityType entityType) {
if (!entityType.getId().startsWith("minecraft:")) {
throw new IllegalArgumentException("Bukkit only supports vanilla entities");
}
return org.bukkit.entity.EntityType.fromName(entityType.getId().substring(10));
}
private static EnumMap<Material, BlockType> materialBlockTypeCache = new EnumMap<>(Material.class);
private static EnumMap<Material, ItemType> materialItemTypeCache = new EnumMap<>(Material.class);
/**
* Converts a Material to a BlockType
*
* @param material The material
* @return The blocktype
*/
@Nullable
public static BlockType asBlockType(Material material) {
checkNotNull(material);
return materialBlockTypeCache.computeIfAbsent(material, input -> BlockTypes.get(material.getKey().toString()));
}
/**
* Converts a Material to a ItemType
*
* @param material The material
* @return The itemtype
*/
@Nullable
public static ItemType asItemType(Material material) {
checkNotNull(material);
return materialItemTypeCache.computeIfAbsent(material, input -> ItemTypes.get(material.getKey().toString()));
}
private static Int2ObjectMap<BlockState> blockStateCache = new Int2ObjectOpenHashMap<>();
private static Map<String, BlockState> blockStateStringCache = new HashMap<>();
/**
* Create a WorldEdit BlockState from a Bukkit BlockData
*
* @param blockData The Bukkit BlockData
* @return The WorldEdit BlockState
*/
public static BlockState adapt(BlockData blockData) {
checkNotNull(blockData);
if (WorldEditPlugin.getInstance().getBukkitImplAdapter() == null) {
return blockStateStringCache.computeIfAbsent(blockData.getAsString(), input -> {
try {
return WorldEdit.getInstance().getBlockFactory().parseFromInput(input, TO_BLOCK_CONTEXT).toImmutableState();
} catch (InputParseException e) {
e.printStackTrace();
return null;
}
});
} else {
return blockStateCache.computeIfAbsent(
WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBlockStateId(blockData).orElseGet(
() -> blockData.getAsString().hashCode()
), input -> {
try {
return WorldEdit.getInstance().getBlockFactory().parseFromInput(blockData.getAsString(), TO_BLOCK_CONTEXT).toImmutableState();
} catch (InputParseException e) {
e.printStackTrace();
return null;
}
});
}
}
private static Int2ObjectMap<BlockData> blockDataCache = new Int2ObjectOpenHashMap<>();
/**
* Create a Bukkit BlockData from a WorldEdit BlockStateHolder
*
* @param block The WorldEdit BlockStateHolder
* @return The Bukkit BlockData
*/
public static <B extends BlockStateHolder<B>> BlockData adapt(B block) {
checkNotNull(block);
// Should never not have an ID for this BlockState.
int cacheKey = BlockStateIdAccess.getBlockStateId(block.toImmutableState()).orElseGet(block::hashCode);
return blockDataCache.computeIfAbsent(cacheKey, input -> Bukkit.createBlockData(block.getAsString())).clone();
}
/**
* Create a WorldEdit BlockState from a Bukkit ItemStack
*
* @param itemStack The Bukkit ItemStack
* @return The WorldEdit BlockState
*/
public static BlockState asBlockState(ItemStack itemStack) throws WorldEditException {
checkNotNull(itemStack);
if (itemStack.getType().isBlock()) {
return adapt(itemStack.getType().createBlockData());
} else {
throw new NotABlockException();
}
}
/**
* Create a WorldEdit BaseItemStack from a Bukkit ItemStack
*
* @param itemStack The Bukkit ItemStack
* @return The WorldEdit BaseItemStack
*/
public static BaseItemStack adapt(ItemStack itemStack) {
checkNotNull(itemStack);
if (WorldEditPlugin.getInstance().getBukkitImplAdapter() != null) {
return WorldEditPlugin.getInstance().getBukkitImplAdapter().adapt(itemStack);
}
return new BaseItemStack(ItemTypes.get(itemStack.getType().getKey().toString()), itemStack.getAmount());
}
/**
* Create a Bukkit ItemStack from a WorldEdit BaseItemStack
*
* @param item The WorldEdit BaseItemStack
* @return The Bukkit ItemStack
*/
public static ItemStack adapt(BaseItemStack item) {
checkNotNull(item);
if (WorldEditPlugin.getInstance().getBukkitImplAdapter() != null) {
return WorldEditPlugin.getInstance().getBukkitImplAdapter().adapt(item);
}
return new ItemStack(adapt(item.getType()), item.getAmount());
}
}
/**
* Adapts between Bukkit and WorldEdit equivalent objects.
*/

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.registry.Category;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.registry.BlockCategoryRegistry;
import org.bukkit.Bukkit;
@ -44,9 +43,4 @@ public class BukkitBlockCategoryRegistry implements BlockCategoryRegistry {
Tag<Material> tag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, new NamespacedKey(namespace, key), Material.class);
return getFromBukkitTag(tag);
}
@Override
public Set<BlockType> getAll(Category<BlockType> category) {
return getCategorisedByName(category.getId());
}
}

View File

@ -75,6 +75,13 @@ public class BukkitBlockRegistry extends BundledBlockRegistry {
return super.getMaterial(state);
}
@Override
public OptionalInt getInternalBlockStateId(BlockState state) {
if (WorldEditPlugin.getInstance().getBukkitImplAdapter() != null) {
return WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBlockStateId(state);
}
return OptionalInt.empty();
}
@Nullable
@Override
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
@ -137,9 +144,4 @@ public class BukkitBlockRegistry extends BundledBlockRegistry {
}
return blocks;
}
@Override
public OptionalInt getInternalBlockStateId(BlockState state) {
return WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBlockStateId(state);
}
}

View File

@ -106,10 +106,6 @@ public class BukkitCommandSender extends AbstractNonPlayerActor {
return true;
}
@Override public boolean togglePermission(String permission) {
return false;
}
@Override public void setPermission(String permission, boolean value) {
}

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.registry.Category;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.registry.ItemCategoryRegistry;
import org.bukkit.Bukkit;
@ -44,9 +43,4 @@ public class BukkitItemCategoryRegistry implements ItemCategoryRegistry {
Tag<Material> tag = Bukkit.getTag(Tag.REGISTRY_ITEMS, new NamespacedKey(namespace, key), Material.class);
return getFromBukkitTag(tag);
}
@Override
public Set<ItemType> getAll(Category<ItemType> category) {
return getCategorisedByName(category.getId());
}
}

View File

@ -44,6 +44,8 @@ import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.Locale;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.gamemode.GameMode;
import com.sk89q.worldedit.world.gamemode.GameModes;
@ -59,7 +61,6 @@ import org.bukkit.inventory.PlayerInventory;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@ -215,12 +216,12 @@ public class BukkitPlayer extends AbstractPlayerActor {
@Override
public GameMode getGameMode() {
return GameModes.get(getPlayer().getGameMode().name().toLowerCase(Locale.ROOT));
return GameModes.get(player.getGameMode().name().toLowerCase(Locale.ROOT));
}
@Override
public void setGameMode(GameMode gameMode) {
getPlayer().setGameMode(org.bukkit.GameMode.valueOf(gameMode.getId().toUpperCase(Locale.ROOT)));
player.setGameMode(org.bukkit.GameMode.valueOf(gameMode.getId().toUpperCase(Locale.ROOT)));
}
@Override
@ -239,6 +240,16 @@ public class BukkitPlayer extends AbstractPlayerActor {
}
}
@Override
public boolean isAllowedToFly() {
return player.getAllowFlight();
}
@Override
public void setFlying(boolean flying) {
player.setFlying(flying);
}
@Override
public void setPermission(String permission, boolean value) {
/*
@ -281,16 +292,6 @@ public class BukkitPlayer extends AbstractPlayerActor {
return player;
}
@Override
public boolean isAllowedToFly() {
return getPlayer().getAllowFlight();
}
@Override
public void setFlying(boolean flying) {
getPlayer().setFlying(flying);
}
@Override
public BaseEntity getState() {
throw new UnsupportedOperationException("Cannot create a state from this object");

View File

@ -41,8 +41,8 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import javax.annotation.Nullable;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.EntityType;

View File

@ -34,6 +34,7 @@ import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.entity.BaseEntity;
@ -43,6 +44,7 @@ import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -328,19 +330,27 @@ public class BukkitWorld extends AbstractWorld {
@Override
public void checkLoadedChunk(BlockVector3 pt) {
World world = getWorld();
int X = pt.getBlockX() >> 4;
int Z = pt.getBlockZ() >> 4;
if (Fawe.isMainThread()) {
world.getChunkAt(X, Z);
} else if (!world.isChunkLoaded(X, Z)) {
if (PaperLib.isPaper()) {
world.getChunkAtAsync(X, Z, true);
} else {
Fawe.get().getQueueHandler().sync(() -> {
world.getChunkAt(X, Z);
});
}
world.getChunkAt(pt.getBlockX() >> 4, pt.getBlockZ() >> 4);
if (!world.isChunkLoaded(pt.getBlockX() >> 4, pt.getBlockZ() >> 4)) {
world.loadChunk(pt.getBlockX() >> 4, pt.getBlockZ() >> 4);
}
if (!world.isChunkLoaded(pt.getBlockX() >> 4, pt.getBlockZ() >> 4)) {
int X = pt.getBlockX() >> 4;
int Z = pt.getBlockZ() >> 4;
if (Fawe.isMainThread()) {
world.getChunkAt(X, Z);
} else if (!world.isChunkLoaded(X, Z)) {
if (PaperLib.isPaper()) {
world.getChunkAtAsync(X, Z, true);
} else {
Fawe.get().getQueueHandler().sync(() -> {
world.getChunkAt(X, Z);
});
}
}
}
}
@Override
@ -552,4 +562,14 @@ public class BukkitWorld extends AbstractWorld {
org.bukkit.entity.Player bukkitPlayer = BukkitAdapter.adapt(player);
WorldEditPlugin.getInstance().getBukkitImplAdapter().sendFakeChunk(getWorld(), bukkitPlayer, packet);
}
@Override
public boolean useItem(BlockVector3 position, BaseItem item, Direction face) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) {
return adapter.simulateItemUse(getWorld(), position, item, face);
}
return false;
}
}

View File

@ -26,7 +26,6 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import java.util.Optional;
import org.bukkit.block.Block;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
@ -42,6 +41,8 @@ import org.enginehub.piston.inject.InjectedValueStore;
import org.enginehub.piston.inject.Key;
import org.enginehub.piston.inject.MapBackedValueStore;
import java.util.Optional;
/**
* Handles all events thrown in relation to a Player
*/

View File

@ -183,8 +183,8 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
if (Files.exists(delChunks)) {
ChunkDeleter.runFromFile(delChunks, true);
}
fail(() -> PermissionsResolverManager.initialize(INSTANCE), "Failed to initialize permissions resolver");
fail(() -> PermissionsResolverManager.initialize(INSTANCE), "Failed to initialize permissions resolver");
}
/**
@ -341,6 +341,20 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
}
}
@Override
public List<String> onTabComplete(CommandSender sender, Command cmd, String commandLabel, String[] args) {
// Add the command to the array because the underlying command handling
// code of WorldEdit expects it
String[] split = new String[args.length + 1];
System.arraycopy(args, 0, split, 1, args.length);
split[0] = "/" + commandLabel;
String arguments = Joiner.on(" ").join(split);
CommandSuggestionEvent event = new CommandSuggestionEvent(wrapCommandSender(sender), arguments);
getWorldEdit().getEventBus().post(event);
return CommandUtil.fixSuggestions(arguments, event.getSuggestions());
}
private void fail(Runnable run, String message) {
try {
run.run();

View File

@ -90,3 +90,4 @@ no-op-permissions: false
debug: false
show-help-on-first-use: true
server-side-cui: true
command-block-support: false

View File

@ -0,0 +1,33 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
applyPlatformAndCoreConfiguration()
applyShadowConfiguration()
dependencies {
"compile"(project(":worldedit-core"))
"compile"("org.apache.logging.log4j:log4j-core:2.8.1")
"compile"("org.apache.logging.log4j:log4j-slf4j-impl:2.8.1")
"compile"("commons-cli:commons-cli:1.4")
}
tasks.named<Jar>("jar") {
manifest {
attributes(
"Implementation-Version" to project.version,
"Main-Class" to "com.sk89q.worldedit.cli.CLIWorldEdit"
)
}
}
tasks.named<ShadowJar>("shadowJar") {
dependencies {
include { true }
}
minimize {
exclude(dependency("org.apache.logging.log4j:log4j-core"))
}
}
tasks.named("assemble").configure {
dependsOn("shadowJar")
}

View File

@ -0,0 +1,37 @@
/*
* 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.cli;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.registry.BlockCategoryRegistry;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
public class CLIBlockCategoryRegistry implements BlockCategoryRegistry {
@Override
public Set<BlockType> getCategorisedByName(String category) {
return CLIWorldEdit.inst.getFileRegistries().getDataFile().blocktags.getOrDefault(category, Collections.emptyList()).stream()
.map(BlockType.REGISTRY::get)
.collect(Collectors.toSet());
}
}

View File

@ -0,0 +1,73 @@
/*
* 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.cli;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.sk89q.worldedit.cli.data.FileRegistries;
import com.sk89q.worldedit.registry.state.BooleanProperty;
import com.sk89q.worldedit.registry.state.DirectionalProperty;
import com.sk89q.worldedit.registry.state.EnumProperty;
import com.sk89q.worldedit.registry.state.IntegerProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.registry.BundledBlockRegistry;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
public class CLIBlockRegistry extends BundledBlockRegistry {
private Property<?> createProperty(String type, String key, List<String> values) {
switch (type) {
case "int": {
List<Integer> fixedValues = values.stream().map(Integer::parseInt).collect(Collectors.toList());
return new IntegerProperty(key, fixedValues);
}
case "bool": {
List<Boolean> fixedValues = values.stream().map(Boolean::parseBoolean).collect(Collectors.toList());
return new BooleanProperty(key, fixedValues);
}
case "enum": {
return new EnumProperty(key, values);
}
case "direction": {
List<Direction> fixedValues = values.stream().map(String::toUpperCase).map(Direction::valueOf).collect(Collectors.toList());
return new DirectionalProperty(key, fixedValues);
}
default:
throw new RuntimeException("Failed to create property");
}
}
@Nullable
@Override
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
Map<String, FileRegistries.BlockProperty> properties =
CLIWorldEdit.inst.getFileRegistries().getDataFile().blocks.get(blockType.getId()).properties;
return ImmutableMap.copyOf(Maps.transformEntries(properties,
(Maps.EntryTransformer<String, FileRegistries.BlockProperty, Property<?>>)
(key, value) -> createProperty(value.type, key, value.values)));
}
}

View File

@ -0,0 +1,165 @@
/*
* 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.cli;
import static com.google.common.base.Preconditions.checkNotNull;
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.FileDialogUtil;
import com.sk89q.worldedit.util.auth.AuthorizationException;
import com.sk89q.worldedit.util.formatting.WorldEditText;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.serializer.plain.PlainComponentSerializer;
import org.slf4j.Logger;
import java.io.File;
import java.util.UUID;
public class CLICommandSender implements Actor {
/**
* One time generated ID.
*/
private static final UUID DEFAULT_ID = UUID.fromString("a233eb4b-4cab-42cd-9fd9-7e7b9a3f74be");
private final CLIWorldEdit app;
private final Logger sender;
public CLICommandSender(CLIWorldEdit app, Logger sender) {
checkNotNull(app);
checkNotNull(sender);
this.app = app;
this.sender = sender;
}
@Override
public UUID getUniqueId() {
return DEFAULT_ID;
}
@Override
public String getName() {
return "Console";
}
@Override
public void printRaw(String msg) {
for (String part : msg.split("\n")) {
sender.info(part);
}
}
private static final String ANSI_PURPLE = "\u001B[35m";
private static final String ANSI_RED = "\u001B[31m";
private static final String ANSI_GREEN = "\u001B[32m";
private static final String ANSI_RESET = "\u001B[0m";
@Override
public void print(String msg) {
for (String part : msg.split("\n")) {
sender.info(ANSI_PURPLE + part + ANSI_RESET);
}
}
@Override
public void printDebug(String msg) {
for (String part : msg.split("\n")) {
sender.debug(ANSI_GREEN + part + ANSI_RESET);
}
}
@Override
public void printError(String msg) {
for (String part : msg.split("\n")) {
sender.error(ANSI_RED + part + ANSI_RESET);
}
}
@Override
public void print(Component component) {
print(PlainComponentSerializer.INSTANCE.serialize(WorldEditText.format(component)));
}
@Override
public boolean canDestroyBedrock() {
return true;
}
@Override
public String[] getGroups() {
return new String[0];
}
@Override
public boolean hasPermission(String perm) {
return true;
}
@Override
public void checkPermission(String permission) throws AuthorizationException {
}
@Override
public boolean isPlayer() {
return false;
}
@Override
public File openFileOpenDialog(String[] extensions) {
return FileDialogUtil.showOpenDialog(extensions);
}
@Override
public File openFileSaveDialog(String[] extensions) {
return FileDialogUtil.showSaveDialog(extensions);
}
@Override
public void dispatchCUIEvent(CUIEvent event) {
}
@Override
public SessionKey getSessionKey() {
return new SessionKey() {
@Override
public String getName() {
return "Console";
}
@Override
public boolean isActive() {
return true;
}
@Override
public boolean isPersistent() {
return true;
}
@Override
public UUID getUniqueId() {
return DEFAULT_ID;
}
};
}
}

View File

@ -17,28 +17,24 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.internal.expression.lexer.tokens;
package com.sk89q.worldedit.cli;
/**
* A unary or binary operator.
*/
public class OperatorToken extends Token {
import com.sk89q.worldedit.util.PropertiesConfiguration;
public final String operator;
import java.io.File;
public OperatorToken(int position, String operator) {
super(position);
this.operator = operator;
public class CLIConfiguration extends PropertiesConfiguration {
public CLIConfiguration(CLIWorldEdit app) {
super(app.getWorkingDir().resolve("worldedit.properties").toFile());
}
@Override
public char id() {
return 'o';
protected void loadExtra() {
}
@Override
public String toString() {
return "OperatorToken(" + operator + ")";
public File getWorkingDirectory() {
return CLIWorldEdit.inst.getWorkingDir().toFile();
}
}
}

View File

@ -17,28 +17,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.internal.expression.lexer.tokens;
package com.sk89q.worldedit.cli;
/**
* A single character that doesn't fit any of the other token categories.
*/
public class CharacterToken extends Token {
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.registry.ItemCategoryRegistry;
public final char character;
import java.util.Set;
import java.util.stream.Collectors;
public CharacterToken(int position, char character) {
super(position);
this.character = character;
}
public class CLIItemCategoryRegistry implements ItemCategoryRegistry {
@Override
public char id() {
return character;
public Set<ItemType> getCategorisedByName(String category) {
return CLIWorldEdit.inst.getFileRegistries().getDataFile().itemtags.get(category).stream()
.map(ItemType.REGISTRY::get)
.collect(Collectors.toSet());
}
@Override
public String toString() {
return "CharacterToken(" + character + ")";
}
}

View File

@ -0,0 +1,159 @@
/*
* 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.cli;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.AbstractPlatform;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Preference;
import com.sk89q.worldedit.world.DataFixer;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.entity.EntityTypes;
import com.sk89q.worldedit.world.registry.Registries;
import org.enginehub.piston.CommandManager;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import javax.annotation.Nullable;
class CLIPlatform extends AbstractPlatform {
private final CLIWorldEdit app;
private int dataVersion = -1;
private final List<World> worlds = new ArrayList<>();
private final Timer timer = new Timer();
private int lastTimerId = 0;
CLIPlatform(CLIWorldEdit app) {
this.app = app;
}
@Override
public Registries getRegistries() {
return CLIRegistries.getInstance();
}
@Override
public int getDataVersion() {
return this.dataVersion;
}
public void setDataVersion(int dataVersion) {
this.dataVersion = dataVersion;
}
@Override
public DataFixer getDataFixer() {
return null;
}
@Override
public boolean isValidMobType(String type) {
return EntityTypes.get(type) != null;
}
@Override
public void reload() {
getConfiguration().load();
}
@Override
public int schedule(long delay, long period, Runnable task) {
this.timer.schedule(new TimerTask() {
@Override
public void run() {
task.run();
if (period >= 0) {
timer.schedule(this, period);
}
}
}, delay);
return this.lastTimerId++;
}
@Override
public List<? extends World> getWorlds() {
return this.worlds;
}
@Nullable
@Override
public Player matchPlayer(Player player) {
return null;
}
@Nullable
@Override
public World matchWorld(World world) {
return this.worlds.stream()
.filter(w -> w.getId().equals(world.getId()))
.findAny()
.orElse(null);
}
@Override
public void registerCommands(CommandManager manager) {
}
@Override
public void registerGameHooks() {
}
@Override
public CLIConfiguration getConfiguration() {
return app.getConfig();
}
@Override
public String getVersion() {
return app.getInternalVersion();
}
@Override
public String getPlatformName() {
return "CLI-Official";
}
@Override
public String getPlatformVersion() {
return app.getInternalVersion();
}
@Override
public Map<Capability, Preference> getCapabilities() {
Map<Capability, Preference> capabilities = new EnumMap<>(Capability.class);
capabilities.put(Capability.CONFIGURATION, Preference.PREFER_OTHERS);
capabilities.put(Capability.GAME_HOOKS, Preference.NORMAL);
capabilities.put(Capability.PERMISSIONS, Preference.NORMAL);
capabilities.put(Capability.USER_COMMANDS, Preference.NORMAL);
capabilities.put(Capability.WORLD_EDITING, Preference.PREFERRED);
return capabilities;
}
public void addWorld(World world) {
worlds.add(world);
}
}

View File

@ -0,0 +1,64 @@
/*
* 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.cli;
import com.sk89q.worldedit.world.registry.BlockCategoryRegistry;
import com.sk89q.worldedit.world.registry.BlockRegistry;
import com.sk89q.worldedit.world.registry.BundledRegistries;
import com.sk89q.worldedit.world.registry.ItemCategoryRegistry;
public class CLIRegistries extends BundledRegistries {
private static final CLIRegistries INSTANCE = new CLIRegistries();
private final BlockRegistry blockRegistry = new CLIBlockRegistry();
private final BlockCategoryRegistry blockCategoryRegistry = new CLIBlockCategoryRegistry();
private final ItemCategoryRegistry itemCategoryRegistry = new CLIItemCategoryRegistry();
/**
* Create a new instance.
*/
private CLIRegistries() {
}
@Override
public BlockRegistry getBlockRegistry() {
return blockRegistry;
}
@Override
public BlockCategoryRegistry getBlockCategoryRegistry() {
return blockCategoryRegistry;
}
@Override
public ItemCategoryRegistry getItemCategoryRegistry() {
return itemCategoryRegistry;
}
/**
* Get a static instance.
*
* @return an instance
*/
public static CLIRegistries getInstance() {
return INSTANCE;
}
}

View File

@ -17,28 +17,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.internal.expression.lexer.tokens;
package com.sk89q.worldedit.cli;
/**
* A keyword.
*/
public class KeywordToken extends Token {
public interface CLIWorld {
public final String value;
/**
* Saves this world back to file if dirty or forced.
*
* @param force Force a save
*/
void save(boolean force);
public KeywordToken(int position, String value) {
super(position);
this.value = value;
}
@Override
public char id() {
return 'k';
}
@Override
public String toString() {
return "KeywordToken(" + value + ")";
}
/**
* Gets whether the world is dirty.
*
* @return If it's dirty
*/
boolean isDirty();
/**
* Set the world's dirty status
*
* @param dirty if dirty
*/
void setDirty(boolean dirty);
}

View File

@ -0,0 +1,335 @@
/*
* 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.cli;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.cli.data.FileRegistries;
import com.sk89q.worldedit.cli.schematic.ClipboardWorld;
import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
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.extension.platform.Platform;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockCategory;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.FuzzyBlockState;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.item.ItemCategory;
import com.sk89q.worldedit.world.item.ItemType;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.Map;
import java.util.Scanner;
/**
* The CLI implementation of WorldEdit.
*/
public class CLIWorldEdit {
private static final Logger LOGGER = LoggerFactory.getLogger(CLIWorldEdit.class);
public static CLIWorldEdit inst;
private CLIPlatform platform;
private CLIConfiguration config;
private Path workingDir;
private String version;
private Actor commandSender;
private FileRegistries fileRegistries;
public CLIWorldEdit() {
inst = this;
}
private void setupPlatform() {
this.fileRegistries = new FileRegistries(this);
this.fileRegistries.loadDataFiles();
WorldEdit.getInstance().getPlatformManager().register(platform);
}
public void setupRegistries() {
// Blocks
for (Map.Entry<String, FileRegistries.BlockManifest> manifestEntry : fileRegistries.getDataFile().blocks.entrySet()) {
if (BlockType.REGISTRY.get(manifestEntry.getKey()) == null) {
BlockType.REGISTRY.register(manifestEntry.getKey(), new BlockType(manifestEntry.getKey(), input -> {
ParserContext context = new ParserContext();
context.setPreferringWildcard(true);
context.setTryLegacy(false);
context.setRestricted(false);
try {
FuzzyBlockState state = (FuzzyBlockState) WorldEdit.getInstance().getBlockFactory().parseFromInput(
manifestEntry.getValue().defaultstate,
context
).toImmutableState();
BlockState defaultState = input.getBlockType().getAllStates().get(0);
for (Map.Entry<Property<?>, Object> propertyObjectEntry : state.getStates().entrySet()) {
@SuppressWarnings("unchecked")
Property<Object> prop = (Property<Object>) propertyObjectEntry.getKey();
defaultState = defaultState.with(prop, propertyObjectEntry.getValue());
}
return defaultState;
} catch (InputParseException e) {
LOGGER.warn("Error loading block state for " + manifestEntry.getKey(), e);
return input;
}
}));
}
}
// Items
for (String name : fileRegistries.getDataFile().items) {
if (ItemType.REGISTRY.get(name) == null) {
ItemType.REGISTRY.register(name, new ItemType(name));
}
}
// Entities
for (String name : fileRegistries.getDataFile().entities) {
if (EntityType.REGISTRY.get(name) == null) {
EntityType.REGISTRY.register(name, new EntityType(name));
}
}
// Biomes
for (String name : fileRegistries.getDataFile().biomes) {
if (BiomeType.REGISTRY.get(name) == null) {
BiomeType.REGISTRY.register(name, new BiomeType(name));
}
}
// Tags
for (String name : fileRegistries.getDataFile().blocktags.keySet()) {
if (BlockCategory.REGISTRY.get(name) == null) {
BlockCategory.REGISTRY.register(name, new BlockCategory(name));
}
}
for (String name : fileRegistries.getDataFile().itemtags.keySet()) {
if (ItemCategory.REGISTRY.get(name) == null) {
ItemCategory.REGISTRY.register(name, new ItemCategory(name));
}
}
}
public void onInitialized() {
// Setup working directory
workingDir = Paths.get("worldedit");
if (!Files.exists(workingDir)) {
try {
Files.createDirectory(workingDir);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
this.commandSender = new CLICommandSender(this, LOGGER);
this.platform = new CLIPlatform(this);
LOGGER.info("WorldEdit CLI (version " + getInternalVersion() + ") is loaded");
}
public void onStarted() {
setupPlatform();
setupRegistries();
WorldEdit.getInstance().loadMappings();
config = new CLIConfiguration(this);
config.load();
WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent());
}
public void onStopped() {
WorldEdit worldEdit = WorldEdit.getInstance();
worldEdit.getSessionManager().unload();
worldEdit.getPlatformManager().unregister(platform);
}
public FileRegistries getFileRegistries() {
return this.fileRegistries;
}
/**
* Get the configuration.
*
* @return the CLI configuration
*/
CLIConfiguration getConfig() {
return this.config;
}
/**
* Get the WorldEdit proxy for the platform.
*
* @return the WorldEdit platform
*/
public Platform getPlatform() {
return this.platform;
}
/**
* Get the working directory where WorldEdit's files are stored.
*
* @return the working directory
*/
public Path getWorkingDir() {
return this.workingDir;
}
/**
* Get the version of the WorldEdit-CLI implementation.
*
* @return a version string
*/
String getInternalVersion() {
if (version == null) {
version = getClass().getPackage().getImplementationVersion();
}
return version;
}
public void saveAllWorlds(boolean force) {
platform.getWorlds().stream()
.filter(world -> world instanceof CLIWorld)
.forEach(world -> ((CLIWorld) world).save(force));
}
public void run(InputStream inputStream) {
try (Scanner scanner = new Scanner(inputStream)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.equals("stop")) {
commandSender.print("Stopping!");
break;
}
CommandEvent event = new CommandEvent(commandSender, line);
WorldEdit.getInstance().getEventBus().post(event);
if (!event.isCancelled()) {
commandSender.printError("Unknown command!");
} else {
saveAllWorlds(false);
}
}
} finally {
saveAllWorlds(false);
}
}
public static void main(String[] args) {
Options options = new Options();
options.addOption("f", "file", true, "The file to load in. Either a schematic, or a level.dat in a world folder.");
options.addOption("s", "script", true, "A file containing a list of commands to run. Newline separated.");
int exitCode = 0;
CLIWorldEdit app = new CLIWorldEdit();
app.onInitialized();
InputStream inputStream = System.in;
try {
CommandLine cmd = new DefaultParser().parse(options, args);
String fileArg = cmd.getOptionValue('f');
File file;
if (fileArg == null) {
String[] formats = Arrays.copyOf(ClipboardFormats.getFileExtensionArray(), ClipboardFormats.getFileExtensionArray().length + 1);
formats[formats.length - 1] = "dat";
file = app.commandSender.openFileOpenDialog(formats);
} else {
file = new File(fileArg);
}
if (file == null) {
throw new IllegalArgumentException("A file must be provided!");
}
if (file.getName().endsWith("level.dat")) {
throw new IllegalArgumentException("level.dat file support is unfinished.");
} else {
ClipboardFormat format = ClipboardFormats.findByFile(file);
if (format != null) {
ClipboardReader dataVersionReader = format
.getReader(Files.newInputStream(file.toPath(), StandardOpenOption.READ));
int dataVersion = dataVersionReader.getDataVersion()
.orElseThrow(() -> new IllegalArgumentException("Failed to obtain data version from schematic."));
dataVersionReader.close();
app.platform.setDataVersion(dataVersion);
app.onStarted();
try (ClipboardReader clipboardReader = format.getReader(Files.newInputStream(file.toPath(), StandardOpenOption.READ))) {
ClipboardWorld world = new ClipboardWorld(
file,
clipboardReader.read(),
file.getName()
);
app.platform.addWorld(world);
WorldEdit.getInstance().getSessionManager().get(app.commandSender).setWorldOverride(world);
}
} else {
throw new IllegalArgumentException("Unknown file provided!");
}
}
String scriptFile = cmd.getOptionValue('s');
if (scriptFile != null) {
File scriptFileHandle = new File(scriptFile);
if (!scriptFileHandle.exists()) {
throw new IllegalArgumentException("Could not find given script file.");
}
InputStream scriptStream = Files.newInputStream(scriptFileHandle.toPath(), StandardOpenOption.READ);
InputStream newLineStream = new ByteArrayInputStream("\n".getBytes(StandardCharsets.UTF_8));
// Cleaner to do this than make an Enumeration :(
inputStream = new SequenceInputStream(new SequenceInputStream(scriptStream, newLineStream), inputStream);
}
app.run(inputStream);
} catch (Exception e) {
e.printStackTrace();
exitCode = 1;
} finally {
app.onStopped();
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.exit(exitCode);
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.cli.data;
import com.google.common.io.Resources;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sk89q.worldedit.cli.CLIWorldEdit;
import com.sk89q.worldedit.util.io.ResourceLoader;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
public class FileRegistries {
private CLIWorldEdit app;
private Gson gson = new GsonBuilder().create();
private DataFile dataFile;
public FileRegistries(CLIWorldEdit app) {
this.app = app;
}
public void loadDataFiles() {
try {
URL url = ResourceLoader.getResource(FileRegistries.class, app.getPlatform().getDataVersion() + ".json");
this.dataFile = gson.fromJson(Resources.toString(url, StandardCharsets.UTF_8), DataFile.class);
} catch (IOException e) {
throw new RuntimeException("The provided file is not compatible with this version of WorldEdit-CLI. Please update or report this.");
}
}
public DataFile getDataFile() {
return this.dataFile;
}
public static class BlockManifest {
public String defaultstate;
public Map<String, BlockProperty> properties;
}
public static class BlockProperty {
public List<String> values;
public String type;
}
public static class DataFile {
public Map<String, List<String>> itemtags;
public Map<String, List<String>> blocktags;
public Map<String, List<String>> entitytags;
public List<String> items;
public List<String> entities;
public List<String> biomes;
public Map<String, BlockManifest> blocks;
}
}

View File

@ -0,0 +1,217 @@
/*
* 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.cli.schematic;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.cli.CLIWorld;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import javax.annotation.Nullable;
public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld {
private final File file;
private final Clipboard clipboard;
private final String name;
private boolean dirty = false;
public ClipboardWorld(File file, Clipboard clipboard, String name) {
this.file = file;
this.clipboard = clipboard;
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public String getId() {
return getName().replace(" ", "_").toLowerCase(Locale.ROOT);
}
@Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight)
throws WorldEditException {
dirty = true;
return clipboard.setBlock(position, block);
}
@Override
public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException {
return false;
}
@Override
public int getBlockLightLevel(BlockVector3 position) {
return 0;
}
@Override
public boolean clearContainerBlockContents(BlockVector3 position) {
return false;
}
@Override
public void dropItem(Vector3 position, BaseItemStack item) {
}
@Override
public void simulateBlockMine(BlockVector3 position) {
}
@Override
public boolean regenerate(Region region, EditSession editSession) {
return false;
}
@Override
public List<? extends Entity> getEntities(Region region) {
return clipboard.getEntities(region);
}
@Override
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position)
throws MaxChangedBlocksException {
return false;
}
@Override
public List<? extends Entity> getEntities() {
return clipboard.getEntities();
}
@Override
public BlockVector3 getSpawnPosition() {
return clipboard.getOrigin();
}
@Nullable
@Override
public Entity createEntity(Location location, BaseEntity entity) {
dirty = true;
return clipboard.createEntity(location, entity);
}
@Override
public BlockState getBlock(BlockVector3 position) {
return clipboard.getBlock(position);
}
@Override
public BaseBlock getFullBlock(BlockVector3 position) {
return clipboard.getFullBlock(position);
}
@Override
public BiomeType getBiome(BlockVector2 position) {
return clipboard.getBiome(position);
}
@Override
public boolean setBiome(BlockVector2 position, BiomeType biome) {
dirty = true;
return clipboard.setBiome(position, biome);
}
@Override
public Region getRegion() {
return clipboard.getRegion();
}
@Override
public BlockVector3 getDimensions() {
return clipboard.getDimensions();
}
@Override
public BlockVector3 getOrigin() {
return clipboard.getOrigin();
}
@Override
public void setOrigin(BlockVector3 origin) {
clipboard.setOrigin(origin);
dirty = true;
}
@Override
public boolean hasBiomes() {
return clipboard.hasBiomes();
}
@Override
public BlockVector3 getMaximumPoint() {
return clipboard.getMaximumPoint();
}
@Override
public BlockVector3 getMinimumPoint() {
return clipboard.getMinimumPoint();
}
@Override
public void save(boolean force) {
if (dirty || force) {
try (ClipboardWriter writer = ClipboardFormats.findByFile(file).getWriter(new FileOutputStream(file))) {
writer.write(this);
dirty = false;
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public boolean isDirty() {
return this.dirty;
}
@Override
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,33 @@
#Don't put comments; they get removed
default-max-polygon-points=-1
schematic-save-dir=schematics
super-pickaxe-many-drop-items=true
register-help=true
nav-wand-item=minecraft:compass
profile=false
trace-unflushed-sessions=false
super-pickaxe-drop-items=true
disallowed-blocks=minecraft:oak_sapling,minecraft:jungle_sapling,minecraft:dark_oak_sapling,minecraft:spruce_sapling,minecraft:birch_sapling,minecraft:acacia_sapling,minecraft:black_bed,minecraft:blue_bed,minecraft:brown_bed,minecraft:cyan_bed,minecraft:gray_bed,minecraft:green_bed,minecraft:light_blue_bed,minecraft:light_gray_bed,minecraft:lime_bed,minecraft:magenta_bed,minecraft:orange_bed,minecraft:pink_bed,minecraft:purple_bed,minecraft:red_bed,minecraft:white_bed,minecraft:yellow_bed,minecraft:powered_rail,minecraft:detector_rail,minecraft:grass,minecraft:dead_bush,minecraft:moving_piston,minecraft:piston_head,minecraft:sunflower,minecraft:rose_bush,minecraft:dandelion,minecraft:poppy,minecraft:brown_mushroom,minecraft:red_mushroom,minecraft:tnt,minecraft:torch,minecraft:fire,minecraft:redstone_wire,minecraft:wheat,minecraft:potatoes,minecraft:carrots,minecraft:melon_stem,minecraft:pumpkin_stem,minecraft:beetroots,minecraft:rail,minecraft:lever,minecraft:redstone_torch,minecraft:redstone_wall_torch,minecraft:repeater,minecraft:comparator,minecraft:stone_button,minecraft:birch_button,minecraft:acacia_button,minecraft:dark_oak_button,minecraft:jungle_button,minecraft:oak_button,minecraft:spruce_button,minecraft:cactus,minecraft:sugar_cane,minecraft:bedrock
max-super-pickaxe-size=5
max-brush-radius=10
craftscript-dir=craftscripts
no-double-slash=false
wand-item=minecraft:wooden_axe
shell-save-type=
scripting-timeout=3000
snapshots-dir=
use-inventory-creative-override=false
log-file=worldedit.log
log-format=[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s]: %5$s%6$s%n
max-changed-blocks=-1
nav-wand-distance=50
butcher-default-radius=-1
default-max-changed-blocks=-1
history-size=15
use-inventory=false
allow-symbolic-links=false
use-inventory-override=false
log-commands=false
butcher-max-radius=-1
max-polygon-points=20
max-radius=-1

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" packages="com.sk89q,org.enginehub">
<Appenders>
<Console name="SysOut" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
</Console>
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
<Policies>
<TimeBasedTriggeringPolicy />
<OnStartupTriggeringPolicy />
</Policies>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="SysOut"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>

View File

@ -21,14 +21,14 @@ configurations.all {
dependencies {
"compile"(project(":worldedit-libs:core"))
"compile"("de.schlichtherle:truezip:6.8.3")
"compile"("rhino:js:1.7R2")
"compile"("rhino:js:1.7.11")
"compile"("org.yaml:snakeyaml:1.23")
"compile"("com.google.guava:guava:21.0")
"compile"("com.google.code.findbugs:jsr305:3.0.2")
"compile"("com.google.code.gson:gson:2.8.0")
"compile"("org.slf4j:slf4j-api:1.7.26")
"compile"("it.unimi.dsi:fastutil:8.2.1")
"compile"("com.googlecode.json-simple:json-simple:1.1.1") { isTransitive = false }
"compile"("com.googlecode.json-simple:json-simple:1.3.9") { isTransitive = false }
"compileOnly"(project(":worldedit-libs:core:ap"))
"annotationProcessor"(project(":worldedit-libs:core:ap"))
// ensure this is on the classpath for the AP
@ -48,6 +48,26 @@ tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-Aarg.name.key.prefix=")
}
tasks.named<AntlrTask>("generateGrammarSource").configure {
val pkg = "com.sk89q.worldedit.antlr"
outputDirectory = file("build/generated-src/antlr/main/${pkg.replace('.', '/')}")
arguments = listOf(
"-visitor", "-package", pkg,
"-Xexact-output-dir"
)
}
// Give intellij info about where ANTLR code comes from
plugins.withId("idea") {
configure<IdeaModel> {
afterEvaluate {
module.sourceDirs.add(file("src/main/antlr"))
module.sourceDirs.add(file("build/generated-src/antlr/main"))
module.generatedSourceDirs.add(file("build/generated-src/antlr/main"))
}
}
}
sourceSets {
main {
java {

View File

@ -0,0 +1,24 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.3.41"
application
}
applyCommonConfiguration()
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
application.mainClassName = "com.sk89q.worldedit.internal.util.DocumentationPrinter"
tasks.named<JavaExec>("run") {
workingDir = rootProject.projectDir
}
dependencies {
"implementation"(project(":worldedit-libs:core:ap"))
"implementation"(project(":worldedit-core"))
"implementation"(kotlin("stdlib-jdk8"))
"implementation"(kotlin("reflect"))
}

View File

@ -0,0 +1,354 @@
/*
* 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.internal.util
import com.google.common.base.Strings
import com.sk89q.worldedit.WorldEdit
import com.sk89q.worldedit.command.BiomeCommands
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.ScriptingCommands
import com.sk89q.worldedit.command.SelectionCommands
import com.sk89q.worldedit.command.SnapshotUtilCommands
import com.sk89q.worldedit.command.ToolCommands
import com.sk89q.worldedit.command.ToolUtilCommands
import com.sk89q.worldedit.command.UtilityCommands
import com.sk89q.worldedit.command.util.PermissionCondition
import com.sk89q.worldedit.internal.command.CommandUtil
import com.sk89q.worldedit.util.formatting.text.TextComponent
import org.enginehub.piston.Command
import org.enginehub.piston.config.TextConfig
import org.enginehub.piston.part.SubCommandPart
import org.enginehub.piston.util.HelpGenerator
import java.nio.file.Files
import java.nio.file.Paths
import java.util.stream.Stream
import kotlin.streams.toList
class DocumentationPrinter private constructor() {
private val nameRegex = Regex("name = \"(.+?)\"")
private val commands = WorldEdit.getInstance().platformManager.platformCommandManager.commandManager.allCommands
.map { it.name to it }.toList().toMap()
private val cmdOutput = StringBuilder()
private val permsOutput = StringBuilder()
private val matchedCommands = mutableSetOf<String>()
private suspend inline fun <reified T> SequenceScope<String>.yieldAllCommandsIn() {
val sourceFile = Paths.get("worldedit-core/src/main/java/" + T::class.qualifiedName!!.replace('.', '/') + ".java")
require(Files.exists(sourceFile)) {
"Source not found for ${T::class.qualifiedName}, looked at ${sourceFile.toAbsolutePath()}"
}
Files.newBufferedReader(sourceFile).useLines { lines ->
var inCommand = false
for (line in lines) {
if (inCommand) {
when (val match = nameRegex.find(line)) {
null -> if (line.trim() == ")") inCommand = false
else -> yield(match.groupValues[1])
}
} else if (line.contains("@Command(")) {
inCommand = true
}
}
}
}
private fun writeAllCommands() {
writeHeader()
dumpSection("General Commands") {
yield("worldedit")
yieldAllCommandsIn<HistoryCommands>()
yieldAllCommandsIn<GeneralCommands>()
}
dumpSection("Navigation Commands") {
yieldAllCommandsIn<NavigationCommands>()
}
dumpSection("Selection Commands") {
yieldAllCommandsIn<SelectionCommands>()
yield("/expand")
}
dumpSection("Region Commands") {
yieldAllCommandsIn<RegionCommands>()
}
dumpSection("Generation Commands") {
yieldAllCommandsIn<GenerationCommands>()
}
dumpSection("Schematic and Clipboard Commands") {
yield("schematic")
yieldAllCommandsIn<ClipboardCommands>()
}
dumpSection("Tool Commands") {
yield("tool")
yieldAllCommandsIn<ToolCommands>()
yieldAllCommandsIn<ToolUtilCommands>()
}
dumpSection("Super Pickaxe Commands") {
yield("superpickaxe")
}
dumpSection("Brush Commands") {
yield("brush")
}
dumpSection("Biome Commands") {
yieldAllCommandsIn<BiomeCommands>()
}
dumpSection("Chunk Commands") {
yieldAllCommandsIn<ChunkCommands>()
}
dumpSection("Snapshot Commands") {
yieldAllCommandsIn<SnapshotUtilCommands>()
yield("snapshot")
}
dumpSection("Scripting Commands") {
yieldAllCommandsIn<ScriptingCommands>()
}
dumpSection("Utility Commands") {
yieldAllCommandsIn<UtilityCommands>()
}
writeFooter()
val missingCommands = commands.keys.filterNot { it in matchedCommands }
require(missingCommands.isEmpty()) { "Missing commands: $missingCommands" }
}
private fun writeHeader() {
cmdOutput.appendln("""
========
Commands
========
.. contents::
:local:
.. note::
Arguments enclosed in ``[ ]`` are optional, those enclosed in ``< >`` are required.
.. tip::
You can access a command listing in-game via the ``//help`` command.
""".trim())
permsOutput.appendln("""
===========
Permissions
===========
By default, no one can use WorldEdit. In order for yourself, moderators, and players to use WorldEdit, you must provide the proper permissions. One way is to provide op to moderators and administrators (unless disabled in the :doc:`configuration <config>`), but providing the permission nodes on this page (through a permissions plugin) is the more flexible.
You can give the ``worldedit.*`` permission to give yourself and other administrators full access to WorldEdit.
Commands
=========
See the :doc:`commands` page for an explanation of some of these commands.
.. csv-table::
:header: Command, Permission
:widths: 15, 25
""".trim())
permsOutput.appendln()
}
private fun writeFooter() {
permsOutput.appendln()
permsOutput.append("""
Other Permissions
==================
.. csv-table::
:header: Permission, Explanation
:widths: 15, 25
``worldedit.navigation.jumpto.tool``,"Allows usage of the navigation wand's ``/jumpto`` shortcut (left click)."
``worldedit.navigation.thru.tool``,"Allows usage of the navigation wand's ``/thru`` shortcut (right click)."
``worldedit.anyblock``,"Allows usage of blocks in the :doc:`disallowed-blocks <config>` config option."
``worldedit.limit.unrestricted``,"Allows setting the limit via the ``//limit`` :doc:`command <commands>` higher than the maximum in the :doc:`configuration <config>`, as well as other limit bypasses."
``worldedit.timeout.unrestricted``,"Allows setting the calculation timeout via the ``//timeout`` :doc:`command <commands>` higher than the maximum in the :doc:`configuration <config>`."
``worldedit.inventory.unrestricted``,"Override the ``use-inventory`` option if enabled in the :doc:`configuration <config>`."
``worldedit.override.bedrock``,"Allows breaking of bedrock with the super-pickaxe tool."
``worldedit.override.data-cycler``,"Allows cycling non-whitelisted blocks with the data cycler tool."
``worldedit.setnbt``,"Allows setting `extra data <https://minecraft.gamepedia.com/Block_entity>`_ on blocks (such as signs, chests, etc)."
``worldedit.report.pastebin``,"Allows uploading report files to pastebin automatically for the ``/worldedit report`` :doc:`command <commands>`."
``worldedit.scripting.execute.<filename>``,"Allows using the CraftScript with the given filename."
""".trim())
}
private fun dumpSection(title: String, addCommandNames: suspend SequenceScope<String>.() -> Unit) {
cmdOutput.append("\n").append(title).append("\n").append(Strings.repeat("~", title.length)).append("\n")
val prefix = reduceToRst(TextConfig.commandPrefixValue())
val commands = sequence(addCommandNames).map { this.commands.getValue(it) }.toList()
matchedCommands.addAll(commands.map { it.name })
cmdsToPerms(commands, prefix)
for (command in commands) {
writeCommandBlock(command, prefix, Stream.empty())
command.parts.stream().filter { p -> p is SubCommandPart }
.flatMap { p -> (p as SubCommandPart).commands.stream() }
.forEach { sc ->
writeCommandBlock(sc, prefix + command.name + " ", Stream.of(command))
}
}
}
private fun cmdsToPerms(cmds: List<Command>, prefix: String) {
cmds.forEach { c ->
permsOutput.append(" ").append(cmdToPerm(prefix, c)).append("\n")
c.parts.filterIsInstance<SubCommandPart>()
.forEach { scp ->
cmdsToPerms(scp.commands.sortedBy { it.name }, prefix + c.name + " ")
}
}
}
private fun cmdToPerm(prefix: String, c: Command): String {
val cond = c.condition
val permissions = when {
cond is PermissionCondition && cond.permissions.isNotEmpty() ->
cond.permissions.joinToString(", ") { "``$it``" }
else -> ""
}
return "``$prefix${c.name}``,\"$permissions\""
}
private fun writeCommandBlock(command: Command, prefix: String, parents: Stream<Command>) {
val name = prefix + command.name
val entries = commandTableEntries(command, parents)
cmdOutput.appendln(".. raw:: html")
cmdOutput.appendln()
cmdOutput.appendln(""" <span id="command-${linkSafe(name)}"></span>""")
cmdOutput.appendln()
cmdOutput.append(".. topic:: ``$name``")
if (!command.aliases.isEmpty()) {
command.aliases.joinTo(cmdOutput, ", ",
prefix = " (or ",
postfix = ")",
transform = { "``$prefix$it``" })
}
cmdOutput.appendln()
cmdOutput.appendln(" :class: command-topic").appendln()
CommandUtil.deprecationWarning(command).ifPresent { warning ->
cmdOutput.appendln("""
| .. WARNING::
| ${reduceToRst(warning).makeRstSafe("\n\n")}
""".trimMargin())
}
cmdOutput.appendln("""
| .. csv-table::
| :widths: 8, 15
""".trimMargin())
cmdOutput.appendln()
for ((k, v) in entries) {
val rstSafe = v.makeRstSafe("\n")
cmdOutput.append(" ".repeat(2))
.append(k)
.append(",")
.append('"')
.append(rstSafe)
.append('"').appendln()
}
cmdOutput.appendln()
}
private fun String.makeRstSafe(lineJoiner: String) = trim()
.replace("\"", "\\\"").replace("\n", "\n" + " ".repeat(2))
.lineSequence()
.map { line -> line.ifBlank { "" } }
.joinToString(separator = lineJoiner)
private fun linkSafe(text: String) = text.replace(" ", "-")
private fun commandTableEntries(command: Command, parents: Stream<Command>): Map<String, String> {
return sequence {
val desc = command.description.run {
val footer = CommandUtil.footerWithoutDeprecation(command)
when {
footer.isPresent -> append(
TextComponent.builder("\n\n").append(footer.get())
)
else -> this
}
}
yield("**Description**" to reduceToRst(desc))
val cond = command.condition
if (cond is PermissionCondition && cond.permissions.isNotEmpty()) {
val perms = cond.permissions.joinToString(", ") { "``$it``" }
yield("**Permissions**" to perms)
}
val usage = reduceToRst(HelpGenerator.create(Stream.concat(parents, Stream.of(command)).toList()).usage)
yield("**Usage**" to "``$usage``")
// Part descriptions
command.parts.filterNot { it is SubCommandPart }
.forEach {
val title = "\u2001\u2001``" + reduceToRst(it.textRepresentation) + "``"
yield(title to reduceToRst(it.description))
}
}.toMap()
}
companion object {
/**
* Generates documentation.
*/
@JvmStatic
fun main(args: Array<String>) {
try {
val printer = DocumentationPrinter()
printer.writeAllCommands()
writeOutput("commands.rst", printer.cmdOutput.toString())
writeOutput("permissions.rst", printer.permsOutput.toString())
} finally {
WorldEdit.getInstance().sessionManager.unload()
}
}
private fun writeOutput(file: String, output: String) {
Files.newBufferedWriter(Paths.get(file)).use {
it.write(output)
}
}
}
}

View File

@ -121,7 +121,6 @@ public class MobSpawnerBlock extends BaseBlock {
@Override
public CompoundTag getNbtData() {
Map<String, Tag> values = new HashMap<>();
values.put("EntityId", new StringTag(mobType));
values.put("Delay", new ShortTag(delay));
values.put("SpawnCount", new ShortTag(spawnCount));
values.put("SpawnRange", new ShortTag(spawnRange));
@ -180,7 +179,6 @@ public class MobSpawnerBlock extends BaseBlock {
this.delay = -1;
}
ShortTag spawnCountTag = null;
ShortTag spawnRangeTag = null;
ShortTag minSpawnDelayTag = null;

View File

@ -0,0 +1,236 @@
grammar Expression;
// Lexer tokens:
PLUS : '+' ;
MINUS : '-' ;
TIMES : '*' ;
DIVIDE : '/' ;
MODULO : '%' ;
POWER : '^' | '**' ;
LEFT_SHIFT : '<<' ;
RIGHT_SHIFT : '>>' ;
ASSIGN : '=' ;
COMPLEMENT : '~' ;
PLUS_ASSIGN : '+=' ;
MINUS_ASSIGN : '-=' ;
TIMES_ASSIGN : '*=' ;
DIVIDE_ASSIGN : '/=' ;
MODULO_ASSIGN : '%=' ;
POWER_ASSIGN : '^=' ;
EQUAL : '==' ;
NOT_EQUAL : '!=' ;
NEAR : '~=' ;
LESS_THAN : '<' ;
LESS_THAN_OR_EQUAL : '<=' ;
GREATER_THAN : '>' ;
GREATER_THAN_OR_EQUAL : '>=' ;
// SC = "Short Circuit"
// Non-SC variants not currently implemented.
AND_SC : '&&' ;
OR_SC : '||' ;
INCREMENT : '++' ;
DECREMENT : '--' ;
COMMA : ',' ;
OPEN_PAREN : '(' ;
CLOSE_PAREN : ')' ;
OPEN_BRACKET : '{' ;
CLOSE_BRACKET : '}' ;
SEMI_COLON : ';' ;
QUESTION_MARK : '?' ;
COLON : ':' ;
EXCLAMATION_MARK : '!' ;
IF : 'if' ;
ELSE : 'else' ;
WHILE : 'while' ;
DO : 'do' ;
FOR : 'for' ;
BREAK : 'break' ;
CONTINUE : 'continue' ;
RETURN : 'return' ;
SWITCH : 'switch' ;
CASE : 'case' ;
DEFAULT : 'default' ;
fragment DIGIT : [0-9] ;
fragment SIGN : [+-] ;
fragment EXP_CHAR : [eE] ;
fragment DECIMAL : '.' DIGIT+ ( EXP_CHAR SIGN? DIGIT+ )? ;
// All numbers are treated the same. No int/dec divide.
NUMBER : ( DIGIT+ DECIMAL? | DECIMAL ) ;
ID : [A-Za-z] [0-9A-Za-z_]* ;
WS : [ \t\r\n\u000C]+ -> skip ;
// Parser rules:
/**
* All statements parseable from the input. Forces consumption of EOF token.
*/
allStatements : statements EOF ;
statements : statement+ ;
statement
: ( block
| ifStatement
| whileStatement
| doStatement
| forStatement
| simpleForStatement
| breakStatement
| continueStatement
| returnStatement
| switchStatement
| expressionStatement
| emptyStatement
) SEMI_COLON?
;
block : '{' statements '}' ;
ifStatement : IF '(' condition=expression ')' trueBranch=statement ( ELSE falseBranch=statement )? ;
whileStatement : WHILE '(' condition=expression ')' body=statement ;
doStatement : DO body=statement WHILE '(' condition=expression ')' ;
// C-Style for loop
forStatement
: FOR '(' init=expression ';' condition=expression ';' update=expression ')' body=statement ;
// Range for loop
simpleForStatement
: FOR '(' counter=ID ASSIGN first=expression ',' last=expression ')' body=statement ;
breakStatement : BREAK ;
continueStatement : CONTINUE ;
returnStatement : RETURN value=expression? ;
switchStatement : SWITCH '(' target=expression ')' '{' (labels+=switchLabel ':' bodies+=statements )+ '}' ;
switchLabel
: CASE constant=constantExpression # Case
| DEFAULT # Default
;
expressionStatement : expression ;
emptyStatement: SEMI_COLON ;
expression : assignmentExpression ;
assignmentExpression
: conditionalExpression
| assignment
;
assignment
: target=ID assignmentOperator source=expression
;
assignmentOperator
: ASSIGN
| POWER_ASSIGN
| TIMES_ASSIGN
| DIVIDE_ASSIGN
| MODULO_ASSIGN
| PLUS_ASSIGN
| MINUS_ASSIGN
;
conditionalExpression
: conditionalOrExpression # CEFallthrough
| condition=conditionalOrExpression QUESTION_MARK
trueBranch=expression COLON falseBranch=conditionalExpression # TernaryExpr
;
conditionalOrExpression
: conditionalAndExpression # COFallthrough
| left=conditionalOrExpression OR_SC right=conditionalAndExpression # ConditionalOrExpr
;
conditionalAndExpression
: equalityExpression # CAFallthrough
| left=conditionalAndExpression AND_SC right=equalityExpression # ConditionalAndExpr
;
equalityExpression
: relationalExpression # EqFallthrough
| left=equalityExpression
op=
( EQUAL
| NOT_EQUAL
| NEAR
) right=relationalExpression # EqualityExpr
;
relationalExpression
: shiftExpression # ReFallthrough
| left=relationalExpression
op=
( LESS_THAN
| GREATER_THAN
| LESS_THAN_OR_EQUAL
| GREATER_THAN_OR_EQUAL
) right=shiftExpression # RelationalExpr
;
shiftExpression
: additiveExpression # ShFallthrough
| left=shiftExpression op=( LEFT_SHIFT | RIGHT_SHIFT ) right=additiveExpression # ShiftExpr
;
additiveExpression
: multiplicativeExpression # AdFallthrough
| left=additiveExpression op=( PLUS | MINUS ) right=multiplicativeExpression # AddExpr
;
multiplicativeExpression
: powerExpression # MuFallthrough
| left=multiplicativeExpression
op=
( TIMES
| DIVIDE
| MODULO
) right=powerExpression # MultiplicativeExpr
;
powerExpression
: unaryExpression # PwFallthrough
| left=powerExpression POWER right=unaryExpression # PowerExpr
;
unaryExpression
: op=( INCREMENT | DECREMENT ) target=ID # PreCrementExpr
| op=( PLUS | MINUS ) expr=unaryExpression # PlusMinusExpr
| postfixExpression # UaFallthrough
| COMPLEMENT expr=unaryExpression # ComplementExpr
| EXCLAMATION_MARK expr=unaryExpression # NotExpr
;
postfixExpression
: unprioritizedExpression # PoFallthrough
| target=ID op=( INCREMENT | DECREMENT) # PostCrementExpr
| expr=postfixExpression op=EXCLAMATION_MARK # PostfixExpr
;
unprioritizedExpression
: functionCall # FunctionCallExpr
| constantExpression # ConstantExpr
| source=ID # IdExpr
| '(' expression ')' # WrappedExpr
;
constantExpression : NUMBER ;
functionCall : name=ID '(' (args+=expression ( ',' args+=expression )*)? ')' ;

View File

@ -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>

View File

@ -404,4 +404,4 @@ public class SimplexNoise {
this.w = w;
}
}
}
}

View File

@ -23,6 +23,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Locale;
import java.util.Locale;
/**
* The {@code TAG_Int_Array} tag.
*/

View File

@ -23,6 +23,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Locale;
import java.util.Locale;
/**
* The {@code TAG_Long_Array} tag.
*/

View File

@ -21,4 +21,4 @@
* 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;
package com.sk89q.minecraft.util.commands;

View File

@ -43,6 +43,8 @@ import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.extent.ChangeSetExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.MaskingExtent;
@ -60,6 +62,7 @@ import com.sk89q.worldedit.extent.world.FastModeExtent;
import com.sk89q.worldedit.extent.world.SurvivalModeExtent;
import com.sk89q.worldedit.extent.world.WatchdogTickingExtent;
import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.biome.BiomeReplace;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.block.Naturalizer;
@ -94,11 +97,11 @@ import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.internal.expression.runtime.ExpressionTimeoutException;
import com.sk89q.worldedit.internal.expression.runtime.RValue;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MathUtils;
import com.sk89q.worldedit.internal.expression.ExpressionTimeoutException;
import com.sk89q.worldedit.internal.expression.LocalSlot.Variable;
import com.sk89q.worldedit.math.MutableBlockVector2;
import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.math.Vector2;
@ -319,6 +322,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
public Extent getBypassHistory() {
return bypassHistory;
}
private final List<WatchdogTickingExtent> watchdogExtents = new ArrayList<>(2);
public void setExtent(AbstractDelegateExtent extent) {
new ExtentTraverser<>(getExtent()).setNext(extent);
@ -1164,6 +1168,18 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
return this.changes = visitor.getAffected();
}
/**
* Count the number of blocks of a list of types in a region.
*
* @param region the region
* @param searchBlocks the list of blocks to search
* @return the number of blocks that matched the block
*/
public int countBlocks(Region region, Set<BaseBlock> searchBlocks) {
BlockMask mask = new BlockMask(this, searchBlocks);
return countBlocks(region, mask);
}
/**
* Remove a cuboid above the given position with a given apothem and a given height.
*
@ -1182,8 +1198,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
getWorld(), // Causes clamping of Y range
position.add(-apothem + 1, 0, -apothem + 1),
position.add(apothem - 1, height - 1, apothem - 1));
Pattern pattern = BlockTypes.AIR.getDefaultState();
return setBlocks(region, pattern);
return setBlocks(region, BlockTypes.AIR.getDefaultState());
}
/**
@ -1231,16 +1246,15 @@ public class EditSession extends PassthroughExtent implements 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 SingleBlockTypeMask(this, blockType);
BlockVector3 adjustment = BlockVector3.ONE.multiply(apothem - 1);
Region region = new CuboidRegion(
getWorld(), // Causes clamping of Y range
@ -1450,7 +1464,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
* @param region the region to stack
* @param dir the direction to stack
* @param count the number of times to stack
* @param copyAir true to also copy air blocks
* @param copyEntities true to copy entities
* @param copyBiomes true to copy biomes
* @param mask source mask for the operation (only matching blocks are copied)
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
@ -1485,10 +1501,13 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
* @param region the region to move
* @param dir the direction
* @param distance the distance to move
* @param copyAir true to copy air blocks
* @param moveEntities true to move entities
* @param copyBiomes true to copy biomes (source biome is unchanged)
* @param mask source mask for the operation (only matching blocks are moved)
* @param replacement the replacement pattern to fill in after moving, or null to use air
* @return number of blocks moved
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* @throws IllegalArgumentException thrown if the region is not a flat region, but copyBiomes is true
*/
public int moveRegion(Region region, BlockVector3 dir, int distance, boolean copyAir,
boolean moveEntities, boolean copyBiomes, Pattern replacement) throws MaxChangedBlocksException {
@ -1563,7 +1582,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
/**
* Drain nearby pools of water or lava, optionally removed waterlogged states from blocks.
*
* @param origin the origin to drain from, which will search a 3×3 area
* @param origin the origin to drain from, which will search a 3x3 area
* @param radius the radius of the removal, where a value should be 0 or greater
* @param waterlogged true to make waterlogged blocks non-waterlogged as well
* @return number of blocks affected
@ -1592,14 +1611,14 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
}
RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1));
// Around the origin in a 3×3 block
// Around the origin in a 3x3 block
for (BlockVector3 position : CuboidRegion.fromCenter(origin, 1)) {
if (mask.test(position)) {
visitor.visit(position);
}
}
Operations.completeBlindly(visitor);
Operations.completeLegacy(visitor);
return this.changes = visitor.getAffected();
}
@ -1680,6 +1699,21 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
return makeCylinder(pos, block, radiusX, radiusZ, height, thickness, false);
}
/**
* Stack a cuboid region. For compatibility, entities are copied by biomes are not.
* Use {@link #stackCuboidRegion(Region, BlockVector3, int, boolean, boolean, Mask)} to fine tune.
*
* @param region the region to stack
* @param dir the direction to stack
* @param count the number of times to stack
* @param copyAir true to also copy air blocks
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int stackCuboidRegion(Region region, BlockVector3 dir, int count, boolean copyAir) throws MaxChangedBlocksException {
return stackCuboidRegion(region, dir, count, true, false, copyAir ? null : new ExistingBlockMask(this));
}
private int makeCylinder(BlockVector3 pos, Pattern block, double radiusX, double radiusZ, int height, double thickness, boolean filled) throws MaxChangedBlocksException {
int affected = 0;
@ -1790,6 +1824,21 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
return this.changes;
}
/**
* Move the blocks in a region a certain direction.
*
* @param region the region to move
* @param dir the direction
* @param distance the distance to move
* @param copyAir true to copy air blocks
* @param replacement the replacement pattern to fill in after moving, or null to use air
* @return number of blocks moved
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
public int moveRegion(Region region, BlockVector3 dir, int distance, boolean copyAir, Pattern replacement) throws MaxChangedBlocksException {
return moveRegion(region, dir, distance, true, false, copyAir ? new ExistingBlockMask(this) : null, replacement);
}
public int makeCircle(BlockVector3 pos, final Pattern block, double radiusX, double radiusY, double radiusZ, boolean filled, Vector3 normal) throws MaxChangedBlocksException {
radiusX += 0.5;
radiusY += 0.5;
@ -2322,8 +2371,10 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
final Expression expression = Expression.compile(expressionString, "x", "y", "z", "type", "data");
expression.optimize();
final RValue typeVariable = expression.getVariable("type", false);
final RValue dataVariable = expression.getVariable("data", false);
final Variable typeVariable = expression.getSlots().getVariable("type")
.orElseThrow(IllegalStateException::new);
final Variable dataVariable = expression.getSlots().getVariable("data")
.orElseThrow(IllegalStateException::new);
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
expression.setEnvironment(environment);
@ -2371,9 +2422,12 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
final Expression expression = Expression.compile(expressionString, "x", "y", "z");
expression.optimize();
final RValue x = expression.getVariable("x", false).optimize();
final RValue y = expression.getVariable("y", false).optimize();
final RValue z = expression.getVariable("z", false).optimize();
final Variable x = expression.getSlots().getVariable("x")
.orElseThrow(IllegalStateException::new);
final Variable y = expression.getSlots().getVariable("y")
.orElseThrow(IllegalStateException::new);
final Variable z = expression.getSlots().getVariable("z")
.orElseThrow(IllegalStateException::new);
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
expression.setEnvironment(environment);

View File

@ -20,8 +20,6 @@
package com.sk89q.worldedit;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.inventory.BlockBag;

View File

@ -78,7 +78,6 @@ import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.world.snapshot.Snapshot;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.File;
@ -148,6 +147,7 @@ public class LocalSession implements TextureHolder {
private transient ResettableExtent transform = null;
private transient ZoneId timezone = ZoneId.systemDefault();
private transient World currentWorld;
private transient boolean tickingWatchdog = false;
private transient UUID uuid;
private transient volatile long historySize = 0;
@ -157,8 +157,6 @@ public class LocalSession implements TextureHolder {
private transient World worldOverride;
private transient boolean tickingWatchdog = false;
private transient boolean loadDefaults = true;
// Saved properties
private String lastScript;
private RegionSelectorType defaultSelector;
@ -1104,6 +1102,14 @@ public class LocalSession implements TextureHolder {
}
}
public void setPlaceAtPos1(boolean placeAtPos1) {
this.placeAtPos1 = placeAtPos1;
}
public boolean isPlaceAtPos1() {
return placeAtPos1;
}
public void setTool(BaseItem item, @Nullable Tool tool, Player player) throws InvalidToolBindException {
ItemType type = item.getType();
if (type.hasBlockType() && type.getBlockType().getMaterial().isAir()) {
@ -1603,4 +1609,13 @@ public class LocalSession implements TextureHolder {
}
}
}
private void prepareEditingExtents(EditSession editSession, Actor actor) {
editSession.setFastMode(fastMode);
editSession.setReorderMode(reorderMode);
if (editSession.getSurvivalExtent() != null) {
editSession.getSurvivalExtent().setStripNbt(!actor.hasPermission("worldedit.setnbt"));
}
editSession.setTickingWatchdog(tickingWatchdog);
}
}

View File

@ -1,66 +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.blocks.metadata;
/**
* Represents the possible types of mobs.
*/
public enum MobType {
BAT("Bat"),
BLAZE("Blaze"),
CAVE_SPIDER("CaveSpider"),
CHICKEN("Chicken"),
COW("Cow"),
CREEPER("Creeper"),
ENDERDRAGON("EnderDragon"),
ENDERMAN("Enderman"),
GHAST("Ghast"),
GIANT("Giant"),
VILLAGER_GOLEM("VillagerGolem"),
HORSE("EntityHorse"),
MAGMA_CUBE("LavaSlime"),
MOOSHROOM("MushroomCow"),
OCELOT("Ozelot"),
PIG("Pig"),
PIG_ZOMBIE("PigZombie"),
SHEEP("Sheep"),
SILVERFISH("Silverfish"),
SKELETON("Skeleton"),
SLIME("Slime"),
SNOWMAN("SnowMan"),
SPIDER("Spider"),
SQUID("Squid"),
VILLAGER("Villager"),
WITCH("Witch"),
WITHER("WitherBoss"),
WOLF("Wolf"),
ZOMBIE("Zombie");
private final String name;
MobType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@ -27,6 +27,7 @@ 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.WorldEditAsyncCommandBuilder;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.Logging;
import com.sk89q.worldedit.entity.Player;
@ -81,6 +82,7 @@ public class BiomeCommands {
public void biomeList(Actor actor,
@ArgFlag(name = 'p', desc = "Page number.", def = "1")
int page) {
WorldEditAsyncCommandBuilder.createAndSendMessage(actor, () -> {
BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager()
.queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry();
@ -97,7 +99,8 @@ public class BiomeCommands {
}
})
.collect(Collectors.toList()));
actor.print(paginationBox.create(page));
return paginationBox.create(page);
}, null);
}
@Command(
@ -180,7 +183,8 @@ public class BiomeCommands {
Mask2D mask2d = mask != null ? mask.toMask2D() : null;
if (atPosition) {
region = new CuboidRegion(player.getLocation().toVector().toBlockPoint(), player.getLocation().toVector().toBlockPoint());
final BlockVector3 pos = player.getLocation().toVector().toBlockPoint();
region = new CuboidRegion(pos, pos);
} else {
region = session.getSelection(world);
}

View File

@ -19,8 +19,6 @@
package com.sk89q.worldedit.command;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
@ -67,6 +65,7 @@ import com.sk89q.worldedit.EmptyClipboardException;
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.blocks.BaseItem;
import com.sk89q.worldedit.command.argument.Arguments;
import com.sk89q.worldedit.command.factory.TreeGeneratorFactory;
@ -127,6 +126,7 @@ import java.nio.file.FileSystems;
import java.util.List;
import java.util.zip.GZIPInputStream;
import org.enginehub.piston.annotation.Command;
import com.sk89q.worldedit.function.factory.Apply;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.ArgFlag;
@ -134,6 +134,8 @@ import org.enginehub.piston.annotation.param.Switch;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Commands to set brush shape.
*/
@ -152,6 +154,15 @@ public class BrushCommands {
this.worldEdit = worldEdit;
}
@Command(
name = "none",
aliases = "unbind",
desc = "Unbind a bound brush from your current item"
)
void none(Player player, LocalSession session) throws WorldEditException {
ToolCommands.setToolNone(player, session, "Brush");
}
@Command(
name = "blendball",
aliases = {"bb", "blend"},
@ -644,18 +655,18 @@ public class BrushCommands {
)
@Deprecated
@CommandPermissions("worldedit.brush.clipboard")
public void clipboardBrush(LocalSession session, InjectedValueAccess context,
@Switch(name = 'a', desc = "Don't paste air from the clipboard")
boolean ignoreAir,
@Switch(name = 'o', desc = "Paste starting at the target location, instead of centering on it")
boolean usingOrigin,
@Switch(name = 'e', desc = "Skip paste entities if available")
boolean skipEntities,
@Switch(name = 'b', desc = "Paste biomes if available")
boolean pasteBiomes,
@ArgFlag(name = 'm', desc = "Skip blocks matching this mask in the clipboard", def = "")
@ClipboardMask
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 starting at the target location, instead of centering on it")
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 = "")
@ClipboardMask
Mask sourceMask) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
@ -678,13 +689,13 @@ public class BrushCommands {
descFooter = "Example: '/brush smooth 2 4 grass_block,dirt,stone'"
)
@CommandPermissions("worldedit.brush.smooth")
public void smoothBrush(Player player, InjectedValueAccess context, EditSession editSession,
@Arg(desc = "The radius to sample for softening", def = "2")
Expression 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 maskOpt) throws WorldEditException {
public void smoothBrush(Player player, LocalSession session,
@Arg(desc = "The radius to sample for softening", def = "2")
Expression 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 maskOpt) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
FaweLimit limit = Settings.IMP.getLimit(player);
@ -1089,4 +1100,106 @@ public class BrushCommands {
player.print("Set brush to " + factory);
}
@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);
}
}

View File

@ -18,8 +18,6 @@
*/
package com.sk89q.worldedit.command;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME;
@ -39,6 +37,7 @@ import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
@ -46,9 +45,10 @@ import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.LegacyChunkStore;
import com.sk89q.worldedit.world.storage.McRegionChunkStore;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.io.File;
import java.nio.file.Path;
import java.time.ZonedDateTime;
import java.util.ArrayList;
@ -59,6 +59,8 @@ import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.ArgFlag;
import org.enginehub.piston.exception.StopExecutionException;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Commands for working with chunks.
*/

View File

@ -19,6 +19,8 @@
package com.sk89q.worldedit.command;
import com.google.common.collect.Lists;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.BBC;
@ -37,12 +39,10 @@ import com.boydti.fawe.util.MaskTraverser;
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.event.extent.PasteEvent;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.Extent;
@ -53,6 +53,8 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.function.block.BlockReplace;
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
@ -91,11 +93,10 @@ import java.util.Set;
import java.util.function.Supplier;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
import java.util.List;
/**
* Clipboard commands.
@ -103,18 +104,6 @@ import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class ClipboardCommands {
private WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public ClipboardCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
name = "/copy",
@ -442,6 +431,8 @@ public class ClipboardCommands {
boolean atOrigin,
@Switch(name = 's', desc = "Select the region after pasting")
boolean selectPasted,
@Switch(name = 'n', desc = "No paste, select only. (Implies -s)")
boolean onlySelect,
@Switch(name = 'e', desc = "Paste entities if available")
boolean pasteEntities,
@Switch(name = 'b', desc = "Paste biomes if available")
@ -457,6 +448,7 @@ public class ClipboardCommands {
}
Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion();
List<String> messages = Lists.newArrayList();
BlockVector3 to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(actor);
checkPaste(actor, editSession, to, holder, clipboard);
@ -471,7 +463,7 @@ public class ClipboardCommands {
.build();
Operations.completeLegacy(operation);
if (selectPasted) {
if (selectPasted || onlySelect) {
BlockVector3 clipboardOffset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
Vector3 realTo = to.toVector3().add(holder.getTransform().apply(clipboardOffset.toVector3()));
Vector3 max = realTo.add(holder.getTransform().apply(region.getMaximumPoint().subtract(region.getMinimumPoint()).toVector3()));
@ -578,7 +570,7 @@ public class ClipboardCommands {
AffineTransform transform = new AffineTransform();
transform = transform.scale(direction.abs().multiply(-2).add(1, 1, 1).toVector3());
holder.setTransform(holder.getTransform().combine(transform));
actor.print(BBC.COMMAND_FLIPPED.s());
actor.print("The clipboard copy has been flipped.");
}
@Command(
@ -588,6 +580,6 @@ public class ClipboardCommands {
@CommandPermissions("worldedit.clipboard.clear")
public void clearClipboard(Actor actor, LocalSession session) throws WorldEditException {
session.setClipboard(null);
actor.print(BBC.CLIPBOARD_CLEARED.s());
actor.print("Clipboard cleared.");
}
}

View File

@ -19,9 +19,6 @@
package com.sk89q.worldedit.command;
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
import static com.sk89q.worldedit.internal.command.CommandUtil.requireIV;
import com.google.common.collect.ImmutableSet;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
@ -39,7 +36,6 @@ import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.world.World;
import java.util.List;
import org.enginehub.piston.Command;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.CommandManagerService;
@ -48,6 +44,11 @@ import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.inject.Key;
import org.enginehub.piston.part.SubCommandPart;
import java.util.List;
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
import static com.sk89q.worldedit.internal.command.CommandUtil.requireIV;
/**
* Extracted from {@link SelectionCommands} to allow importing of {@link Command}.
*/

View File

@ -19,8 +19,6 @@
package com.sk89q.worldedit.command;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.extent.ResettableExtent;
@ -44,6 +42,8 @@ import com.sk89q.worldedit.extension.input.DisallowedUsageException;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor;
import java.util.ArrayList;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.function.mask.Mask;
@ -52,7 +52,6 @@ import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.item.ItemType;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -64,6 +63,8 @@ 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;
/**
* General WorldEdit commands.
*/
@ -132,8 +133,8 @@ public class GeneralCommands {
}
@Command(
name = "/fast",
desc = "Toggle fast mode"
name = "/fast",
desc = "Toggle fast mode"
)
@CommandPermissions("worldedit.fast")
public void fast(Actor actor, LocalSession session,
@ -144,12 +145,13 @@ public class GeneralCommands {
actor.printError("Fast mode already " + (fastMode ? "enabled" : "disabled") + ".");
return;
}
if (hasFastMode) {
session.setFastMode(false);
actor.print(BBC.FAST_DISABLED.s());
actor.print("Fast mode disabled.");
} else {
session.setFastMode(true);
actor.print(BBC.FAST_ENABLED.s());
actor.print("Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes.");
}
}
@ -196,20 +198,20 @@ public class GeneralCommands {
}
}
// @Command(
// name = "/world",
// desc = "Sets the world override"
// )
// @CommandPermissions("worldedit.world")
// public void worldOverride(Actor actor, LocalSession session,
// @Arg(desc = "The world override", def = "") World world) {
// session.setWorldOverride(world);
// if (world == null) {
// actor.print("Removed world override.");
// } else {
// actor.print("Set the world override to " + world.getId() + ". (Use //world to go back to default)");
// }
// }
@Command(
name = "/world",
desc = "Sets the world override"
)
@CommandPermissions("worldedit.world")
public void world(Actor actor, LocalSession session,
@Arg(desc = "The world override", def = "") World world) {
session.setWorldOverride(world);
if (world == null) {
actor.print("Removed world override.");
} else {
actor.print("Set the world override to " + world.getId() + ". (Use //world to go back to default)");
}
}
@Command(
name = "/watchdog",
@ -237,16 +239,18 @@ public class GeneralCommands {
@Command(
name = "gmask",
aliases = {"/gmask"},
descFooter = "The global destination mask applies to all edits you do and masks based on the destination blocks (i.e., the blocks in the world).",
desc = "Set the global mask"
)
@CommandPermissions({"worldedit.global-mask", "worldedit.mask.global"})
public void gmask(Actor actor, LocalSession session, @Arg(desc = "The mask to set", def = "") Mask mask) {
session.setMask(mask);
@CommandPermissions("worldedit.global-mask")
public void gmask(Actor actor, LocalSession session,
@Arg(desc = "The mask to set", def = "")
Mask mask) {
if (mask == null) {
actor.print(BBC.MASK_DISABLED.s());
session.setMask(null);
actor.print("Global mask disabled.");
} else {
actor.print(BBC.MASK.s());
session.setMask(mask);
actor.print("Global mask set.");
}
}
@ -291,7 +295,7 @@ public class GeneralCommands {
actor.print(new ItemSearcher(search, blocksOnly, itemsOnly, page).call());
}
public static class ItemSearcher implements Callable<Component> {
private static class ItemSearcher implements Callable<Component> {
private final boolean blocksOnly;
private final boolean itemsOnly;
private final String search;

View File

@ -18,8 +18,6 @@
*/
package com.sk89q.worldedit.command;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.command.MethodCommands.getArguments;
import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL;
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
@ -42,10 +40,13 @@ import com.sk89q.worldedit.command.util.Logging;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.function.generator.CavesGen;
import java.util.List;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.internal.annotation.Radii;
import com.sk89q.worldedit.internal.annotation.Range;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.internal.expression.ExpressionException;
@ -61,11 +62,12 @@ import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.List;
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 org.enginehub.piston.inject.InjectedValueAccess;
/**
@ -184,20 +186,15 @@ public class GenerationCommands {
)
@CommandPermissions("worldedit.generation.cylinder")
@Logging(PLACEMENT)
public void hcyl(Actor actor, LocalSession session, EditSession editSession,
public int hcyl(Actor actor, LocalSession session, EditSession editSession,
@Arg(desc = "The pattern of blocks to generate")
Pattern pattern,
@Arg(desc = "The radii of the cylinder. Order is N/S, E/W") BlockVector2 radius,
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,
@Range(min = 1) @Arg(desc = "double", def = "1") double thickness, InjectedValueAccess context) throws WorldEditException {
double max = MathMan.max(radius.getBlockX(), radius.getBlockZ());
worldEdit.checkMaxRadius(max);
BlockVector3 pos = session.getPlacementPosition(actor);
actor.checkConfirmationRadius(() -> {
int affected = editSession.makeHollowCylinder(pos, pattern, radius.getX(), radius.getZ(), Math.min(256, height), thickness - 1);
BBC.VISITOR_BLOCK.send(actor, affected);
}, "/hcyl", (int) max, context);
int height) throws WorldEditException {
return cyl(actor, session, editSession, pattern, radii, height, true);
}
@Command(
@ -278,9 +275,10 @@ public class GenerationCommands {
int size,
@Arg(desc = "The type of forest", def = "tree")
TreeType type,
@Range(min = 0, max = 100) @Arg(desc = "The density of the forest, between 0 and 100", def = "5")
@Arg(desc = "The density of the forest, between 0 and 100", def = "5")
double density) throws WorldEditException {
checkCommandArgument(0 <= density && density <= 100, "Density must be between 0 and 100");
worldEdit.checkMaxRadius(size);
density /= 100;
int affected = editSession.makeForest(session.getPlacementPosition(actor), size, density, type);
actor.print(affected + " trees created.");
@ -295,14 +293,10 @@ public class GenerationCommands {
@Logging(POSITION)
public int pumpkins(Actor actor, LocalSession session, EditSession editSession,
@Arg(desc = "The size of the patch", def = "10")
int size,
@Arg(desc = "//TODO", def = "10")
int apothem,
@Arg(desc = "//TODO ", def = "0.02")
double density) throws WorldEditException {
checkCommandArgument(0 <= density && density <= 100, "Density must be between 0 and 100");
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(actor), apothem, density);
BBC.COMMAND_PUMPKIN.send(actor, affected);
int size) throws WorldEditException {
worldEdit.checkMaxRadius(size);
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(actor), size);
actor.print(affected + " pumpkin patches created.");
return affected;
}

View File

@ -19,8 +19,6 @@
package com.sk89q.worldedit.command;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC;
@ -57,6 +55,8 @@ import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.Switch;
import org.enginehub.piston.inject.InjectedValueAccess;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Commands to undo, redo, and clear history.
*/
@ -223,6 +223,16 @@ public class HistoryCommands {
aliases = { "/un", "/ud", "undo" },
desc = "Undoes the last action (from history)"
)
} else {
undoSession = session;
}
int finalTimes = times;
player.checkConfirmation(() -> {
EditSession undone = null;
int i = 0;
for (; i < finalTimes; ++i) {
undone = undoSession.undo(undoSession.getBlockBag(player), player);
if (undone == null) break;
@CommandPermissions({"worldedit.history.undo", "worldedit.history.undo.self"})
public void undo(Player player, LocalSession session,
@Range(min = 1) @Arg(desc = "Number of undoes to perform", def = "1")
@ -243,16 +253,6 @@ public class HistoryCommands {
BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, playerName);
return;
}
} else {
undoSession = session;
}
int finalTimes = times;
player.checkConfirmation(() -> {
EditSession undone = null;
int i = 0;
for (; i < finalTimes; ++i) {
undone = undoSession.undo(undoSession.getBlockBag(player), player);
if (undone == null) break;
worldEdit.flushBlockBag(player, undone);
}
if (undone == null) i--;
@ -311,7 +311,7 @@ public class HistoryCommands {
@CommandPermissions("worldedit.history.clear")
public void clearHistory(Actor actor, LocalSession session) {
session.clearHistory();
actor.print(BBC.COMMAND_HISTORY_CLEAR.s());
actor.print("History cleared.");
}
}

View File

@ -18,8 +18,6 @@
*/
package com.sk89q.worldedit.command;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION;
import com.boydti.fawe.config.BBC;
@ -36,6 +34,8 @@ 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;
/**
* Commands for moving the player around.
*/
@ -62,7 +62,7 @@ public class NavigationCommands {
@CommandPermissions("worldedit.navigation.unstuck")
public void unstuck(Player player) throws WorldEditException {
player.findFreePosition();
player.print(BBC.UNSTUCK.s());
player.print("There you go!");
}
@Command(
@ -84,11 +84,7 @@ public class NavigationCommands {
if (ascentLevels == 0) {
player.printError(BBC.ASCEND_FAIL.s());
} else {
if (ascentLevels == 1) {
player.print(BBC.ASCENDED_SINGULAR.s());
} else {
BBC.ASCENDED_PLURAL.send(player, ascentLevels);
}
player.print((ascentLevels != 1) ? "Ascended " + ascentLevels + " levels." : "Ascended a level.");
}
}
@ -113,7 +109,7 @@ public class NavigationCommands {
} else if (descentLevels == 1) {
player.print(BBC.DESCEND_SINGULAR.s());
} else {
BBC.DESCEND_PLURAL.send(player, descentLevels);
player.print((descentLevels != 1) ? "Descended " + descentLevels + " levels." : "Descended a level.");
}
}

View File

@ -19,19 +19,23 @@
package com.sk89q.worldedit.command;
import com.google.common.base.Joiner;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.implementation.processors.ChunkSendProcessor;
import com.boydti.fawe.beta.implementation.processors.NullProcessor;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweLimit;
import com.google.common.collect.Lists;
import com.sk89q.jnbt.CompoundTag;
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.function.RegionFunction;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.command.util.Logging;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
@ -39,9 +43,11 @@ import com.sk89q.worldedit.function.FlatRegionFunction;
import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.biome.BiomeReplace;
import com.sk89q.worldedit.function.generator.FloraGenerator;
import com.sk89q.worldedit.function.mask.MaskIntersection;
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.visitor.RegionVisitor;
import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
@ -63,6 +69,8 @@ import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.Regions;
import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.world.World;
@ -81,10 +89,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.command.MethodCommands.getArguments;
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.internal.command.CommandUtil.checkCommandArgument;
@ -98,16 +103,35 @@ import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
@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(
name = "/set",
desc = "Sets all the blocks in the region"
)
@CommandPermissions("worldedit.region.set")
@Logging(REGION)
public int set(Actor actor, EditSession editSession,
@Selection Region region,
@Arg(desc = "The pattern 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()) {
actor.print("Operation completed.");
} else {
actor.print("Operation completed (" + Joiner.on(", ").join(messages) + ").");
}
return visitor.getAffected();
}
@Command(
@ -254,7 +278,7 @@ public class RegionCommands {
@Selection Region region,
@Arg(desc = "The pattern of blocks to place")
Pattern pattern,
@Range(min = 1) @Arg(desc = "The thickness of the line", def = "0")
@Arg(desc = "The thickness of the line", def = "0")
int thickness,
@Switch(name = 'h', desc = "Generate only a shell")
boolean shell) throws WorldEditException {
@ -269,7 +293,7 @@ public class RegionCommands {
BlockVector3 pos2 = cuboidregion.getPos2();
int blocksChanged = editSession.drawLine(pattern, pos1, pos2, thickness, !shell);
BBC.VISITOR_BLOCK.send(actor, blocksChanged);
actor.print(blocksChanged + " block(s) have been changed.");
return blocksChanged;
}
@ -290,7 +314,7 @@ public class RegionCommands {
boolean shell, InjectedValueAccess context) throws WorldEditException {
if (!(region instanceof ConvexPolyhedralRegion)) {
actor.printError("//curve only works with convex polyhedral selections");
return;
return 0;
}
checkCommandArgument(thickness >= 0, "Thickness must be >= 0");
@ -300,7 +324,7 @@ public class RegionCommands {
int blocksChanged = editSession.drawSpline(pattern, vectors, 0, 0, 0, 10, thickness, !shell);
BBC.VISITOR_BLOCK.send(actor, blocksChanged);
actor.print(blocksChanged + " block(s) have been changed.");
}, getArguments(context), region, context);
}
@ -321,14 +345,8 @@ public class RegionCommands {
}
Mask finalFrom = from;
actor.checkConfirmationRegion(() -> {
int affected = editSession.replaceBlocks(region, finalFrom, to);
BBC.VISITOR_BLOCK.send(actor, affected);
if (!actor.hasPermission("fawe.tips")) {
BBC.TIP_REPLACE_ID
.or(BBC.TIP_REPLACE_LIGHT, BBC.TIP_REPLACE_MARKER, BBC.TIP_TAB_COMPLETE,
BBC.TIP_REPLACE_REGEX, BBC.TIP_REPLACE_REGEX_2, BBC.TIP_REPLACE_REGEX_3,
BBC.TIP_REPLACE_REGEX_4, BBC.TIP_REPLACE_REGEX_5).send(actor);
}
int affected = editSession.replaceBlocks(region, finalFrom, to);
actor.print(affected + " block(s) have been replaced.");
}, getArguments(context), region, context);
}
@ -342,8 +360,8 @@ public class RegionCommands {
@Arg(desc = "The pattern of blocks to overlay")
Pattern pattern, InjectedValueAccess context) throws WorldEditException {
actor.checkConfirmationRegion(() -> {
int affected = editSession.overlayCuboidBlocks(region, pattern);
BBC.VISITOR_BLOCK.send(actor, affected);
int affected = editSession.overlayCuboidBlocks(region, pattern);
actor.print(affected + " block(s) have been overlaid.");
}, getArguments(context), region, context);
}
@ -380,11 +398,12 @@ public class RegionCommands {
)
@Logging(REGION)
@CommandPermissions("worldedit.region.center")
public void center(Actor actor, EditSession editSession, @Selection Region region,
public int center(Actor actor, EditSession editSession, @Selection Region region,
@Arg(desc = "The pattern of blocks to set")
Pattern pattern) throws WorldEditException {
int affected = editSession.center(region, pattern);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print("Center set (" + affected + " block(s) changed)");
return affected;
}
@Command(
@ -396,7 +415,7 @@ public class RegionCommands {
public void naturalize(Actor actor, EditSession editSession, @Selection Region region, InjectedValueAccess context) throws WorldEditException {
actor.checkConfirmationRegion(() -> {
int affected = editSession.naturalizeCuboidBlocks(region);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been made to look more natural.");
}, getArguments(context), region, context);
}
@ -411,7 +430,7 @@ public class RegionCommands {
Pattern pattern, InjectedValueAccess context) throws WorldEditException {
actor.checkConfirmationRegion(() -> {
int affected = editSession.makeWalls(region, pattern);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been changed.");
}, getArguments(context), region, context);
}
@ -427,7 +446,7 @@ public class RegionCommands {
Pattern pattern, InjectedValueAccess context) throws WorldEditException {
actor.checkConfirmationRegion(() -> {
int affected = editSession.makeCuboidFaces(region, pattern);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been changed.");
}, getArguments(context), region, context);
}
@ -456,7 +475,7 @@ public class RegionCommands {
HeightMap heightMap = new HeightMap(editSession, region, mask, snow);
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
int affected = heightMap.applyFilter(filter, iterations);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print("Terrain's height map smoothed. " + affected + " block(s) changed.");
} catch (Throwable e) {
throw new RuntimeException(e);
}
@ -522,8 +541,20 @@ public class RegionCommands {
boolean copyBiomes,
InjectedValueAccess context) throws WorldEditException {
checkCommandArgument(count >= 1, "Count must be >= 1");
Mask combinedMask;
if (ignoreAirBlocks) {
if (mask == null) {
combinedMask = new ExistingBlockMask(editSession);
} else {
combinedMask = new MaskIntersection(mask, new ExistingBlockMask(editSession));
}
} else {
combinedMask = mask;
}
actor.checkConfirmationRegion(() -> {
int affected = editSession.moveRegion(region, direction, count, !ignoreAirBlocks, !skipEntities, copyBiomes, replace);
int affected = editSession.moveRegion(region, direction, count, !ignoreAirBlocks, !skipEntities, copyBiomes, combinedMask, replace);
if (moveSelection) {
try {
@ -583,17 +614,29 @@ public class RegionCommands {
@ArgFlag(name = 'm', desc = "Source mask", def="")
Mask sourceMask,
InjectedValueAccess context) throws WorldEditException {
Mask combinedMask;
if (ignoreAirBlocks) {
if (mask == null) {
combinedMask = new ExistingBlockMask(editSession);
} else {
combinedMask = new MaskIntersection(mask, new ExistingBlockMask(editSession));
}
} else {
combinedMask = mask;
}
actor.checkConfirmationStack(() -> {
if (sourceMask != null) {
editSession.addSourceMask(sourceMask);
}
int affected = editSession.stackCuboidRegion(region, direction, count, !ignoreAirBlocks, !skipEntities, copyBiomes);
int affected = editSession.stackCuboidRegion(region, direction, count, !skipEntities, copyBiomes, combinedMask);
if (moveSelection) {
try {
final BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint());
final BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1);
final BlockVector3 shiftVector = direction.toVector3().multiply(count * (Math.abs(direction.dot(size)) + 1)).toBlockPoint();
final BlockVector3 shiftVector = direction.multiply(size).multiply(count);
region.shift(shiftVector);
session.getRegionSelector(world).learnChanges();
@ -652,7 +695,7 @@ public class RegionCommands {
if (actor instanceof Player) {
((Player) actor).findFreePosition();
}
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been deformed.");
} catch (ExpressionException e) {
actor.printError(e.getMessage());
}
@ -718,7 +761,7 @@ public class RegionCommands {
Mask finalMask = mask == null ? new SolidBlockMask(editSession) : mask;
actor.checkConfirmationRegion(() -> {
int affected = editSession.hollowOutRegion(region, thickness, pattern, finalMask);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been changed.");
}, getArguments(context), region, context);
}
@ -735,7 +778,7 @@ public class RegionCommands {
double density) throws WorldEditException {
checkCommandArgument(0 <= density && density <= 100, "Density must be in [0, 100]");
int affected = editSession.makeForest(region, density / 100, type);
BBC.COMMAND_TREE.send(actor, affected);
actor.print(affected + " trees created.");
return affected;
}
@ -756,7 +799,7 @@ public class RegionCommands {
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density / 100));
Operations.completeLegacy(visitor);
BBC.COMMAND_FLORA.send(actor, ground.getAffected());
actor.print(affected + " flora created.");
}, "/flora", region, context);
}

View File

@ -20,7 +20,6 @@
package com.sk89q.worldedit.command;
import static com.boydti.fawe.util.ReflectionUtils.as;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.config.BBC;
@ -41,6 +40,7 @@ import com.sk89q.worldedit.command.argument.Arguments;
import com.sk89q.worldedit.command.util.AsyncCommandBuilder;
import com.sk89q.worldedit.command.util.CommandPermissions;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.ActorSaveClipboardEvent;
import com.sk89q.worldedit.extension.platform.Actor;
@ -60,6 +60,7 @@ import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.component.CodeFormat;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.util.io.Closer;
import com.sk89q.worldedit.util.io.file.FilenameException;
@ -70,6 +71,8 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import static com.google.common.base.Preconditions.checkArgument;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
@ -843,6 +846,24 @@ public class SchematicCommands {
return fileList;
}
@Command(
name = "delete",
aliases = {"d"},
desc = "Delete a saved schematic"
)
@CommandPermissions("worldedit.schematic.delete")
public void delete(Actor actor,
@Arg(desc = "File name.")
String filename) throws WorldEditException {
LocalConfiguration config = worldEdit.getConfiguration();
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
File f = worldEdit.getSafeOpenFile(actor instanceof Player ? ((Player) actor) : null,
dir, filename, "schematic", ClipboardFormats.getFileExtensionArray());
if (!f.exists()) {
actor.printError("Schematic " + filename + " does not exist!");
return;
private boolean delete(File file) {
if (file.delete()) {
new File(file.getParentFile(), "." + file.getName() + ".cached").delete();

View File

@ -18,8 +18,6 @@
*/
package com.sk89q.worldedit.command;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL;
import com.boydti.fawe.config.BBC;
@ -39,6 +37,8 @@ import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.inject.InjectedValueAccess;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Commands related to scripting.
@ -68,8 +68,8 @@ public class ScriptingCommands {
}
@Command(
name = "cs",
desc = "Execute a CraftScript"
name = "cs",
desc = "Execute a CraftScript"
)
@CommandPermissions("worldedit.scripting.execute")
@Logging(ALL)
@ -77,9 +77,9 @@ public class ScriptingCommands {
@Arg(desc = "Filename of the CraftScript to load")
String filename,
@Arg(desc = "Arguments to the CraftScript", def = "", variable = true)
List<String> commandStr) throws WorldEditException {
List<String> args) throws WorldEditException {
if (!player.hasPermission("worldedit.scripting.execute." + filename)) {
player.printError(BBC.SCRIPTING_NO_PERM.s());
player.printError("You don't have permission to use that script.");
return;
}
@ -88,19 +88,19 @@ public class ScriptingCommands {
File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().scriptsDir);
File f = worldEdit.getSafeOpenFile(player, dir, filename, "js", "js");
worldEdit.runScript(player, f, Stream.concat(Stream.of(filename), commandStr.stream())
.toArray(String[]::new));
worldEdit.runScript(player, f, Stream.concat(Stream.of(filename), args.stream())
.toArray(String[]::new));
}
@Command(
name = ".s",
desc = "Execute last CraftScript"
name = ".s",
desc = "Execute last CraftScript"
)
@CommandPermissions("worldedit.scripting.execute")
@Logging(ALL)
public void executeLast(Player player, LocalSession session,
@Arg(desc = "Arguments to the CraftScript", def = "", variable = true)
List<String> commandStr) throws WorldEditException {
List<String> args) throws WorldEditException {
String lastScript = session.getLastScript();
@ -117,7 +117,7 @@ public class ScriptingCommands {
File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().scriptsDir);
File f = worldEdit.getSafeOpenFile(player, dir, lastScript, "js", "js");
worldEdit.runScript(player, f, Stream.concat(Stream.of(lastScript), commandStr.stream())
.toArray(String[]::new));
worldEdit.runScript(player, f, Stream.concat(Stream.of(lastScript), args.stream())
.toArray(String[]::new));
}
}

View File

@ -19,6 +19,8 @@
package com.sk89q.worldedit.command;
import com.google.common.base.Strings;
import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION;
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
@ -44,6 +46,7 @@ import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Locatable;
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.annotation.Direction;
@ -77,12 +80,19 @@ import com.sk89q.worldedit.world.storage.ChunkStore;
import java.io.File;
import java.net.URI;
import java.util.List;
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
import com.sk89q.worldedit.util.formatting.component.InvalidComponentException;
import com.sk89q.worldedit.util.formatting.text.Component;
import java.util.Optional;
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import java.util.stream.Stream;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer;
import com.sk89q.worldedit.world.block.BlockType;
import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.Switch;
import org.enginehub.piston.annotation.param.ArgFlag;
import org.enginehub.piston.exception.StopExecutionException;
/**
* Selection commands.
@ -98,7 +108,6 @@ public class SelectionCommands {
@Command(
name = "/pos1",
aliases = "/1",
desc = "Set position 1"
)
@Logging(POSITION)
@ -116,18 +125,17 @@ public class SelectionCommands {
return;
}
if (!session.getRegionSelector(world).selectPrimary(pos.toBlockPoint(), ActorSelectorLimits.forActor(actor))) {
actor.printError(BBC.SELECTOR_ALREADY_SET.s());
if (!session.getRegionSelector(world).selectPrimary(pos.toVector().toBlockPoint(), ActorSelectorLimits.forActor(actor))) {
actor.printError("Position already set.");
return;
}
session.getRegionSelector(world)
.explainPrimarySelection(actor, session, pos.toBlockPoint());
.explainPrimarySelection(actor, session, pos.toVector().toBlockPoint());
}
@Command(
name = "/pos2",
aliases = "/2",
desc = "Set position 2"
)
@Logging(POSITION)
@ -145,13 +153,13 @@ public class SelectionCommands {
return;
}
if (!session.getRegionSelector(world).selectSecondary(pos.toBlockPoint(), ActorSelectorLimits.forActor(actor))) {
actor.printError(BBC.SELECTOR_ALREADY_SET.s());
if (!session.getRegionSelector(world).selectSecondary(pos.toVector().toBlockPoint(), ActorSelectorLimits.forActor(actor))) {
actor.printError("Position already set.");
return;
}
session.getRegionSelector(world)
.explainSecondarySelection(actor, session, pos.toBlockPoint());
.explainSecondarySelection(actor, session, pos.toVector().toBlockPoint());
}
@Command(
@ -204,7 +212,7 @@ public class SelectionCommands {
)
@Logging(POSITION)
@CommandPermissions("worldedit.selection.chunk")
public void chunk(Player player, LocalSession session,
public void chunk(Actor actor, World world, 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")
@ -213,7 +221,6 @@ public class SelectionCommands {
boolean useChunkCoordinates) throws WorldEditException {
final BlockVector3 min;
final BlockVector3 max;
final World world = player.getWorld();
if (expandSelection) {
Region region = session.getSelection(world);
@ -223,7 +230,9 @@ public class SelectionCommands {
min = BlockVector3.at(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
max = BlockVector3.at(max2D.getBlockX() * 16 + 15, world.getMaxY(), max2D.getBlockZ() * 16 + 15);
BBC.SELECTION_CHUNKS.send(player, min2D.getBlockX() + ", " + min2D.getBlockZ(), max2D.getBlockX() + ", " + max2D.getBlockZ());
actor.print("Chunks selected: ("
+ min2D.getBlockX() + ", " + min2D.getBlockZ() + ") - ("
+ max2D.getBlockX() + ", " + max2D.getBlockZ() + ")");
} else {
final BlockVector2 min2D;
if (coordinates != null) {
@ -233,13 +242,18 @@ public class SelectionCommands {
: ChunkStore.toChunk(coordinates.toBlockVector3());
} else {
// use player loc
min2D = ChunkStore.toChunk(player.getBlockLocation().toBlockPoint());
if (actor instanceof Locatable) {
min2D = ChunkStore.toChunk(((Locatable) actor).getBlockLocation().toVector().toBlockPoint());
} else {
throw new StopExecutionException(TextComponent.of("A player or coordinates are required."));
}
}
min = BlockVector3.at(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
max = min.add(15, world.getMaxY(), 15);
BBC.SELECTION_CHUNK.send(player, min2D.getBlockX() + ", " + min2D.getBlockZ());
actor.print("Chunk selected: "
+ min2D.getBlockX() + ", " + min2D.getBlockZ());
}
final CuboidRegionSelector selector;
@ -248,11 +262,11 @@ public class SelectionCommands {
} else {
selector = new CuboidRegionSelector(world);
}
selector.selectPrimary(min, ActorSelectorLimits.forActor(player));
selector.selectSecondary(max, ActorSelectorLimits.forActor(player));
selector.selectPrimary(min, ActorSelectorLimits.forActor(actor));
selector.selectSecondary(max, ActorSelectorLimits.forActor(actor));
session.setRegionSelector(world, selector);
session.dispatchCUISelection(player);
session.dispatchCUISelection(actor);
}
@ -333,8 +347,7 @@ public class SelectionCommands {
session.getRegionSelector(world).explainRegionAdjust(actor, session);
BBC.SELECTION_CONTRACT.send(actor, (oldSize - newSize));
actor.print("Region contracted " + (oldSize - newSize) + " blocks.");
} catch (RegionOperationException e) {
actor.printError(e.getMessage());
}
@ -363,7 +376,7 @@ public class SelectionCommands {
session.getRegionSelector(world).explainRegionAdjust(actor, session);
actor.print(BBC.SELECTION_SHIFT.s());
actor.print("Region shifted.");
} catch (RegionOperationException e) {
actor.printError(e.getMessage());
}
@ -386,7 +399,7 @@ public class SelectionCommands {
region.expand(getChangesForEachDir(amount, onlyHorizontal, onlyVertical));
session.getRegionSelector(world).learnChanges();
session.getRegionSelector(world).explainRegionAdjust(actor, session);
actor.print(BBC.SELECTION_OUTSET.s());
actor.print("Region outset.");
}
@Command(
@ -496,11 +509,11 @@ public class SelectionCommands {
desc = "Counts the number of blocks matching a mask"
)
@CommandPermissions("worldedit.analysis.count")
public void count(Player player, LocalSession session, EditSession editSession,
public void count(Actor actor, World world, LocalSession session, EditSession editSession,
@Arg(desc = "The mask of blocks to match")
Mask mask) throws WorldEditException {
int count = editSession.countBlocks(session.getSelection(player.getWorld()), mask);
BBC.SELECTION_COUNT.send(player, count);
int count = editSession.countBlocks(session.getSelection(world), mask);
actor.print("Counted: " + count);
}
@Command(
@ -531,7 +544,7 @@ public class SelectionCommands {
if (distribution.isEmpty()) { // *Should* always be false
player.printError("No blocks counted.");
actor.printError("No blocks counted.");
return;
}
@ -549,6 +562,65 @@ public class SelectionCommands {
}
}
private static class BlockDistributionResult extends PaginationBox {
private final List<Countable<BlockState>> distribution;
private final int totalBlocks;
private final boolean separateStates;
BlockDistributionResult(List<Countable<BlockState>> distribution, boolean separateStates) {
super("Block Distribution", "//distr -p %page%" + (separateStates ? " -d" : ""));
this.distribution = distribution;
// note: doing things like region.getArea is inaccurate for non-cuboids.
this.totalBlocks = distribution.stream().mapToInt(Countable::getAmount).sum();
this.separateStates = separateStates;
setComponentsPerPage(7);
}
@Override
public Component getComponent(int number) {
Countable<BlockState> c = distribution.get(number);
TextComponent.Builder line = TextComponent.builder();
final int count = c.getAmount();
final double perc = count / (double) totalBlocks * 100;
final int maxDigits = (int) (Math.log10(totalBlocks) + 1);
final int curDigits = (int) (Math.log10(count) + 1);
line.append(String.format("%s%.3f%% ", perc < 10 ? " " : "", perc), TextColor.GOLD);
final int space = maxDigits - curDigits;
String pad = Strings.repeat(" ", space == 0 ? 2 : 2 * space + 1);
line.append(String.format("%s%s", count, pad), TextColor.YELLOW);
final BlockState state = c.getID();
final BlockType blockType = state.getBlockType();
TextComponent blockName = TextComponent.of(blockType.getName(), TextColor.LIGHT_PURPLE);
TextComponent toolTip;
if (separateStates && state != blockType.getDefaultState()) {
toolTip = TextComponent.of(state.getAsString(), TextColor.GRAY);
blockName = blockName.append(TextComponent.of("*", TextColor.LIGHT_PURPLE));
} else {
toolTip = TextComponent.of(blockType.getId(), TextColor.GRAY);
}
blockName = blockName.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, toolTip));
line.append(blockName);
return line.build();
}
@Override
public int getComponentsSize() {
return distribution.size();
}
@Override
public Component create(int page) throws InvalidComponentException {
super.getContents().append(TextComponent.of("Total Block Count: " + totalBlocks, TextColor.GRAY))
.append(TextComponent.newline());
return super.create(page);
}
}
@Command(
name = "/sel",
aliases = { ";", "/desel", "/deselect" },

View File

@ -76,7 +76,7 @@ public class SnapshotCommands {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
actor.printError(BBC.SNAPSHOT_NOT_CONFIGURED.s());
actor.printError("Snapshot/backup restore is not configured.");
return;
}
@ -86,7 +86,7 @@ public class SnapshotCommands {
if (!snapshots.isEmpty()) {
actor.print(new SnapshotListBox(world.getName(), snapshots).create(page));
} else {
actor.printError(BBC.SNAPSHOT_NOT_AVAILABLE.s());
actor.printError("No snapshots are available. See console for details.");
// Okay, let's toss some debugging information!
File dir = config.snapshotRepo.getDirectory();
@ -101,7 +101,7 @@ public class SnapshotCommands {
}
}
} catch (MissingWorldException ex) {
actor.printError(BBC.SNAPSHOT_NOT_FOUND_WORLD.s());
actor.printError("No snapshots were found for this world.");
}
}
@ -117,7 +117,7 @@ public class SnapshotCommands {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
actor.printError(BBC.SNAPSHOT_NOT_CONFIGURED.s());
actor.printError("Snapshot/backup restore is not configured.");
return;
}
@ -128,19 +128,19 @@ public class SnapshotCommands {
if (snapshot != null) {
session.setSnapshot(null);
actor.print(BBC.SNAPSHOT_NEWEST.s());
actor.print("Now using newest snapshot.");
} else {
actor.printError(BBC.SNAPSHOT_NOT_FOUND.s());
actor.printError("No snapshots were found.");
}
} catch (MissingWorldException ex) {
actor.printError(BBC.SNAPSHOT_NOT_FOUND_WORLD.s());
actor.printError("No snapshots were found for this world.");
}
} else {
try {
session.setSnapshot(config.snapshotRepo.getSnapshot(name));
BBC.SNAPSHOT_SET.send(actor, name);
actor.print("Snapshot set to: " + name);
} catch (InvalidSnapshotException e) {
actor.printError(BBC.SNAPSHOT_NOT_AVAILABLE.s());
actor.printError("That snapshot does not exist or is not available.");
}
}
}
@ -156,12 +156,12 @@ public class SnapshotCommands {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
actor.printError(BBC.SNAPSHOT_NOT_CONFIGURED.s());
actor.printError("Snapshot/backup restore is not configured.");
return;
}
if (index < 1) {
actor.printError(BBC.SNAPSHOT_INVALID_INDEX.s());
actor.printError("Invalid index, must be equal or higher then 1.");
return;
}
@ -173,13 +173,13 @@ public class SnapshotCommands {
}
Snapshot snapshot = snapshots.get(index - 1);
if (snapshot == null) {
actor.printError(BBC.SNAPSHOT_NOT_AVAILABLE.s());
actor.printError("That snapshot does not exist or is not available.");
return;
}
session.setSnapshot(snapshot);
BBC.SNAPSHOT_SET.send(actor, snapshot.getName());
actor.print("Snapshot set to: " + snapshot.getName());
} catch (MissingWorldException e) {
actor.printError(BBC.SNAPSHOT_NOT_FOUND_WORLD.s());
actor.printError("No snapshots were found for this world.");
}
}
@ -195,7 +195,7 @@ public class SnapshotCommands {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
actor.printError(BBC.SNAPSHOT_NOT_CONFIGURED.s());
actor.printError("Snapshot/backup restore is not configured.");
return;
}
@ -207,10 +207,10 @@ public class SnapshotCommands {
+ dateFormat.withZone(session.getTimeZone()).format(date) + ".");
} else {
session.setSnapshot(snapshot);
BBC.SNAPSHOT_SET.send(actor, snapshot.getName());
actor.print("Snapshot set to: " + snapshot.getName());
}
} catch (MissingWorldException ex) {
actor.printError(BBC.SNAPSHOT_NOT_FOUND_WORLD.s());
actor.printError("No snapshots were found for this world.");
}
}
@ -226,7 +226,7 @@ public class SnapshotCommands {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
actor.printError(BBC.SNAPSHOT_NOT_CONFIGURED.s());
actor.printError("Snapshot/backup restore is not configured.");
return;
}
@ -240,7 +240,7 @@ public class SnapshotCommands {
actor.print("Snapshot set to: " + snapshot.getName());
}
} catch (MissingWorldException ex) {
actor.printError(BBC.SNAPSHOT_NOT_FOUND_WORLD.s());
actor.printError("No snapshots were found for this world.");
}
}

View File

@ -68,7 +68,7 @@ public class SnapshotUtilCommands {
LocalConfiguration config = we.getConfiguration();
if (config.snapshotRepo == null) {
actor.printError(BBC.SNAPSHOT_NOT_CONFIGURED.s());
actor.printError("Snapshot/backup restore is not configured.");
return;
}
@ -79,7 +79,7 @@ public class SnapshotUtilCommands {
try {
snapshot = config.snapshotRepo.getSnapshot(snapshotName);
} catch (InvalidSnapshotException e) {
actor.printError(BBC.SNAPSHOT_NOT_AVAILABLE.s());
actor.printError("That snapshot does not exist or is not available.");
return;
}
} else {
@ -92,7 +92,7 @@ public class SnapshotUtilCommands {
snapshot = config.snapshotRepo.getDefaultSnapshot(world.getName());
if (snapshot == null) {
actor.printError(BBC.SNAPSHOT_NOT_AVAILABLE.s());
actor.printError("No snapshots were found. See console for details.");
// Okay, let's toss some debugging information!
File dir = config.snapshotRepo.getDirectory();
@ -109,15 +109,21 @@ public class SnapshotUtilCommands {
return;
}
} catch (MissingWorldException ex) {
actor.printError(BBC.SNAPSHOT_NOT_FOUND_WORLD.s());
actor.printError("No snapshots were found for this world.");
return;
}
}
ChunkStore chunkStore;
// Load chunk store
try (ChunkStore chunkStore = snapshot.getChunkStore()) {
BBC.SNAPSHOT_LOADED.send(actor, snapshot.getName());
try {
chunkStore = snapshot.getChunkStore();
actor.print("Snapshot '" + snapshot.getName() + "' loaded; now restoring...");
} catch (DataException | IOException e) {
actor.printError("Failed to load snapshot: " + e.getMessage());
return;
}
// Restore snapshot
SnapshotRestore restore = new SnapshotRestore(chunkStore, editSession, region);
@ -128,12 +134,12 @@ public class SnapshotUtilCommands {
if (restore.hadTotalFailure()) {
String error = restore.getLastErrorMessage();
if (!restore.getMissingChunks().isEmpty()) {
actor.printError(BBC.SNAPSHOT_ERROR_RESTORE.s());
actor.printError("Chunks were not present in snapshot.");
} else if (error != null) {
actor.printError("Errors prevented any blocks from being restored.");
actor.printError("Last error: " + error);
} else {
actor.printError(BBC.SNAPSHOT_ERROR_RESTORE_CHUNKS.s());
actor.printError("No chunks could be loaded. (Bad archive?)");
}
} else {
actor.print(String.format("Restored; %d "
@ -143,6 +149,6 @@ public class SnapshotUtilCommands {
}
} catch (DataException | IOException e) {
actor.printError("Failed to load snapshot: " + e.getMessage());
}
}
}
}

View File

@ -19,6 +19,8 @@
package com.sk89q.worldedit.command;
import com.google.common.collect.Collections2;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.brush.InspectBrush;
import com.sk89q.worldedit.LocalConfiguration;
@ -28,6 +30,7 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.command.tool.BlockDataCyler;
import com.sk89q.worldedit.command.tool.BlockReplacer;
import com.sk89q.worldedit.command.tool.InvalidToolBindException;
import com.sk89q.worldedit.command.tool.DistanceWand;
import com.sk89q.worldedit.command.tool.FloatingTreeRemover;
import com.sk89q.worldedit.command.tool.FloodFillTool;
@ -44,27 +47,95 @@ import com.sk89q.worldedit.util.HandSide;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.world.item.ItemType;
import org.enginehub.piston.annotation.Command;
import com.sk89q.worldedit.internal.command.CommandRegistrationHandler;
import com.sk89q.worldedit.internal.command.CommandUtil;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.CommandManagerService;
import org.enginehub.piston.CommandMetadata;
import org.enginehub.piston.CommandParameters;
import org.enginehub.piston.part.SubCommandPart;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class ToolCommands {
public static void register(CommandRegistrationHandler registration,
CommandManager commandManager,
CommandManagerService commandManagerService,
WorldEdit worldEdit) {
// Collect the tool commands
CommandManager collect = commandManagerService.newCommandManager();
registration.register(
collect,
ToolCommandsRegistration.builder(),
new ToolCommands(worldEdit)
);
// Register deprecated global commands
Set<org.enginehub.piston.Command> commands = collect.getAllCommands()
.collect(Collectors.toSet());
for (org.enginehub.piston.Command command : commands) {
if (command.getAliases().contains("unbind")) {
// Don't register new /tool unbind alias
command = command.toBuilder().aliases(
Collections2.filter(command.getAliases(), alias -> !"unbind".equals(alias))
).build();
}
commandManager.register(CommandUtil.deprecate(
command, "Global tool names cause conflicts " +
"and will be removed in WorldEdit 8", ToolCommands::asNonGlobal
));
}
// Remove aliases with / in them, since it doesn't make sense for sub-commands.
Set<org.enginehub.piston.Command> nonGlobalCommands = commands.stream()
.map(command ->
command.toBuilder().aliases(
Collections2.filter(command.getAliases(), alias -> !alias.startsWith("/"))
).build()
)
.collect(Collectors.toSet());
commandManager.register("tool", command -> {
command.addPart(SubCommandPart.builder(
TranslatableComponent.of("tool"),
TextComponent.of("The tool to bind")
)
.withCommands(nonGlobalCommands)
.required()
.build());
command.description(TextComponent.of("Binds a tool to the item in your hand"));
});
}
private static String asNonGlobal(org.enginehub.piston.Command oldCommand,
CommandParameters oldParameters) {
String name = Optional.ofNullable(oldParameters.getMetadata())
.map(CommandMetadata::getCalledName)
.filter(n -> !n.startsWith("/"))
.orElseGet(oldCommand::getName);
return "/tool " + name;
}
static void setToolNone(Player player, LocalSession session, String type)
throws InvalidToolBindException {
session.setTool(player.getItemInHand(HandSide.MAIN_HAND).getType(), null);
player.print(type + " unbound from your current item.");
}
private final WorldEdit we;
public ToolCommands(WorldEdit we) {
this.we = we;
}
// @Command(
// name = "none",
// desc = "Unbind a bound tool from your current item"
// )
// public void none(Player player, LocalSession session) throws WorldEditException {
//
// session.setTool(player.getItemInHand(HandSide.MAIN_HAND).getType(), null);
// player.print("Tool unbound from your current item.");
// }
@Command(
name = "selwand",
aliases = "/selwand",
@ -74,7 +145,7 @@ public class ToolCommands {
public void selwand(Player player, LocalSession session) throws WorldEditException {
final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType();
session.setTool(player, SelectionWand.INSTANCE);
session.setTool(itemType, new SelectionWand());
player.print("Selection wand bound to " + itemType.getName() + ".");
}
@ -215,8 +286,17 @@ public class ToolCommands {
Pattern secondary) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(player, new LongRangeBuildTool(primary, secondary));
BBC.TOOL_LRBUILD_BOUND.send(player, itemStack.getType().getName());
BBC.TOOL_LRBUILD_INFO.send(player, secondary, primary);
session.setTool(itemStack.getType(), new LongRangeBuildTool(primary, secondary));
player.print("Long-range building tool bound to " + itemStack.getType().getName() + ".");
String primaryName = "pattern";
String secondaryName = "pattern";
if (primary instanceof BlockStateHolder) {
primaryName = ((BlockStateHolder<?>) primary).getBlockType().getName();
}
if (secondary instanceof BlockStateHolder) {
secondaryName = ((BlockStateHolder<?>) secondary).getBlockType().getName();
}
player.print("Left-click set to " + primaryName + "; right-click set to "
+ secondaryName + ".");
}
}

View File

@ -82,16 +82,16 @@ public class ToolUtilCommands {
return;
}
if (maskOpt == null) {
player.print(BBC.BRUSH_MASK_DISABLED.s());
player.print("Brush mask disabled.");
tool.setMask(null);
return;
}
}
BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext();
String lastArg = Iterables.getLast(CommandArgParser.spaceSplit(arguments.get())).getSubstring();
settings.addSetting(BrushSettings.SettingType.MASK, lastArg);
settings.setMask(maskOpt);
tool.update();
player.print(BBC.BRUSH_MASK.s());
player.print("Brush mask set.");
}
@Command(
@ -110,7 +110,7 @@ public class ToolUtilCommands {
if (tool == null) {
player.print(BBC.BRUSH_NONE.s());
return;
}
}
if (pattern == null) {
player.print(BBC.BRUSH_MATERIAL.s());
tool.setFill(null);
@ -125,61 +125,29 @@ public class ToolUtilCommands {
}
@Command(
name = "range",
desc = "Set the brush range"
)
name = "range",
desc = "Set the brush range"
)
@CommandPermissions("worldedit.brush.options.range")
public void range(Player player, LocalSession session,
@Arg(desc = "The range of the brush")
int range) throws WorldEditException {
range = Math.max(0, Math.min(256, range));
BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {
player.print(BBC.BRUSH_NONE.s());
return;
}
tool.setRange(range);
player.print(BBC.BRUSH_RANGE.s());
int range) throws WorldEditException {
session.getBrushTool(player, false).setRange(range);
player.print("Brush range set.");
}
@Command(
name = "size",
desc = "Set the brush size"
name = "size",
desc = "Set the brush size"
)
@CommandPermissions("worldedit.brush.options.size")
public void size(Player player, LocalSession session,
@Arg(desc = "The size of the brush", def = "5")
int size,
@Switch(name = 'h', desc = "TODO")
boolean offHand) throws WorldEditException {
@Arg(desc = "The size of the brush")
int size) throws WorldEditException {
we.checkMaxBrushRadius(size);
BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {
player.print(BBC.BRUSH_NONE.s());
return;
}
BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext();
settings.setSize(size);
tool.update();
player.print(BBC.BRUSH_SIZE.s());
}
@Command(
name = "tracemask",
aliases = {"tarmask", "tm", "targetmask"},
desc = "Set the mask used to stop tool traces"
)
@CommandPermissions("worldedit.brush.options.tracemask")
public void traceMask(Player player, LocalSession session,
@Arg(desc = "The trace mask to set", def = "")
Mask maskOpt) throws WorldEditException {
BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {
player.print(BBC.BRUSH_NONE.s());
return;
}
tool.setTraceMask(maskOpt);
BBC.BRUSH_TARGET_MASK_SET.send(player, maskOpt.toString());
session.getBrushTool(player, false).setSize(size);
player.print("Brush size set.");
}
//todo none should be moved to the same class where it is in upstream
@ -194,28 +162,42 @@ public class ToolUtilCommands {
}
@Command(
name = "/superpickaxe",
aliases = {",", "/sp", "/pickaxe"},
desc = "Toggle the super pickaxe function"
name = "tracemask",
aliases = {"tarmask", "tm", "targetmask"},
desc = "Set the mask used to stop tool traces"
)
@CommandPermissions("worldedit.brush.options.tracemask")
public void traceMask(Player player, LocalSession session,
@Arg(desc = "The trace mask to set", def = "")
Mask maskOpt) throws WorldEditException {
session.getBrushTool(player, false).setTraceMask(maskOpt);
if (maskOpt == null) {
player.print("Trace mask disabled.");
} else {
player.print("Trace mask set.");
}
}
@Command(
name = "/",
aliases = { "," },
desc = "Toggle the super pickaxe function"
)
@CommandPermissions("worldedit.superpickaxe")
public void togglePickaxe(Player player, LocalSession session,
@Arg(desc = "state", def = "on") String state) throws WorldEditException {
if (session.hasSuperPickAxe()) {
if ("on".equals(state)) {
player.print(BBC.SUPERPICKAXE_ENABLED.s());
@Arg(desc = "The new super pickaxe state", def = "")
Boolean superPickaxe) {
boolean hasSuperPickAxe = session.hasSuperPickAxe();
if (superPickaxe != null && superPickaxe == hasSuperPickAxe) {
player.printError("Super pickaxe already " + (superPickaxe ? "enabled" : "disabled") + ".");
return;
}
if (hasSuperPickAxe) {
session.disableSuperPickAxe();
player.print(BBC.SUPERPICKAXE_DISABLED.s());
player.print("Super pickaxe disabled.");
} else {
if ("off".equals(state)) {
player.print(BBC.SUPERPICKAXE_DISABLED.s());
return;
}
session.enableSuperPickAxe();
player.print(BBC.SUPERPICKAXE_ENABLED.s());
player.print("Super pickaxe enabled.");
}
}

View File

@ -30,7 +30,6 @@ import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.image.ImageUtil;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalConfiguration;
@ -46,21 +45,23 @@ import com.sk89q.worldedit.command.util.Logging;
import com.sk89q.worldedit.command.util.PrintCommandHelp;
import com.sk89q.worldedit.command.util.SkipQueue;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.function.EntityFunction;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
import com.sk89q.worldedit.function.visitor.EntityVisitor;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Range;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import java.text.DecimalFormat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.CylinderRegion;
@ -77,7 +78,6 @@ import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.AbstractMap;
import java.util.ArrayList;
@ -99,7 +99,8 @@ import org.enginehub.piston.annotation.param.Switch;
/**
* Utility commands.
*/
@CommandContainer(superTypes = {
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class UtilityCommands {
// CommandQueuedConditionGenerator.Registration.class,
CommandPermissionsConditionGenerator.Registration.class // TODO NOT IMPLEMENTED - Piston doesn't seem to work with multiple conditions???
})
@ -193,6 +194,7 @@ public class UtilityCommands {
@Command(
name = "/fill",
desc = "Fill a hole"
)
@CommandPermissions("worldedit.fill")
@Logging(PLACEMENT)
@ -218,6 +220,8 @@ public class UtilityCommands {
/*
@Command(
name = "/fillr",
desc = "Fill a hole recursively"
name = "patterns",
desc = "View help about patterns",
descFooter = "Patterns determine what blocks are placed\n" +
@ -296,10 +300,10 @@ public class UtilityCommands {
public int fillr(Actor actor, LocalSession session, EditSession editSession,
@Arg(desc = "The blocks to fill with")
Pattern pattern,
@Range(min=1) @Arg(desc = "The radius to fill in")
@Arg(desc = "The radius to fill in")
Expression radiusExp,
@Arg(desc = "The depth to fill", def = "")
Integer depth) throws WorldEditException, EvaluationException {
Integer depth) throws WorldEditException {
double radius = radiusExp.evaluate();
radius = Math.max(1, radius);
we.checkMaxRadius(radius);
@ -319,10 +323,10 @@ public class UtilityCommands {
@CommandPermissions("worldedit.drain")
@Logging(PLACEMENT)
public int drain(Actor actor, LocalSession session, EditSession editSession,
@Range(min=0) @Arg(desc = "The radius to drain")
@Arg(desc = "The radius to drain")
Expression radiusExp,
@Switch(name = 'w', desc = "Also un-waterlog blocks")
boolean waterlogged) throws WorldEditException, EvaluationException {
boolean waterlogged) throws WorldEditException {
double radius = radiusExp.evaluate();
radius = Math.max(0, radius);
we.checkMaxRadius(radius);
@ -340,9 +344,8 @@ public class UtilityCommands {
@CommandPermissions("worldedit.fixlava")
@Logging(PLACEMENT)
public int fixLava(Actor actor, LocalSession session, EditSession editSession,
@Range(min=0) @Arg(desc = "The radius to fix in")
Expression radiusExp) throws WorldEditException, EvaluationException {
double radius = radiusExp.evaluate();
@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(actor), radius, BlockTypes.LAVA);
@ -358,13 +361,12 @@ public class UtilityCommands {
@CommandPermissions("worldedit.fixwater")
@Logging(PLACEMENT)
public int fixWater(Actor actor, LocalSession session, EditSession editSession,
@Range(min=0) @Arg(desc = "The radius to fix in")
Expression radiusExp) throws WorldEditException, EvaluationException {
double radius = radiusExp.evaluate();
@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(actor), radius, BlockTypes.WATER);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been changed.");
return affected;
}
@ -376,15 +378,16 @@ public class UtilityCommands {
@CommandPermissions("worldedit.removeabove")
@Logging(PLACEMENT)
public int removeAbove(Actor actor, World world, LocalSession session, EditSession editSession,
@Range(min=1) @Arg(name = "size", desc = "The apothem of the square to remove from", def = "1")
@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);
height = height != null ? Math.min((world.getMaxY() + 1), height + 1) : (world.getMaxY() + 1);
int affected = editSession.removeAbove(session.getPlacementPosition(actor), size, height);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been removed.");
return affected;
}
@ -396,7 +399,7 @@ public class UtilityCommands {
@CommandPermissions("worldedit.removebelow")
@Logging(PLACEMENT)
public int removeBelow(Actor actor, World world, LocalSession session, EditSession editSession,
@Arg(name = "size", desc = "The apothem of the square to remove from", def = "1")
@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 {
@ -405,7 +408,7 @@ public class UtilityCommands {
height = height != null ? Math.min((world.getMaxY() + 1), height + 1) : (world.getMaxY() + 1);
int affected = editSession.removeBelow(session.getPlacementPosition(actor), size, height);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been removed.");
return affected;
}
@ -419,25 +422,25 @@ public class UtilityCommands {
public int removeNear(Actor actor, LocalSession session, EditSession editSession,
@Arg(desc = "The mask of blocks to remove")
Mask mask,
@Range(min=1) @Arg(desc = "The radius of the square to remove from", def = "50")
@Arg(desc = "The radius of the square to remove from", def = "50")
int radius) throws WorldEditException {
radius = Math.max(1, radius);
we.checkMaxRadius(radius);
int affected = editSession.removeNear(session.getPlacementPosition(actor), mask, radius);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been removed.");
return affected;
}
@Command(
name = "replacenear",
aliases = { "/replacenear", "/rn" },
aliases = { "/replacenear" },
desc = "Replace nearby blocks"
)
@CommandPermissions("worldedit.replacenear")
@Logging(PLACEMENT)
public int replaceNear(Actor actor, World world, LocalSession session, EditSession editSession,
@Range(min=1) @Arg(desc = "The radius of the square to remove in")
@Arg(desc = "The radius of the square to remove in")
int radius,
@Arg(desc = "The mask matching blocks to remove", def = "")
Mask from,
@ -456,7 +459,7 @@ public class UtilityCommands {
}
int affected = editSession.replaceBlocks(region, from, to);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been replaced.");
return affected;
}
@ -468,7 +471,7 @@ public class UtilityCommands {
@CommandPermissions("worldedit.snow")
@Logging(PLACEMENT)
public int snow(Actor actor, LocalSession session, EditSession editSession,
@Range(min=1) @Arg(desc = "The radius of the circle to snow in", def = "10")
@Arg(desc = "The radius of the circle to snow in", def = "10")
double size) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size);
@ -486,7 +489,7 @@ public class UtilityCommands {
@CommandPermissions("worldedit.thaw")
@Logging(PLACEMENT)
public int thaw(Actor actor, LocalSession session, EditSession editSession,
@Range(min=1) @Arg(desc = "The radius of the circle to thaw in", def = "10")
@Arg(desc = "The radius of the circle to thaw in", def = "10")
double size) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size);
@ -504,7 +507,7 @@ public class UtilityCommands {
@CommandPermissions("worldedit.green")
@Logging(PLACEMENT)
public int green(Actor actor, LocalSession session, EditSession editSession,
@Range(min=1) @Arg(desc = "The radius of the circle to convert in", def = "10")
@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 {
@ -513,10 +516,37 @@ public class UtilityCommands {
final boolean onlyNormalDirt = !convertCoarse;
final int affected = editSession.green(session.getPlacementPosition(actor), size, onlyNormalDirt);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " surface(s) greened.");
return affected;
}
private int killMatchingEntities(Integer radius, Actor actor, Supplier<EntityFunction> func) throws IncompleteRegionException,
MaxChangedBlocksException {
List<EntityVisitor> visitors = new ArrayList<>();
LocalSession session = we.getSessionManager().get(actor);
BlockVector3 center = session.getPlacementPosition(actor);
EditSession editSession = session.createEditSession(actor);
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(), func.get()));
int killed = 0;
for (EntityVisitor visitor : visitors) {
Operations.completeLegacy(visitor);
killed += visitor.getAffected();
}
session.remember(editSession);
editSession.flushSession();
return killed;
}
@Command(
name = "extinguish",
aliases = { "/ex", "/ext", "/extinguish", "ex", "ext" },
@ -525,7 +555,7 @@ public class UtilityCommands {
@CommandPermissions("worldedit.extinguish")
@Logging(PLACEMENT)
public void extinguish(Actor actor, LocalSession session, EditSession editSession,
@Range(min=1) @Arg(desc = "The radius of the square to remove in", def = "")
@Arg(desc = "The radius of the square to remove in", def = "")
Integer radius) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
@ -534,9 +564,9 @@ public class UtilityCommands {
int size = radius != null ? Math.max(1, radius) : defaultRadius;
we.checkMaxRadius(size);
Mask mask = BlockTypes.FIRE.toMask();
Mask mask = new BlockTypeMask(editSession, BlockTypes.FIRE);
int affected = editSession.removeNear(session.getPlacementPosition(actor), mask, size);
BBC.VISITOR_BLOCK.send(actor, affected);
actor.print(affected + " block(s) have been removed.");
}
@Command(
@ -597,6 +627,22 @@ public class UtilityCommands {
return killed;
}
@Command(
name = "/help",
desc = "Displays help for WorldEdit commands"
)
@CommandPermissions("worldedit.help")
public void help(Actor actor,
@Switch(name = 's', desc = "List sub-commands of the given command, if applicable")
boolean listSubCommands,
@ArgFlag(name = 'p', 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, listSubCommands,
we.getPlatformManager().getPlatformCommandManager().getCommandManager(), actor, "//help");
}
@Command(
name = "remove",
aliases = { "rem", "rement" },
@ -607,9 +653,8 @@ public class UtilityCommands {
public int remove(Actor actor,
@Arg(desc = "The type of entity to remove")
EntityRemover remover,
@Range(min=-1) @Arg(desc = "The radius of the cuboid to remove from")
@Arg(desc = "The radius of the cuboid to remove from")
int radius) throws WorldEditException {
if (radius < -1) {
actor.printError("Use -1 to remove all entities in loaded chunks");
return 0;
@ -621,34 +666,6 @@ public class UtilityCommands {
return removed;
}
private int killMatchingEntities(Integer radius, Actor actor, Supplier<EntityFunction> func) throws IncompleteRegionException, MaxChangedBlocksException {
List<EntityVisitor> visitors = new ArrayList<>();
LocalSession session = we.getSessionManager().get(actor);
BlockVector3 center = session.getPlacementPosition(actor);
EditSession editSession = session.createEditSession(actor);
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(), func.get()));
int killed = 0;
for (EntityVisitor visitor : visitors) {
Operations.completeLegacy(visitor);
killed += visitor.getAffected();
}
BBC.KILL_SUCCESS.send(actor, killed, radius);
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 {
@ -663,7 +680,7 @@ public class UtilityCommands {
@CommandPermissions("worldedit.calc")
public void calc(Actor actor,
@Arg(desc = "Expression to evaluate", variable = true)
List<String> input) throws EvaluationException {
List<String> input) {
Expression expression;
try {
expression = Expression.compile(String.join(" ", input));
@ -672,11 +689,12 @@ public class UtilityCommands {
"'%s' could not be parsed as a valid expression", input));
return;
}
double result = expression.evaluate(
new double[]{}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout());
String formatted = Double.isNaN(result) ? "NaN" : formatter.format(result);
TextComponent msg = SubtleFormat.wrap(input + " = ").append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE));
actor.print(msg);
WorldEditAsyncCommandBuilder.createAndSendMessage(actor, () -> {
double result = expression.evaluate(
new double[]{}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout());
String formatted = Double.isNaN(result) ? "NaN" : formatter.format(result);
return SubtleFormat.wrap(input + " = ").append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE));
}, null);
}
@Command(
@ -690,22 +708,6 @@ public class UtilityCommands {
}
}
@Command(
name = "/help",
desc = "Displays help for WorldEdit commands"
)
@CommandPermissions("worldedit.help")
public void help(Actor actor,
@Switch(name = 's', desc = "List sub-commands of the given command, if applicable")
boolean listSubCommands,
@ArgFlag(name = 'p', desc = "The page to retrieve", def = "1")
int page,
@Arg(desc = "The command to retrieve help for", def = "", variable = true)
List<String> commandStr) throws WorldEditException {
PrintCommandHelp.help(commandStr, page, listSubCommands,
we.getPlatformManager().getPlatformCommandManager().getCommandManager(), actor, "//help");
}
public static List<Map.Entry<URI, String>> filesToEntry(final File root, final List<File> files, final UUID uuid) {
return Lists.transform(files, input -> { // Keep this functional, as transform is evaluated lazily
URI uri = input.toURI();

View File

@ -56,11 +56,9 @@ import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.ArgFlag;
import org.enginehub.piston.annotation.param.Switch;
@CommandContainer(superTypes = {CommandPermissionsConditionGenerator.Registration.class, CommandQueuedConditionGenerator.Registration.class})
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class WorldEditCommands {
private static final DateTimeFormatter dateFormat = DateTimeFormatter
.ofPattern("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;
@ -174,11 +172,10 @@ public class WorldEditCommands {
try {
ZoneId tz = ZoneId.of(timezone);
session.setTimezone(tz);
BBC.TIMEZONE_SET.send(actor, tz.getDisplayName(
TextStyle.FULL, Locale.ENGLISH
actor.print("Timezone set for this session to: " + tz.getDisplayName(
TextStyle.FULL, Locale.ENGLISH
));
BBC.TIMEZONE_DISPLAY
.send(actor, dateFormat.format(ZonedDateTime.now(tz)));
actor.print("The current time in that timezone is: " + dateFormat.format(ZonedDateTime.now(tz)));
} catch (ZoneRulesException e) {
actor.printError("Invalid timezone");
}
@ -186,7 +183,7 @@ public class WorldEditCommands {
@Command(
name = "help",
desc = "Displays help for FAWE commands"
desc = "Displays help for WorldEdit commands"
)
@SkipQueue
@CommandPermissions("worldedit.help")
@ -196,8 +193,8 @@ public class WorldEditCommands {
@ArgFlag(name = 'p', desc = "The page to retrieve", def = "1")
int page,
@Arg(desc = "The command to retrieve help for", def = "", variable = true)
List<String> commandStr) throws WorldEditException {
PrintCommandHelp.help(commandStr, page, listSubCommands,
we.getPlatformManager().getPlatformCommandManager().getCommandManager(), actor, "/worldedit help");
List<String> command) throws WorldEditException {
PrintCommandHelp.help(command, page, listSubCommands,
we.getPlatformManager().getPlatformCommandManager().getCommandManager(), actor, "/worldedit help");
}
}

View File

@ -19,20 +19,21 @@
package com.sk89q.worldedit.command.argument;
import static com.google.common.base.Preconditions.checkArgument;
import static com.sk89q.worldedit.util.formatting.text.TextComponent.space;
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 java.util.List;
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.TextComponent.space;
public class CommaSeparatedValuesConverter<T> implements ArgumentConverter<T> {
public static <T> CommaSeparatedValuesConverter<T> wrap(ArgumentConverter<T> delegate) {

View File

@ -28,12 +28,13 @@ 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 static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
import java.util.List;
import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix;
public class EntityRemoverConverter implements ArgumentConverter<EntityRemover> {
public static void register(CommandManager commandManager) {

View File

@ -66,8 +66,8 @@ public class AreaPickaxe implements BlockTool {
try {
for (int x = ox - range; x <= ox + range; ++x) {
for (int z = oz - range; z <= oz + range; ++z) {
for (int y = oy + range; y >= oy - range; --y) {
for (int y = oy - range; y <= oy + range; ++y) {
for (int z = oz - range; z <= oz + range; ++z) {
if (initialType.equals(editSession.getBlock(x, y, z))) {
continue;
}

View File

@ -70,7 +70,6 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BlockType;
@ -437,7 +436,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
return act(BrushAction.PRIMARY, player, session);
}
}
public BlockVector3 getPosition(EditSession editSession, Player player) {
Location loc = player.getLocation();

View File

@ -23,7 +23,6 @@ import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
import com.sk89q.worldedit.function.mask.Mask;
@ -40,11 +39,6 @@ public class DistanceWand extends BrushTool implements DoubleActionTraceTool {
super("worldedit.selection.pos");
}
@Override
public boolean canUse(Actor player) {
return player.hasPermission("worldedit.wand");
}
@Override
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
Location target = getTarget(player);
@ -74,8 +68,7 @@ public class DistanceWand extends BrushTool implements DoubleActionTraceTool {
private Location getTarget(Player player) {
Location target;
Mask mask = getTraceMask();
int range = getRange();
if (range < MAX_RANGE) {
if (this.range > -1) {
target = player.getBlockTrace(getRange(), true, mask);
} else {
target = player.getBlockTrace(MAX_RANGE, false, mask);

View File

@ -118,7 +118,7 @@ public class FloatingTreeRemover implements BlockTool {
* @param origin any point contained in the floating tree
* @return a set containing all blocks in the tree/shroom or null if this is not a floating tree/shroom.
*/
private Set<BlockVector3> bfs(World world, BlockVector3 origin) throws MaxChangedBlocksException {
private Set<BlockVector3> bfs(World world, BlockVector3 origin) {
final LocalBlockVectorSet visited = new LocalBlockVectorSet();
final LocalBlockVectorSet queue = new LocalBlockVectorSet();

View File

@ -27,6 +27,7 @@ import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
@ -56,39 +57,56 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
Location pos = getTargetFace(player);
if (pos == null) return false;
try (EditSession eS = session.createEditSession(player)) {
BlockBag bag = session.getBlockBag(player);
try (EditSession editSession = session.createEditSession(player)) {
try {
editSession.disableBuffering();
BlockVector3 blockPoint = pos.toVector().toBlockPoint();
BaseBlock applied = secondary.apply(blockPoint);
if (applied.getBlockType().getMaterial().isAir()) {
eS.setBlock(blockPoint, secondary);
editSession.setBlock(blockPoint, secondary);
} else {
eS.setBlock(pos.toVector().subtract(pos.getDirection()).toBlockPoint(), secondary);
editSession.setBlock(pos.toVector().subtract(pos.getDirection()).toBlockPoint(), secondary);
}
} catch (MaxChangedBlocksException ignored) {
} finally {
session.remember(editSession);
}
return true;
} catch (MaxChangedBlocksException ignored) {
// one block? eat it
} finally {
if (bag != null) {
bag.flushChanges();
}
return false;
}
return true;
}
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
Location pos = getTargetFace(player);
if (pos == null) return false;
try (EditSession eS = session.createEditSession(player)) {
BlockBag bag = session.getBlockBag(player);
try (EditSession editSession = session.createEditSession(player)) {
try {
editSession.disableBuffering();
BlockVector3 blockPoint = pos.toVector().toBlockPoint();
BaseBlock applied = primary.apply(blockPoint);
if (applied.getBlockType().getMaterial().isAir()) {
eS.setBlock(blockPoint, primary);
editSession.setBlock(blockPoint, primary);
} else {
eS.setBlock(pos.toVector().subtract(pos.getDirection()).toBlockPoint(), primary);
editSession.setBlock(pos.toVector().subtract(pos.getDirection()).toBlockPoint(), primary);
}
} catch (MaxChangedBlocksException ignored) {
} finally {
session.remember(editSession);
}
return true;
} catch (MaxChangedBlocksException ignored) {
// one block? eat it
} finally {
if (bag != null) {
bag.flushChanges();
}
return false;
}
return true;
}
private Location getTargetFace(Player player) {
@ -99,6 +117,7 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo
} else {
target = player.getBlockTrace(MAX_RANGE, false, mask);
}
if (target == null) {
player.printError(BBC.NO_BLOCK.s());
return null;

View File

@ -24,6 +24,7 @@ import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.Location;
@ -33,6 +34,8 @@ import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import java.util.OptionalInt;
/**
* Looks up information about a block.
*/

View File

@ -84,4 +84,36 @@ public class RecursivePickaxe implements BlockTool {
return true;
}
private static void recurse(Platform server, EditSession editSession, World world, BlockVector3 pos,
BlockVector3 origin, double size, BlockType initialType, Set<BlockVector3> visited) throws MaxChangedBlocksException {
final double distanceSq = origin.distanceSq(pos);
if (distanceSq > size*size || visited.contains(pos)) {
return;
}
visited.add(pos);
if (editSession.getBlock(pos).getBlockType() != initialType) {
return;
}
editSession.setBlock(pos, BlockTypes.AIR.getDefaultState());
world.queueBlockBreakEffect(server, pos, initialType, distanceSq);
recurse(server, editSession, world, pos.add(1, 0, 0),
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(-1, 0, 0),
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 0, 1),
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 0, -1),
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 1, 0),
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, -1, 0),
origin, size, initialType, visited);
}
}

View File

@ -44,7 +44,7 @@ public class ClipboardBrush implements Brush {
this.ignoreAirBlocks = ignoreAirBlocks;
this.usingOrigin = usingOrigin;
this.pasteBiomes = false;
this.pasteEntities = true;
this.pasteEntities = false;
this.sourceMask = null;
}

View File

@ -23,7 +23,12 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.util.LocatedBlock;
import java.util.LinkedHashSet;
import java.util.Set;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.util.collection.LocatedBlockList;
import com.sk89q.worldedit.world.block.BlockTypes;
public class GravityBrush implements Brush {
@ -48,12 +53,15 @@ public class GravityBrush implements Brush {
if (y != freeSpot) {
editSession.setBlock((int)x, (int)y, (int)z, BlockTypes.AIR.getDefaultState());
editSession.setBlock((int)x, (int)freeSpot, (int)z, block);
}
}
freeSpot = y + 1;
}
}
}
column.clear();
removedBlocks.clear();
}
}
}
}

View File

@ -19,8 +19,6 @@
package com.sk89q.worldedit.command.util;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
@ -42,6 +40,9 @@ import javax.annotation.Nullable;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
public final class AsyncCommandBuilder<T> {
private static final Logger logger = LoggerFactory.getLogger(AsyncCommandBuilder.class);

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.command.util;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableSet;
import org.enginehub.piston.Command;
import org.enginehub.piston.gen.CommandConditionGenerator;
@ -28,6 +27,8 @@ 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 {

View File

@ -20,12 +20,12 @@
package com.sk89q.worldedit.command.util;
import com.boydti.fawe.util.TaskManager;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.entity.metadata.EntityProperties;
import com.sk89q.worldedit.function.EntityFunction;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.regex.Pattern;
/**

View File

@ -24,8 +24,6 @@ import org.enginehub.piston.Command;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
import java.lang.annotation.Annotation;
import java.util.Optional;
import java.util.Set;
public class PermissionCondition implements Command.Condition {

View File

@ -303,14 +303,6 @@ public interface Player extends Entity, Actor {
*/
void setPosition(Vector3 pos, float pitch, float yaw);
/**
* Move the player.
*
* @param pos where to move them
*/
@Override
void setPosition(Vector3 pos);
/**
* Sends a fake block to the client.
*

View File

@ -18,8 +18,6 @@
*/
package com.sk89q.worldedit.event.platform;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.event.Event;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.util.Substring;
@ -27,6 +25,8 @@ import com.sk89q.worldedit.internal.util.Substring;
import java.util.Collections;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Posted when suggestions for auto-completion are requested for command input.
*/

View File

@ -32,6 +32,7 @@ import com.sk89q.worldedit.internal.registry.InputParser;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* A registry of known {@link Mask}s. Provides methods to instantiate
@ -48,19 +49,36 @@ public final class MaskFactory extends AbstractFactory<Mask> {
* @param worldEdit the WorldEdit instance
*/
public MaskFactory(WorldEdit worldEdit) {
super(worldEdit, new DefaultMaskParser(worldEdit));
super(worldEdit, new DefaultMaskParser(worldEdit));
/*
super(worldEdit, new BlocksMaskParser(worldEdit));
// register(new ExistingMaskParser(worldEdit));
// register(new SolidMaskParser(worldEdit));
// register(new LazyRegionMaskParser(worldEdit));
// register(new RegionMaskParser(worldEdit));
// register(new OffsetMaskParser(worldEdit));
// register(new NoiseMaskParser(worldEdit));
// register(new BlockStateMaskParser(worldEdit));
// register(new NegateMaskParser(worldEdit));
// register(new ExpressionMaskParser(worldEdit));
register(new BlockCategoryMaskParser(worldEdit)); // TODO implement in DefaultMaskParser
// register(new BiomeMaskParser(worldEdit));
register(new ExistingMaskParser(worldEdit));
register(new SolidMaskParser(worldEdit));
register(new LazyRegionMaskParser(worldEdit));
register(new RegionMaskParser(worldEdit));
register(new OffsetMaskParser(worldEdit));
register(new NoiseMaskParser(worldEdit));
register(new BlockStateMaskParser(worldEdit));
register(new NegateMaskParser(worldEdit));
register(new ExpressionMaskParser(worldEdit));
*/
register(new BlockCategoryMaskParser(worldEdit));
/*
register(new BiomeMaskParser(worldEdit));
*/
}
@Override
public List<String> getSuggestions(String input) {
final String[] split = input.split(" ");
if (split.length > 1) {
String prev = input.substring(0, input.lastIndexOf(" ")) + " ";
return super.getSuggestions(split[split.length -1]).stream().map(s -> prev + s).collect(Collectors.toList());
}
return super.getSuggestions(input);
}
@Override

View File

@ -40,16 +40,19 @@ public final class PatternFactory extends AbstractFactory<Pattern> {
* @param worldEdit the WorldEdit instance
*/
public PatternFactory(WorldEdit worldEdit) {
super(worldEdit, new DefaultPatternParser(worldEdit));
super(worldEdit, new DefaultPatternParser(worldEdit));
/*
super(worldEdit, new SingleBlockPatternParser(worldEdit));
// split and parse each sub-pattern
// register(new RandomPatternParser(worldEdit));
register(new RandomPatternParser(worldEdit));
// individual patterns
// register(new ClipboardPatternParser(worldEdit));
// register(new TypeOrStateApplyingPatternParser(worldEdit));
// register(new RandomStatePatternParser(worldEdit));
register(new BlockCategoryPatternParser(worldEdit)); // TODO implement in pattern parser
register(new ClipboardPatternParser(worldEdit));
register(new TypeOrStateApplyingPatternParser(worldEdit));
register(new RandomStatePatternParser(worldEdit));
*/
register(new BlockCategoryPatternParser(worldEdit));
}
}

View File

@ -19,6 +19,8 @@
package com.sk89q.worldedit.extension.factory.parser;
import com.google.common.collect.Maps;
import com.boydti.fawe.command.SuggestInputParseException;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.jnbt.JSON2NBT;
@ -35,7 +37,7 @@ import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.MobSpawnerBlock;
import com.sk89q.worldedit.blocks.SignBlock;
import com.sk89q.worldedit.blocks.SkullBlock;
import com.sk89q.worldedit.blocks.metadata.MobType;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.DisallowedUsageException;
import com.sk89q.worldedit.extension.input.InputParseException;
@ -61,6 +63,8 @@ import com.sk89q.worldedit.world.registry.LegacyMapper;
import java.util.Arrays;
import java.util.Locale;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -111,6 +115,8 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
}
}
private static String[] EMPTY_STRING_ARRAY = {};
/**
* Backwards compatibility for wool colours in block syntax.
*
@ -162,6 +168,71 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
}
}
private static Map<Property<?>, Object> parseProperties(BlockType type, String[] stateProperties, ParserContext context) throws NoMatchException {
Map<Property<?>, Object> blockStates = new HashMap<>();
if (stateProperties.length > 0) { // Block data not yet detected
// Parse the block data (optional)
for (String parseableData : stateProperties) {
try {
String[] parts = parseableData.split("=");
if (parts.length != 2) {
throw new NoMatchException("Bad state format in " + parseableData);
}
@SuppressWarnings("unchecked")
Property<Object> propertyKey = (Property<Object>) type.getPropertyMap().get(parts[0]);
if (propertyKey == null) {
if (context.getActor() != null) {
throw new NoMatchException("Unknown property " + parts[0] + " for block " + type.getId());
} else {
WorldEdit.logger.warn("Unknown property " + parts[0] + " for block " + type.getId());
}
return Maps.newHashMap();
}
if (blockStates.containsKey(propertyKey)) {
throw new NoMatchException("Duplicate property " + parts[0]);
}
Object value;
try {
value = propertyKey.getValueFor(parts[1]);
} catch (IllegalArgumentException e) {
throw new NoMatchException("Unknown value " + parts[1] + " for state " + parts[0]);
}
blockStates.put(propertyKey, value);
} catch (NoMatchException e) {
throw e; // Pass-through
} catch (Exception e) {
WorldEdit.logger.warn("Unknown state '" + parseableData + "'", e);
throw new NoMatchException("Unknown state '" + parseableData + "'");
}
}
}
return blockStates;
}
@Override
public Stream<String> getSuggestions(String input) {
final int idx = input.lastIndexOf('[');
if (idx < 0) {
return SuggestionHelper.getNamespacedRegistrySuggestions(BlockType.REGISTRY, input);
}
String blockType = input.substring(0, idx);
BlockType type = BlockTypes.get(blockType.toLowerCase(Locale.ROOT));
if (type == null) {
return Stream.empty();
}
String props = input.substring(idx + 1);
if (props.isEmpty()) {
return type.getProperties().stream().map(p -> input + p.getName() + "=");
}
return SuggestionHelper.getBlockPropertySuggestions(blockType, props);
}
private BaseBlock parseLogic(String input, ParserContext context) throws InputParseException {
String[] blockAndExtraData = input.trim().split("\\|", 2);
blockAndExtraData[0] = woolMapper(blockAndExtraData[0]);
@ -193,7 +264,7 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
state = LegacyMapper.getInstance().getBlockFromLegacy(type.getLegacyCombinedId() >> 4, data);
}
}
} catch (NumberFormatException e) {
} catch (NumberFormatException ignored) {
}
}
@ -206,6 +277,13 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
typeString = blockAndExtraData[0];
} else {
typeString = blockAndExtraData[0].substring(0, stateStart);
if (stateStart + 1 >= blockAndExtraData[0].length()) {
throw new InputParseException("Invalid format. Hanging bracket @ " + stateStart + ".");
}
int stateEnd = blockAndExtraData[0].lastIndexOf(']');
if (stateEnd < 0) {
throw new InputParseException("Invalid format. Unclosed property.");
}
stateString = blockAndExtraData[0].substring(stateStart + 1, blockAndExtraData[0].length() - 1);
}
if (typeString.isEmpty()) {
@ -288,6 +366,10 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
}
}
}
// this should be impossible but IntelliJ isn't that smart
if (blockType == null) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'");
}
if (blockAndExtraData.length > 1 && blockAndExtraData[1].startsWith("{")) {
String joined = StringMan.join(Arrays.copyOfRange(blockAndExtraData, 1, blockAndExtraData.length), "|");
@ -322,6 +404,7 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
break;
}
}
mobName = ent.getId();
if (!worldEdit.getPlatformManager().queryCapability(Capability.USER_COMMANDS).isValidMobType(mobName)) {
String finalMobName = mobName.toLowerCase(Locale.ROOT);
throw new SuggestInputParseException("Unknown mob type '" + mobName + "'", mobName, () -> Stream.of(MobType.values())

View File

@ -28,7 +28,6 @@ import com.sk89q.worldedit.function.mask.BiomeMask2D;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.session.request.RequestExtent;
import com.sk89q.worldedit.world.biome.BiomeType;
import java.util.Arrays;

View File

@ -26,7 +26,8 @@ import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.BlockStateMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.session.request.RequestExtent;
import java.util.stream.Stream;
import java.util.stream.Stream;

View File

@ -25,7 +25,6 @@ import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import com.sk89q.worldedit.session.request.RequestExtent;
import java.util.List;

View File

@ -29,7 +29,8 @@ import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.function.mask.OffsetMask;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.session.request.RequestExtent;
import java.util.stream.Stream;
import java.util.stream.Stream;

View File

@ -25,7 +25,6 @@ import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import com.sk89q.worldedit.session.request.RequestExtent;
import java.util.List;

View File

@ -30,6 +30,7 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.StateApplyingPattern;
import com.sk89q.worldedit.function.pattern.TypeApplyingPattern;
import com.sk89q.worldedit.internal.registry.InputParser;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

View File

@ -19,45 +19,12 @@
package com.sk89q.worldedit.extension.platform;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.task.SimpleAsyncNotifyQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.internal.cui.CUIEvent;
import java.io.File;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AbstractNonPlayerActor implements Actor {
private final ConcurrentHashMap<String, Object> meta = new ConcurrentHashMap<>();
@Override
public Map<String, Object> getRawMeta() {
return meta;
}
// Queue for async tasks
private AtomicInteger runningCount = new AtomicInteger();
private SimpleAsyncNotifyQueue asyncNotifyQueue = new SimpleAsyncNotifyQueue(
(thread, throwable) -> {
while (throwable.getCause() != null) {
throwable = throwable.getCause();
}
if (throwable instanceof WorldEditException) {
printError(throwable.getLocalizedMessage());
} else {
FaweException fe = FaweException.get(throwable);
if (fe != null) {
printError(fe.getMessage());
} else {
throwable.printStackTrace();
}
}
});
@Override
public boolean canDestroyBedrock() {
return true;
@ -81,35 +48,4 @@ public abstract class AbstractNonPlayerActor implements Actor {
@Override
public void dispatchCUIEvent(CUIEvent event) {
}
/**
* Run a task either async, or on the current thread
*
* @param ifFree
* @param checkFree Whether to first check if a task is running
* @param async
* @return false if the task was ran or queued
*/
@Override
public boolean runAction(Runnable ifFree, boolean checkFree, boolean async) {
if (checkFree) {
if (runningCount.get() != 0) {
return false;
}
}
Runnable wrapped = () -> {
try {
runningCount.addAndGet(1);
ifFree.run();
} finally {
runningCount.decrementAndGet();
}
};
if (async) {
asyncNotifyQueue.queue(wrapped);
} else {
TaskManager.IMP.taskNow(wrapped, false);
}
return true;
}
}

View File

@ -19,13 +19,14 @@
package com.sk89q.worldedit.extension.platform;
import com.sk89q.worldedit.EditSession;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.task.SimpleAsyncNotifyQueue;
import com.boydti.fawe.regions.FaweMaskManager;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.util.WEManager;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
@ -45,6 +46,8 @@ import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector;
import javax.annotation.Nullable;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.regions.selector.CylinderRegionSelector;
import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector;
@ -70,7 +73,6 @@ import java.text.NumberFormat;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.jetbrains.annotations.NotNull;
@ -249,7 +251,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
if (!lastState) {
lastState = BlockTypeUtil.centralBottomLimit(state) != 1;
continue;
}
}
if (freeStart == -1) {
freeStart = level + BlockTypeUtil.centralTopLimit(state);
} else {
@ -257,13 +259,13 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
double space = level + bottomLimit - freeStart;
if (space >= height) {
setPosition(Vector3.at(x + 0.5, freeStart, z + 0.5));
return true;
}
return true;
}
// Not enough room, reset the free position
if (bottomLimit != 1) {
freeStart = -1;
}
}
}
}
} else {
freeStart = -1;
lastState = true;
@ -414,7 +416,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
session.setBlock(spot, BlockTypes.GLASS.getDefaultState());
} catch (MaxChangedBlocksException ignored) {
}
}
}
} else {
setFlying(true);
}
@ -477,6 +479,23 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
return getBlockTrace(range, false);
}
/**
* Advances the block target block until the current block is a free
* @return true if a free spot is found
*/
private boolean advanceToFree(TargetBlock hitBlox) {
Location curBlock;
while ((curBlock = hitBlox.getCurrentBlock()) != null) {
if (canPassThroughBlock(curBlock)) {
return true;
}
hitBlox.getNextBlock();
}
return false;
}
@Override
public Location getSolidBlockTrace(int range) {
TargetBlock tb = new TargetBlock(this, range, 0.2);
@ -541,33 +560,17 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
return false;
}
/**
* Advances the block target block until the current block is a free
* @return true if a free spot is found
*/
private boolean advanceToFree(TargetBlock hitBlox) {
Location curBlock;
while ((curBlock = hitBlox.getCurrentBlock()) != null) {
if (canPassThroughBlock(curBlock)) {
return true;
}
hitBlox.getNextBlock();
}
return false;
}
@Override
public boolean passThroughForwardWall(int range) {
TargetBlock hitBlox = new TargetBlock(this, range, 0.2);
if (!advanceToWall(hitBlox)) {
return false;
}
return false;
}
if (!advanceToFree(hitBlox)) {
return false;
return false;
}
Location foundBlock = hitBlox.getCurrentBlock();
@ -576,7 +579,6 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
return true;
}
return false;
}

Some files were not shown because too many files have changed in this diff Show More