Fix some merge issues

This commit is contained in:
Jesse Boyd 2019-11-20 00:11:54 +00:00
parent 0e22d4718a
commit 60759934a3
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
54 changed files with 1403 additions and 1180 deletions

View File

@ -21,6 +21,7 @@ repositories {
maven { url = uri("http://repo.dmulloy2.net/content/groups/public/") }
maven { url = uri("http://ci.ender.zone/plugin/repository/everything/") }
maven { url = uri("https://repo.inventivetalent.org/content/groups/public/")}
flatDir {dir(File("lib"))}
}
configurations.all {
@ -34,6 +35,7 @@ dependencies {
"api"(project(":worldedit-core"))
"api"(project(":worldedit-libs:core"))
"api"(project(":worldedit-libs:bukkit"))
"compile"(":worldedit-adapters:")
"compile"("it.unimi.dsi:fastutil:8.2.1")
"api"("com.destroystokyo.paper:paper-api:1.14.4-R0.1-SNAPSHOT") {
exclude("junit", "junit")

View File

@ -230,16 +230,6 @@ public class BukkitPlayer extends AbstractPlayerActor {
|| plugin.getPermissionsResolver().hasPermission(player.getWorld().getName(), player, perm);
}
@Override public boolean togglePermission(String permission) {
if (this.hasPermission(permission)) {
player.addAttachment(plugin).setPermission(permission, false);
return false;
} else {
player.addAttachment(plugin).setPermission(permission, true);
return true;
}
}
@Override
public boolean isAllowedToFly() {
return player.getAllowFlight();
@ -257,13 +247,13 @@ public class BukkitPlayer extends AbstractPlayerActor {
* - The `/wea` command will give/remove the required bypass permission
*/
if (Fawe.<FaweBukkit>imp().getVault() == null || Fawe.<FaweBukkit> imp().getVault().permission == null) {
player.addAttachment(Fawe.<FaweBukkit> imp().getPlugin()).setPermission(permission, value);
player.addAttachment(plugin).setPermission(permission, value);
} else if (value) {
if (!Fawe.<FaweBukkit> imp().getVault().permission.playerAdd(player, permission)) {
player.addAttachment(Fawe.<FaweBukkit> imp().getPlugin()).setPermission(permission, value);
player.addAttachment(plugin).setPermission(permission, value);
}
} else if (!Fawe.<FaweBukkit>imp().getVault().permission.playerRemove(player, permission)) {
player.addAttachment(Fawe.<FaweBukkit>imp().getPlugin()).setPermission(permission, value);
player.addAttachment(plugin).setPermission(permission, value);
}
}

View File

@ -10,6 +10,7 @@ plugins {
repositories {
maven { url = uri("http://ci.athion.net/job/PlotSquared-breaking/ws/mvn/") }
}
applyPlatformAndCoreConfiguration()
@ -23,7 +24,7 @@ configurations.all {
dependencies {
"compile"(project(":worldedit-libs:core"))
"compile"("de.schlichtherle:truezip:6.8.3")
"compile"("rhino:js:1.7.11")
"compile"("org.mozilla:rhino: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")

View File

@ -16,10 +16,9 @@ import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.Constant;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@ -39,6 +38,8 @@ public class BrushSettings {
SCROLL_ACTION,
}
private static final Expression DEFAULT_SIZE = Expression.compile("1");
private final Map<SettingType, Object> constructor = new ConcurrentHashMap<>();
private Brush brush;
@ -46,7 +47,7 @@ public class BrushSettings {
private Mask sourceMask;
private ResettableExtent transform;
private Pattern material;
private Expression size = new Expression(1);
private Expression size = DEFAULT_SIZE;
private Set<String> permissions;
private Scroll scrollAction;
private String lastWorld;
@ -135,7 +136,7 @@ public class BrushSettings {
transform = null;
material = null;
scrollAction = null;
size = new Expression(1);
size = DEFAULT_SIZE;
permissions.clear();
constructor.clear();
return this;
@ -182,7 +183,7 @@ public class BrushSettings {
public BrushSettings setSize(Expression size) {
checkNotNull(size);
this.size = size;
if (size.getRoot() instanceof Constant && ((Constant) size.getRoot()).getValue() == -1) {
if (size == DEFAULT_SIZE) {
constructor.remove(SettingType.SIZE);
} else {
constructor.put(SettingType.SIZE, size.toString());
@ -191,7 +192,7 @@ public class BrushSettings {
}
public BrushSettings setSize(double size) {
return setSize(new Expression(size));
return setSize(Expression.compile(Double.toString(size)));
}
public BrushSettings setScrollAction(Scroll scrollAction) {

View File

@ -3,9 +3,9 @@ package com.boydti.fawe.object.pattern;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.internal.expression.EvaluationException;
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.math.BlockVector3;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -49,7 +49,7 @@ public class ExpressionPattern extends AbstractPattern {
((WorldEditExpressionEnvironment) expression.getEnvironment()).setCurrentBlock(vector.toVector3());
}
double combined = expression.evaluate(vector.getX(), vector.getY(), vector.getZ());
return BlockState.getFromInternalId((int) combined).toBaseBlock();
return BlockState.getFromOrdinal((int) combined).toBaseBlock();
} catch (EvaluationException e) {
e.printStackTrace();
return BlockTypes.AIR.getDefaultState().toBaseBlock();

View File

@ -22,7 +22,7 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.SpongeSchematicWriter;
import com.sk89q.worldedit.extent.clipboard.io.FastSchematicWriter;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import java.io.BufferedOutputStream;
@ -78,7 +78,7 @@ public class FaweSchematicHandler extends SchematicHandler {
if (cTag instanceof CompressedSchematicTag) {
Clipboard clipboard = (Clipboard) cTag.getSource();
try (OutputStream stream = new FileOutputStream(tmp); NBTOutputStream output = new NBTOutputStream(new BufferedOutputStream(new PGZIPOutputStream(stream)))) {
new SpongeSchematicWriter(output).write(clipboard);
new FastSchematicWriter(output).write(clipboard);
}
} else {
try (OutputStream stream = new FileOutputStream(tmp); BufferedOutputStream output = new BufferedOutputStream(new PGZIPOutputStream(stream))) {

View File

@ -1,287 +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.boydti.fawe.util;
import com.boydti.fawe.command.AnvilCommands;
import com.boydti.fawe.command.CFICommands;
import com.sk89q.minecraft.util.commands.Step;
import com.sk89q.worldedit.command.ToolUtilCommands;
import com.sk89q.worldedit.internal.annotation.Range;
import org.enginehub.piston.annotation.Command;
import com.sk89q.worldedit.command.util.CommandPermissions;
import com.sk89q.minecraft.util.commands.NestedCommand;
import com.sk89q.worldedit.command.BiomeCommands;
import com.sk89q.worldedit.command.BrushCommands;
import com.sk89q.worldedit.command.ChunkCommands;
import com.sk89q.worldedit.command.ClipboardCommands;
import com.sk89q.worldedit.command.GenerationCommands;
import com.sk89q.worldedit.command.HistoryCommands;
//import com.sk89q.worldedit.command.MaskCommands;
import com.sk89q.worldedit.command.NavigationCommands;
//import com.sk89q.worldedit.command.PatternCommands;
import com.sk89q.worldedit.command.RegionCommands;
import com.sk89q.worldedit.command.SchematicCommands;
import com.sk89q.worldedit.command.ScriptingCommands;
import com.sk89q.worldedit.command.SelectionCommands;
import com.sk89q.worldedit.command.SnapshotCommands;
import com.sk89q.worldedit.command.SnapshotUtilCommands;
import com.sk89q.worldedit.command.SuperPickaxeCommands;
import com.sk89q.worldedit.command.ToolCommands;
//import com.sk89q.worldedit.command.TransformCommands;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.command.WorldEditCommands;
import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.ArgFlag;
import org.enginehub.piston.annotation.param.Switch;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public final class DocumentationPrinter {
private DocumentationPrinter() {
}
/**
* Generates documentation.
*
* @param args arguments
* @throws IOException thrown on I/O error
*/
public static void main(String[] args) throws IOException {
writePermissionsWikiTable();
}
private static void writePermissionsWikiTable()
throws IOException {
try (FileOutputStream fos = new FileOutputStream("wiki_permissions.md")) {
PrintStream stream = new PrintStream(fos);
stream.print("## Overview\n");
stream.print("This page is generated from the source. " +
"Click one of the edit buttons below to modify a command class. " +
"You will need to find the parts which correspond to the documentation. " +
"Command documentation will be consistent with what is available ingame");
stream.println();
stream.println();
stream.print("To view this information ingame use `//help [category|command]`\n");
stream.print("## Command Syntax \n");
stream.print(" - `<arg>` - A required parameter \n");
stream.print(" - `[arg]` - An optional parameter \n");
stream.print(" - `<arg1|arg2>` - Multiple parameters options \n");
stream.print(" - `<arg=value>` - Default or suggested value \n");
stream.print(" - `-a` - A command flag e.g., `//<command> -a [flag-value]`");
stream.println();
stream.print("## See also\n");
stream.print(" - [Masks](https://github.com/boy0001/FastAsyncWorldedit/wiki/WorldEdit---FAWE-mask-list)\n");
stream.print(" - [Patterns](https://github.com/boy0001/FastAsyncWorldedit/wiki/WorldEdit-and-FAWE-patterns)\n");
stream.print(" - [Transforms](https://github.com/boy0001/FastAsyncWorldedit/wiki/Transforms)\n");
stream.println();
stream.print("## Content");
stream.println();
stream.print("Click on a category to go to the list of commands, or `More Info` for detailed descriptions ");
stream.println();
StringBuilder builder = new StringBuilder();
writePermissionsWikiTable(stream, builder, "/we ", WorldEditCommands.class);
writePermissionsWikiTable(stream, builder, "/", UtilityCommands.class);
writePermissionsWikiTable(stream, builder, "/", RegionCommands.class);
writePermissionsWikiTable(stream, builder, "/", SelectionCommands.class);
writePermissionsWikiTable(stream, builder, "/", HistoryCommands.class);
writePermissionsWikiTable(stream, builder, "/schematic ", SchematicCommands.class);
writePermissionsWikiTable(stream, builder, "/", ClipboardCommands.class);
writePermissionsWikiTable(stream, builder, "/", GenerationCommands.class);
writePermissionsWikiTable(stream, builder, "/", BiomeCommands.class);
writePermissionsWikiTable(stream, builder, "/anvil ", AnvilCommands.class);
writePermissionsWikiTable(stream, builder, "/sp ", SuperPickaxeCommands.class);
writePermissionsWikiTable(stream, builder, "/", NavigationCommands.class);
writePermissionsWikiTable(stream, builder, "/snapshot", SnapshotCommands.class);
writePermissionsWikiTable(stream, builder, "/", SnapshotUtilCommands.class);
writePermissionsWikiTable(stream, builder, "/", ScriptingCommands.class);
writePermissionsWikiTable(stream, builder, "/", ChunkCommands.class);
writePermissionsWikiTable(stream, builder, "/", ToolUtilCommands.class);
writePermissionsWikiTable(stream, builder, "/tool ", ToolCommands.class);
writePermissionsWikiTable(stream, builder, "/brush ", BrushCommands.class);
//writePermissionsWikiTable(stream, builder, "", MaskCommands.class, "/Masks");
//writePermissionsWikiTable(stream, builder, "", PatternCommands.class, "/Patterns");
//writePermissionsWikiTable(stream, builder, "", TransformCommands.class, "/Transforms");
writePermissionsWikiTable(stream, builder, "/cfi ", CFICommands.class, "Create From Image");
stream.println();
stream.print("#### Uncategorized\n");
stream.append("| Aliases | Permission | flags | Usage |\n");
stream.append("| --- | --- | --- | --- |\n");
stream.append("| //cancel | fawe.cancel | | Cancels your current operations |\n");
stream.append("| /plot replaceall | plots.replaceall | | Replace all blocks in the plot world |\n");
// stream.append("| /plot createfromimage | plots.createfromimage | | Starts world creation from a heightmap image: [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/CreateFromImage) |\n");
stream.print("\n---\n");
stream.print(builder);
}
}
private static void writePermissionsWikiTable(PrintStream stream, StringBuilder content, String prefix, Class<?> cls) {
writePermissionsWikiTable(stream, content, prefix, cls, getName(cls));
}
public static String getName(Class cls) {
return cls.getSimpleName().replaceAll("(\\p{Ll})(\\p{Lu})", "$1 $2");
}
private static void writePermissionsWikiTable(PrintStream stream, StringBuilder content, String prefix, Class<?> cls, String name) {
stream.print(" - [`" + name + "`](#" + name.replaceAll(" ", "-").replaceAll("/", "").toLowerCase() + "-edittop) ");
Command cmd = cls.getAnnotation(Command.class);
if (cmd != null) {
stream.print(" (" + cmd.desc() + ")");
}
stream.println();
writePermissionsWikiTable(content, prefix, cls, name, true);
}
private static void writePermissionsWikiTable(StringBuilder stream, String prefix, Class<?> cls, String name, boolean title) {
if (title) {
String path = "https://github.com/boy0001/FastAsyncWorldedit/edit/master/core/src/main/java/" + cls.getName().replaceAll("\\.", "/") + ".java";
stream.append("### **" + name + "** `[`[`edit`](" + path + ")`|`[`top`](#overview)`]`");
stream.append("\n");
Command cmd = cls.getAnnotation(Command.class);
if (cmd != null) {
if (!cmd.desc().isEmpty()) {
stream.append("> (" + (cmd.desc()) + ") \n");
}
if (!cmd.descFooter().isEmpty()) {
stream.append("" + (cmd.descFooter()) + " \n");
}
}
stream.append("\n");
stream.append("---");
stream.append("\n");
stream.append("\n");
}
for (Method method : cls.getMethods()) {
if (!method.isAnnotationPresent(Command.class)) {
continue;
}
Command cmd = method.getAnnotation(Command.class);
String[] aliases = cmd.aliases();
String usage = prefix + aliases[0] + " " + getUsage(cmd, method);
stream.append("#### `" + usage + "`\n");
if (method.isAnnotationPresent(CommandPermissions.class)) {
CommandPermissions perms = method.getAnnotation(CommandPermissions.class);
stream.append("**Perm**: `" + StringMan.join(perms.value(), "`, `") + "` \n");
}
String help = getDesc(cmd, method);
stream.append("**Desc**: " + help.trim().replaceAll("\n", "<br />") + " \n");
if (method.isAnnotationPresent(NestedCommand.class)) {
NestedCommand nested =
method.getAnnotation(NestedCommand.class);
Class<?>[] nestedClasses = nested.value();
for (Class clazz : nestedClasses) {
writePermissionsWikiTable(stream, prefix + cmd.aliases()[0] + " ", clazz, getName(clazz), false);
}
}
}
stream.append("\n");
if (title) stream.append("---");
stream.append("\n");
stream.append("\n");
}
public static String getDesc(Command command, Method method) {
Parameter[] params = method.getParameters();
List<String> desc = new ArrayList<>();
for (Parameter param : params) {
String[] info = getParamInfo(param);
if (info != null) {
desc.add(info[0].replace("%s0", info[1]) + " - " + info[2] + ": " + info[3]);
}
}
String footer = command.descFooter();
if (!footer.isEmpty()) footer += "\n";
return footer + StringMan.join(desc, "\n");
}
public static String getUsage(Command command, Method method) {
Parameter[] params = method.getParameters();
List<String> usage = new ArrayList<>();
for (Parameter param : params) {
String[] info = getParamInfo(param);
if (info != null) {
usage.add(info[0].replace("%s0", info[1]));
}
}
return StringMan.join(usage, " ");
}
/*
Return format, name, type, description
*/
public static String[] getParamInfo(Parameter param) {
Switch switchAnn = param.getAnnotation(Switch.class);
Arg argAnn = param.getAnnotation(Arg.class);
Range rangeAnn = param.getAnnotation(Range.class);
Step stepAnn = param.getAnnotation(Step.class);
if (switchAnn != null || argAnn != null || rangeAnn != null || stepAnn != null) {
String[] result = new String[] { "[%s0]", param.getName(), param.getType().getSimpleName(), ""};
boolean optional = argAnn != null && argAnn.def().length != 0;
if (optional) {
result[0] = "<%s0>";
}
if (argAnn != null) result[1] = argAnn.name();
if (argAnn != null) {
if (argAnn.def().length != 0) {
result[0] = result[0].replace("%s0", "%s0=" + argAnn.def());
}
result[3] = argAnn.desc();
} else if (switchAnn != null) {
result[0] = result[0].replace("%s0", "-" + switchAnn.name() + " %s0");
}
if (switchAnn != null) result[3] = switchAnn.desc();
if (rangeAnn != null) {
String step;
String min = rangeAnn.min() == Double.MIN_VALUE ? "(-∞" : ("[" + rangeAnn.min());
String max = rangeAnn.max() == Double.MAX_VALUE ? "∞)" : (rangeAnn.max() + "]");
result[0] += min + "," + max;
}
if (stepAnn != null) {
result[0] += "" + stepAnn.value();
}
return result;
}
return null;
}
public static Collection<ArgFlag> getFlags(Command command, Method method) {
Parameter[] params = method.getParameters();
List<ArgFlag> flags = new ArrayList<>();
for (Parameter param : params) {
ArgFlag flagAnn = param.getAnnotation(ArgFlag.class);
if (flagAnn != null) flags.add(flagAnn);
}
return flags;
}
}

View File

@ -3,7 +3,7 @@ package com.sk89q.jnbt;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.SpongeSchematicWriter;
import com.sk89q.worldedit.extent.clipboard.io.FastSchematicWriter;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
@ -19,7 +19,7 @@ public class CompressedSchematicTag extends CompressedCompoundTag<Clipboard> {
FastByteArrayOutputStream blocksOut = new FastByteArrayOutputStream();
try (LZ4BlockOutputStream lz4out = new LZ4BlockOutputStream(blocksOut)) {
NBTOutputStream nbtOut = new NBTOutputStream(lz4out);
new SpongeSchematicWriter(nbtOut).write(getSource());
new FastSchematicWriter(nbtOut).write(getSource());
} catch (IOException e) {
throw new RuntimeException(e);
}

View File

@ -135,6 +135,7 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@ -1427,8 +1428,22 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
}
/**
* Stack a cuboid region. For compatibility, entities are copied but biomes are not.
* Use {@link #stackCuboidRegion(Region, BlockVector3, int, boolean, boolean, boolean)} to fine tune.
* 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));
}
/**
* Stack a cuboid region.
*
* @param region the region to stack
* @param dir the direction to stack
@ -1439,7 +1454,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
* @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, boolean copyEntities, boolean copyBiomes) throws MaxChangedBlocksException {
public int stackCuboidRegion(Region region, BlockVector3 dir, int count,
boolean copyEntities, boolean copyBiomes, Mask mask) throws MaxChangedBlocksException {
checkNotNull(region);
checkNotNull(dir);
checkArgument(count >= 1, "count >= 1 required");
@ -1451,14 +1467,10 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
copy.setCopyingBiomes(copyBiomes);
copy.setRepetitions(count);
copy.setTransform(new AffineTransform().translate(dir.multiply(size)));
Mask sourceMask = getSourceMask();
if (sourceMask != null) {
new MaskTraverser(sourceMask).reset(EditSession.this);
copy.setSourceMask(sourceMask);
mask = MaskIntersection.of(getSourceMask(), mask).optimize();
if (mask != Masks.alwaysTrue()) {
setSourceMask(null);
}
if (!copyAir) {
copy.setSourceMask(new ExistingBlockMask(this));
copy.setSourceMask(mask);
}
Operations.completeBlindly(copy);
return this.changes = copy.getAffected();
@ -2349,12 +2361,26 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
final Vector3 scaled = current.subtract(zero).divide(unit);
try {
if (expression.evaluateTimeout(timeout, scaled.getX(), scaled.getY(), scaled.getZ(), defaultMaterial.getBlockType().getInternalId(), defaultMaterial.getInternalPropertiesId()) <= 0) {
// TODO data
int[] legacy = LegacyMapper.getInstance().getLegacyFromBlock(defaultMaterial.toImmutableState());
int typeVar = 0;
int dataVar = 0;
if (legacy != null) {
typeVar = legacy[0];
if (legacy.length > 1) {
dataVar = legacy[1];
}
}
if (expression.evaluate(new double[]{scaled.getX(), scaled.getY(), scaled.getZ(), typeVar, dataVar}, timeout) <= 0) {
return null;
}
return BlockTypes.get((int) typeVariable.getValue()).withPropertyId((int) dataVariable.getValue()).toBaseBlock();
int newType = (int) typeVariable.getValue();
int newData = (int) dataVariable.getValue();
if (newType != typeVar || newData != dataVar) {
BlockState state = LegacyMapper.getInstance().getBlockFromLegacy(newType, newData);
return state == null ? defaultMaterial : state.toBaseBlock();
} else {
return defaultMaterial;
}
} catch (ExpressionTimeoutException e) {
timedOut[0] = timedOut[0] + 1;
return null;
@ -2404,7 +2430,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
final Vector3 scaled = position.toVector3().subtract(zero).divide(unit);
// transform
expression.evaluateTimeout(timeout, scaled.getX(), scaled.getY(), scaled.getZ());
expression.evaluate(new double[]{scaled.getX(), scaled.getY(), scaled.getZ()}, timeout);
int xv = (int) (x.getValue() * unit.getX() + zero2.getX());
int yv = (int) (y.getValue() * unit.getY() + zero2.getY());
int zv = (int) (z.getValue() * unit.getZ() + zero2.getZ());

View File

@ -78,6 +78,7 @@ 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;
@ -147,7 +148,6 @@ 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;
@ -992,6 +992,8 @@ public class LocalSession implements TextureHolder {
return getTool(item, player);
}
private transient boolean loadDefaults = true;
public Tool getTool(BaseItem item, Player player) {
if (Settings.IMP.EXPERIMENTAL.PERSISTENT_BRUSHES && item.getNativeItem() != null) {
BrushTool tool = BrushCache.getTool(player, this, item);
@ -1612,7 +1614,9 @@ 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"));
}

View File

@ -43,8 +43,6 @@ 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.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.runtime.Constant;
import com.sk89q.worldedit.internal.expression.runtime.RValue;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.scripting.CraftScriptContext;
import com.sk89q.worldedit.scripting.CraftScriptEngine;
@ -397,8 +395,8 @@ public final class WorldEdit {
public void checkMaxBrushRadius(Expression radius) throws MaxBrushRadiusException {
if (getConfiguration().maxBrushRadius > 0) {
RValue r = radius.getRoot();
if (r instanceof Constant && ((Constant) r).getValue() > getConfiguration().maxBrushRadius) {
double val = radius.evaluate();
if (val > getConfiguration().maxBrushRadius) {
throw new MaxBrushRadiusException();
}
}

View File

@ -97,7 +97,7 @@ public class ApplyBrushCommands {
Contextual<? extends RegionFunction> generatorFactory) throws WorldEditException {
double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class));
RegionFactory regionFactory = REGION_FACTORY.value(parameters).asSingle(RegionFactory.class);
BrushCommands.setOperationBasedBrush(player, localSession, new Expression(radius),
BrushCommands.setOperationBasedBrush(player, localSession, Expression.compile(Double.toString(radius)),
new Apply(generatorFactory), regionFactory, "worldedit.brush.apply");
}

View File

@ -42,6 +42,7 @@ import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.FlatRegion;
import com.sk89q.worldedit.regions.Region;

View File

@ -98,9 +98,8 @@ import com.sk89q.worldedit.function.mask.SingleBlockTypeMask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.annotation.ClipboardMask;
import com.sk89q.worldedit.internal.annotation.Range;
import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.factory.RegionFactory;
@ -133,6 +132,7 @@ import org.enginehub.piston.annotation.param.ArgFlag;
import org.enginehub.piston.annotation.param.Switch;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
import org.jetbrains.annotations.Range;
import static com.google.common.base.Preconditions.checkNotNull;
@ -308,7 +308,7 @@ public class BrushCommands {
)
@CommandPermissions("worldedit.brush.spline")
public void catenaryBrush(InjectedValueAccess context, @Arg(desc = "Pattern") Pattern fill,
@Arg(def = "1.2", desc = "Length of wire compared to distance between points") @Range(min = 1) double lengthFactor,
@Arg(def = "1.2", desc = "Length of wire compared to distance between points") @Range(from = 1, to=Integer.MAX_VALUE) double lengthFactor,
@Arg(desc = "The radius to sample for blending", def = "0")
Expression radius,
@Switch(name = 'h', desc = "Create only a shell")
@ -439,7 +439,7 @@ public class BrushCommands {
public void stencilBrush(LocalSession session, InjectedValueAccess context, @Arg(desc = "Pattern") Pattern fill,
@Arg(desc = "Expression", def = "5") Expression radius,
@Arg(desc = "String", def = "") String image,
@Arg(def = "0", desc = "rotation") @Range(min = 0, max = 360) int rotation,
@Arg(def = "0", desc = "rotation") @Range(from=0, to=360) int rotation,
@Arg(desc = "double", def = "1") double yscale,
@Switch(name = 'w', desc = "Apply at maximum saturation") boolean onlyWhite,
@Switch(name = 'r', desc = "Apply random rotation") boolean randomRotate) throws WorldEditException, FileNotFoundException {
@ -470,7 +470,7 @@ public class BrushCommands {
@Arg(desc = "Expression", def = "5")
Expression radius,
ProvideBindings.ImageUri imageUri,
@Arg(def = "1", desc = "scale height") @Range(min = Double.MIN_NORMAL)
@Arg(def = "1", desc = "scale height")
double yscale,
@Switch(name = 'a', desc = "Use image Alpha")
boolean alpha,
@ -660,13 +660,14 @@ public class BrushCommands {
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 = '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 {
Mask sourceMask,
InjectedValueAccess context) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
@ -695,7 +696,8 @@ public class BrushCommands {
@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 {
Mask maskOpt,
InjectedValueAccess context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
FaweLimit limit = Settings.IMP.getLimit(player);
@ -752,7 +754,7 @@ public class BrushCommands {
"Snow Pic: https://i.imgur.com/Hrzn0I4.png"
)
@CommandPermissions("worldedit.brush.height")
public void heightBrush(LocalSession session, @Arg(desc = "Expression", def = "5") Expression radius, @Arg(desc = "String", def = "") String image, @Arg(def = "0", desc = "rotation") @Range(min = 0, max = 360) int rotation, @Arg(desc = "double", def = "1") double yscale, @Switch(name = 'r', desc = "TODO") boolean randomRotate, @Switch(name = 'l', desc = "TODO") boolean layers, @Switch(name = 's', desc = "TODO") boolean dontSmooth, InjectedValueAccess context) throws WorldEditException, FileNotFoundException {
public void heightBrush(LocalSession session, @Arg(desc = "Expression", def = "5") Expression radius, @Arg(desc = "String", def = "") String image, @Arg(def = "0", desc = "rotation") @Range(from = 0, to = 360) int rotation, @Arg(desc = "double", def = "1") double yscale, @Switch(name = 'r', desc = "TODO") boolean randomRotate, @Switch(name = 'l', desc = "TODO") boolean layers, @Switch(name = 's', desc = "TODO") boolean dontSmooth, InjectedValueAccess context) throws WorldEditException, FileNotFoundException {
terrainBrush(session, radius, image, rotation, yscale, false, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE, context);
}
@ -768,7 +770,7 @@ public class BrushCommands {
Expression radius,
@Arg(desc = "String", def = "")
String image,
@Arg(def = "0", desc = "rotation") @Step(90) @Range(min = 0, max = 360)
@Arg(def = "0", desc = "rotation") @Step(90) @Range(from = 0, to = 360)
int rotation,
@Arg(desc = "double", def = "1")
double yscale,
@ -787,7 +789,7 @@ public class BrushCommands {
desc = "This brush raises or lowers land towards the clicked point"
)
@CommandPermissions("worldedit.brush.height")
public void flattenBrush(LocalSession session, @Arg(desc = "Expression", def = "5") Expression radius, @Arg(desc = "String", def = "") String image, @Arg(def = "0", desc = "rotation") @Step(90) @Range(min = 0, max = 360) int rotation, @Arg(desc = "double", def = "1") double yscale,
public void flattenBrush(LocalSession session, @Arg(desc = "Expression", def = "5") Expression radius, @Arg(desc = "String", def = "") String image, @Arg(def = "0", desc = "rotation") @Step(90) @Range(from = 0, to = 360) int rotation, @Arg(desc = "double", def = "1") double yscale,
@Switch(name = 'r', desc = "Enables random off-axis rotation")
boolean randomRotate,
@Switch(name = 'l', desc = "Will work on snow layers")

View File

@ -39,10 +39,12 @@ 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;
@ -314,8 +316,8 @@ public class ClipboardCommands {
}
}
final LocalConfiguration config = this.worldEdit.getConfiguration();
final File working = this.worldEdit.getWorkingDirectoryFile(config.saveDir).getAbsoluteFile();
final LocalConfiguration config = WorldEdit.getInstance().getConfiguration();
final File working = WorldEdit.getInstance().getWorkingDirectoryFile(config.saveDir).getAbsoluteFile();
url = MainUtil.upload(null, null, "zip", new RunnableVal<OutputStream>() {
@Override
@ -484,7 +486,7 @@ public class ClipboardCommands {
uri = ((URIClipboardHolder) holder).getURI(clipboard);
}
PasteEvent event = new PasteEvent(player, clipboard, uri, editSession, to);
worldEdit.getEventBus().post(event);
WorldEdit.getInstance().getEventBus().post(event);
if (event.isCancelled()) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
}

View File

@ -342,7 +342,7 @@ public class GeneralCommands {
desc = "Set the global mask"
)
@CommandPermissions("worldedit.global-texture")
public void gtexture(Player player, World world, LocalSession session, EditSession editSession, @Arg(name = "context", desc = "InjectedValueAccess", def = "") List<String> arguments) throws WorldEditException, FileNotFoundException {
public void gtexture(Player player, World worldArg, LocalSession session, EditSession editSession, @Arg(name = "context", desc = "InjectedValueAccess", def = "") List<String> arguments) throws WorldEditException, FileNotFoundException {
// gtexture <randomize> <min=0> <max=100>
// TODO NOT IMPLEMENTED convert this to an ArgumentConverter
if (arguments.isEmpty()) {
@ -375,7 +375,7 @@ public class GeneralCommands {
} else {
ParserContext parserContext = new ParserContext();
parserContext.setActor(player);
parserContext.setWorld(world);
parserContext.setWorld(worldArg);
parserContext.setSession(session);
parserContext.setExtent(editSession);
Mask mask = worldEdit.getMaskFactory().parseFromInput(arg, parserContext);

View File

@ -47,8 +47,8 @@ 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.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
@ -69,6 +69,7 @@ import org.enginehub.piston.annotation.param.Switch;
import static com.google.common.base.Preconditions.checkNotNull;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.jetbrains.annotations.Range;
/**
* Commands for the generation of shapes and other objects.
@ -173,7 +174,7 @@ public class GenerationCommands {
)
@CommandPermissions("worldedit.generation.ore")
@Logging(PLACEMENT)
public void ore(Actor actor, LocalSession session, EditSession editSession, @Selection Region region, @Arg(desc = "Mask") Mask mask, @Arg(desc = "Pattern") Pattern material, @Arg(desc="Ore vein size") @Range(min = 0) int size, int freq, @Range(min = 0, max = 100) int rarity, @Range(min = 0, max = 255) int minY, @Range(min = 0, max = 255) int maxY, InjectedValueAccess context) throws WorldEditException {
public void ore(Actor actor, LocalSession session, EditSession editSession, @Selection Region region, @Arg(desc = "Mask") Mask mask, @Arg(desc = "Pattern") Pattern material, @Arg(desc="Ore vein size") @Range(from = 0, to=Integer.MAX_VALUE) int size, int freq, @Range(from=0, to=100) int rarity, @Range(from=0, to=255) int minY, @Range(from=0, to=255) int maxY, InjectedValueAccess context) throws WorldEditException {
actor.checkConfirmationRegion(() -> {
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
BBC.VISITOR_BLOCK.send(actor, editSession.getBlockChangeCount());
@ -186,15 +187,14 @@ public class GenerationCommands {
)
@CommandPermissions("worldedit.generation.cylinder")
@Logging(PLACEMENT)
public int hcyl(Actor actor, LocalSession session, EditSession editSession,
public void hcyl(Actor actor, LocalSession session, EditSession editSession, InjectedValueAccess context,
@Arg(desc = "The pattern of blocks to generate")
Pattern pattern,
@Arg(desc = "The radii of the cylinder. 1st is N/S, 2nd is E/W")
@Radii(2)
List<Double> radii,
BlockVector2 radii,
@Arg(desc = "The height of the cylinder", def = "1")
int height) throws WorldEditException {
return cyl(actor, session, editSession, pattern, radii, height, true);
cyl(actor, session, editSession, pattern, radii, height, true, context);
}
@Command(
@ -293,9 +293,12 @@ 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) throws WorldEditException {
int size,
@Arg(desc = "//TODO ", def = "0.02")
double density) throws WorldEditException {
checkCommandArgument(0 <= density && density <= 100, "Density must be between 0 and 100");
worldEdit.checkMaxRadius(size);
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(actor), size);
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(actor), size, density);
actor.print(affected + " pumpkin patches created.");
return affected;
}

View File

@ -40,7 +40,6 @@ import com.sk89q.worldedit.command.util.CommandPermissions;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.annotation.Range;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
@ -54,6 +53,7 @@ import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.Switch;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.jetbrains.annotations.Range;
import static com.google.common.base.Preconditions.checkNotNull;
@ -83,7 +83,7 @@ public class HistoryCommands {
" - Import from disk: /frb #import"
)
@CommandPermissions("worldedit.history.rollback")
public void faweRollback(Player player, LocalSession session, @Arg(desc = "String user") String user, @Arg(def = "0", desc = "radius") @Range(min = 0) int radius, @Arg(name = "time", desc = "String", def = "0") String time, @Switch(name = 'r', desc = "TODO") boolean restore) throws WorldEditException {
public void faweRollback(Player player, LocalSession session, @Arg(desc = "String user") String user, @Arg(def = "0", desc = "radius") @Range(from = 0, to=Integer.MAX_VALUE) int radius, @Arg(name = "time", desc = "String", def = "0") String time, @Switch(name = 'r', desc = "TODO") boolean restore) throws WorldEditException {
if (!Settings.IMP.HISTORY.USE_DATABASE) {
BBC.SETTING_DISABLE.send(player, "history.use-database (Import with /frb #import )");
return;
@ -214,7 +214,7 @@ public class HistoryCommands {
" - Import from disk: /frb #import"
)
@CommandPermissions("worldedit.history.rollback")
public void restore(Player player, LocalSession session, @Arg(desc = "String user") String user, @Arg(def = "0", desc = "radius") @Range(min = 0) int radius, @Arg(name = "time", desc = "String", def = "0") String time) throws WorldEditException {
public void restore(Player player, LocalSession session, @Arg(desc = "String user") String user, @Arg(def = "0", desc = "radius") int radius, @Arg(name = "time", desc = "String", def = "0") String time) throws WorldEditException {
faweRollback(player, session, user, radius, time, true);
}
@ -223,19 +223,9 @@ 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")
@Arg(desc = "Number of undoes to perform", def = "1")
int times,
@Arg(name = "player", desc = "Undo this player's operations", def = "")
String playerName,
@ -253,6 +243,16 @@ 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--;
@ -272,7 +272,7 @@ public class HistoryCommands {
)
@CommandPermissions({"worldedit.history.redo", "worldedit.history.redo.self"})
public void redo(Player player, LocalSession session,
@Range(min = 1) @Arg(desc = "Number of redoes to perform", def = "1")
@Arg(desc = "Number of redoes to perform", def = "1")
int times,
@Arg(name = "player", desc = "Redo this player's operations", def = "")
String playerName) throws WorldEditException {

View File

@ -39,8 +39,8 @@ import com.sk89q.worldedit.function.mask.OffsetMask;
import com.sk89q.worldedit.function.mask.RegionMask;
import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionEnvironment;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;

View File

@ -104,7 +104,7 @@ public class PaintBrushCommands {
double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class));
double density = requireNonNull(DENSITY.value(parameters).asSingle(double.class)) / 100;
RegionFactory regionFactory = REGION_FACTORY.value(parameters).asSingle(RegionFactory.class);
BrushCommands.setOperationBasedBrush(player, localSession, new Expression(radius),
BrushCommands.setOperationBasedBrush(player, localSession, Expression.compile(Double.toString(radius)),
new Paint(generatorFactory, density), regionFactory, "worldedit.brush.paint");
}

View File

@ -46,7 +46,6 @@ import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.ClipboardPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.RandomPattern;
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.math.Vector3;
@ -61,6 +60,7 @@ import java.util.Set;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import org.jetbrains.annotations.Range;
//@Command(aliases = {"patterns"},
// desc = "Help for the various patterns. [More Info](https://git.io/vSPmA)",
@ -226,7 +226,7 @@ public class PatternCommands {
descFooter = "Use the pattern's id and the existing blocks data with the provided mask\n" +
" - Use to replace slabs or where the data values needs to be shifted instead of set"
)
public Pattern iddatamask(Extent extent, @Range(min = 0, max = 15) @Arg(desc = "bit mask") int bitmask, @Arg(desc = "Pattern")Pattern pattern) {
public Pattern iddatamask(Extent extent, @Range(from = 0, to = 15) @Arg(desc = "bit mask") int bitmask, @Arg(desc = "Pattern")Pattern pattern) {
return new IdDataMaskPattern(extent, pattern, bitmask);
}

View File

@ -54,7 +54,6 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
import com.sk89q.worldedit.function.visitor.LayerVisitor;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Range;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.math.BlockVector2;
@ -83,6 +82,7 @@ import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.ArgFlag;
import org.enginehub.piston.annotation.param.Switch;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.jetbrains.annotations.Range;
import java.util.ArrayList;
import java.util.Collections;
@ -254,7 +254,7 @@ public class RegionCommands {
desc = "Set block lighting in a selection"
)
@CommandPermissions("worldedit.light.set")
public void setlighting(Player player, EditSession editSession, @Selection Region region, @Range(min = 0, max = 15) int value) {
public void setlighting(Player player, EditSession editSession, @Selection Region region, @Range(from = 0, to = 15) int value) {
// TODO NOT IMPLEMENTED
}
@ -263,7 +263,7 @@ public class RegionCommands {
desc = "Set sky lighting in a selection"
)
@CommandPermissions("worldedit.light.set")
public void setskylighting(Player player, @Selection Region region, @Range(min = 0, max = 15) int value) {
public void setskylighting(Player player, @Selection Region region, @Range(from = 0, to= 15) int value) {
// TODO NOT IMPLEMENTED
}
@ -314,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 0;
return;
}
checkCommandArgument(thickness >= 0, "Thickness must be >= 0");
@ -535,10 +535,12 @@ public class RegionCommands {
boolean moveSelection,
@Switch(name = 'a', desc = "Ignore air blocks")
boolean ignoreAirBlocks,
@Switch(name = 'e', desc = "Ignore entities")
@Switch(name = 'e', desc = "Skip copy entities")
boolean skipEntities,
@Switch(name = 'b', desc = "Also copy biomes")
boolean copyBiomes,
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air", def = "")
Mask mask,
InjectedValueAccess context) throws WorldEditException {
checkCommandArgument(count >= 1, "Count must be >= 1");
@ -554,7 +556,7 @@ public class RegionCommands {
}
actor.checkConfirmationRegion(() -> {
int affected = editSession.moveRegion(region, direction, count, !ignoreAirBlocks, !skipEntities, copyBiomes, combinedMask, replace);
int affected = editSession.moveRegion(region, direction, count, !skipEntities, copyBiomes, combinedMask, replace);
if (moveSelection) {
try {
@ -612,7 +614,7 @@ public class RegionCommands {
@Switch(name = 'b', desc = "Also copy biomes")
boolean copyBiomes,
@ArgFlag(name = 'm', desc = "Source mask", def="")
Mask sourceMask,
Mask mask,
InjectedValueAccess context) throws WorldEditException {
Mask combinedMask;
@ -627,9 +629,6 @@ public class RegionCommands {
}
actor.checkConfirmationStack(() -> {
if (sourceMask != null) {
editSession.addSourceMask(sourceMask);
}
int affected = editSession.stackCuboidRegion(region, direction, count, !skipEntities, copyBiomes, combinedMask);
if (moveSelection) {
@ -751,7 +750,7 @@ public class RegionCommands {
@Logging(REGION)
public void hollow(Actor actor, EditSession editSession,
@Selection Region region,
@Range(min = 0) @Arg(desc = "Thickness of the shell to leave", def = "0")
@Range(from=0, to=Integer.MAX_VALUE) @Arg(desc = "Thickness of the shell to leave", def = "0")
int thickness,
@Arg(desc = "The pattern of blocks to replace the hollowed area with", def = "air")
Pattern pattern,
@ -799,6 +798,7 @@ public class RegionCommands {
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density / 100));
Operations.completeLegacy(visitor);
int affected = ground.getAffected();
actor.print(affected + " flora created.");
}, "/flora", region, context);
}

View File

@ -429,49 +429,6 @@ public class SchematicCommands {
}
}
@Command(
name = "delete",
aliases = {"d"},
desc = "Delete a saved schematic"
)
@CommandPermissions({"worldedit.schematic.delete", "worldedit.schematic.delete.other"})
public void delete(Actor actor, LocalSession session,
@Arg(desc = "File name.")
String filename) throws WorldEditException, IOException {
LocalConfiguration config = worldEdit.getConfiguration();
File working = worldEdit.getWorkingDirectoryFile(config.saveDir);
File dir = Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? new File(working, actor.getUniqueId().toString()) : working;
List<File> files = new ArrayList<>();
if (filename.equalsIgnoreCase("*")) {
files.addAll(getFiles(session.getClipboard()));
} else {
File f = MainUtil.resolveRelative(new File(dir, filename));
files.add(f);
}
if (files.isEmpty()) {
actor.printError(BBC.SCHEMATIC_NONE.s());
return;
}
for (File f : files) {
if (!MainUtil.isInSubDirectory(working, f) || !f.exists()) {
actor.printError("Schematic " + filename + " does not exist! (" + f.exists() + "|" + f + "|" + !MainUtil.isInSubDirectory(working, f)
+ ")");
continue;
}
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS && !MainUtil.isInSubDirectory(dir, f) && !actor.hasPermission("worldedit.schematic.delete.other")) {
BBC.NO_PERM.send(actor, "worldedit.schematic.delete.other");
continue;
}
if (!delete(f)) {
actor.printError("Deletion of " + filename + " failed! Maybe it is read-only.");
continue;
}
BBC.FILE_DELETED.send(actor, filename);
}
}
private List<File> getFiles(ClipboardHolder clipboard) {
Collection<URI> uris = Collections.emptyList();
if (clipboard instanceof URIClipboardHolder) {
@ -853,17 +810,43 @@ public class SchematicCommands {
)
@CommandPermissions("worldedit.schematic.delete")
public void delete(Actor actor,
LocalSession session,
@Arg(desc = "File name.")
String filename) throws WorldEditException {
String filename) throws WorldEditException, IOException {
LocalConfiguration config = worldEdit.getConfiguration();
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
File working = worldEdit.getWorkingDirectoryFile(config.saveDir);
File dir = Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? new File(working, actor.getUniqueId().toString()) : working;
List<File> files = new ArrayList<>();
File f = worldEdit.getSafeOpenFile(actor instanceof Player ? ((Player) actor) : null,
dir, filename, "schematic", ClipboardFormats.getFileExtensionArray());
if (filename.equalsIgnoreCase("*")) {
files.addAll(getFiles(session.getClipboard()));
} else {
File f = MainUtil.resolveRelative(new File(dir, filename));
files.add(f);
}
if (!f.exists()) {
actor.printError("Schematic " + filename + " does not exist!");
if (files.isEmpty()) {
actor.printError(BBC.SCHEMATIC_NONE.s());
return;
}
for (File f : files) {
if (!MainUtil.isInSubDirectory(working, f) || !f.exists()) {
actor.printError("Schematic " + filename + " does not exist! (" + f.exists() + "|" + f + "|" + !MainUtil.isInSubDirectory(working, f)
+ ")");
continue;
}
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS && !MainUtil.isInSubDirectory(dir, f) && !actor.hasPermission("worldedit.schematic.delete.other")) {
BBC.NO_PERM.send(actor, "worldedit.schematic.delete.other");
continue;
}
if (!delete(f)) {
actor.printError("Deletion of " + filename + " failed! Maybe it is read-only.");
continue;
}
BBC.FILE_DELETED.send(actor, filename);
}
}
private boolean delete(File file) {
if (file.delete()) {
new File(file.getParentFile(), "." + file.getName() + ".cached").delete();

View File

@ -58,15 +58,6 @@ public class ScriptingCommands {
this.worldEdit = worldEdit;
}
@Command(
name = "setupdispatcher",
desc = ""
)
@CommandPermissions("fawe.setupdispatcher")
public void setupdispatcher(Player player, LocalSession session, InjectedValueAccess args) throws WorldEditException {
PlatformCommandManager.getInstance().registerAllCommands();
}
@Command(
name = "cs",
desc = "Execute a CraftScript"

View File

@ -74,6 +74,7 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.world.World;
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.storage.ChunkStore;
@ -108,6 +109,7 @@ public class SelectionCommands {
@Command(
name = "/pos1",
aliases = "/1",
desc = "Set position 1"
)
@Logging(POSITION)
@ -136,6 +138,7 @@ public class SelectionCommands {
@Command(
name = "/pos2",
aliases = "/2",
desc = "Set position 2"
)
@Logging(POSITION)
@ -544,7 +547,7 @@ public class SelectionCommands {
if (distribution.isEmpty()) { // *Should* always be false
actor.printError("No blocks counted.");
player.printError("No blocks counted.");
return;
}

View File

@ -19,9 +19,6 @@
package com.sk89q.worldedit.command;
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
@ -39,12 +36,15 @@ import com.sk89q.worldedit.world.snapshot.Snapshot;
import com.sk89q.worldedit.world.snapshot.SnapshotRestore;
import com.sk89q.worldedit.world.storage.ChunkStore;
import com.sk89q.worldedit.world.storage.MissingWorldException;
import java.io.File;
import java.io.IOException;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import java.io.File;
import java.io.IOException;
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class SnapshotUtilCommands {
@ -98,10 +98,10 @@ public class SnapshotUtilCommands {
File dir = config.snapshotRepo.getDirectory();
try {
WorldEdit.logger.info("FAWE found no snapshots: looked in: "
WorldEdit.logger.info("WorldEdit found no snapshots: looked in: "
+ dir.getCanonicalPath());
} catch (IOException e) {
WorldEdit.logger.info("FAWE found no snapshots: looked in "
WorldEdit.logger.info("WorldEdit found no snapshots: looked in "
+ "(NON-RESOLVABLE PATH - does it exist?): "
+ dir.getPath());
}
@ -125,6 +125,7 @@ public class SnapshotUtilCommands {
return;
}
try {
// Restore snapshot
SnapshotRestore restore = new SnapshotRestore(chunkStore, editSession, region);
//player.print(restore.getChunksAffected() + " chunk(s) will be loaded.");
@ -147,8 +148,11 @@ public class SnapshotUtilCommands {
restore.getMissingChunks().size(),
restore.getErrorChunks().size()));
}
} catch (DataException | IOException e) {
actor.printError("Failed to load snapshot: " + e.getMessage());
} finally {
try {
chunkStore.close();
} catch (IOException ignored) {
}
}
}
}

View File

@ -42,13 +42,13 @@ import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.annotation.Range;
import com.sk89q.worldedit.internal.command.CommandArgParser;
import com.sk89q.worldedit.util.HandSide;
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 org.jetbrains.annotations.Range;
import java.util.List;
@ -253,7 +253,7 @@ public class ToolUtilCommands {
)
@CommandPermissions("worldedit.brush.visualize")
public void visual(Player player, LocalSession session,
@Arg(name = "mode", desc = "int", def = "0") @Range(min = 0, max = 2)
@Arg(name = "mode", desc = "int", def = "0") @Range(from = 0, to = 2)
int mode)
throws WorldEditException {
BrushTool tool = session.getBrushTool(player, false);

View File

@ -45,6 +45,7 @@ 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;
@ -57,7 +58,7 @@ 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.EvaluationException;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
@ -95,15 +96,13 @@ import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.ArgFlag;
import org.enginehub.piston.annotation.param.Switch;
import org.enginehub.piston.exception.StopExecutionException;
import org.jetbrains.annotations.Range;
/**
* Utility commands.
*/
@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???
})
public class UtilityCommands {
private final WorldEdit we;
@ -201,9 +200,9 @@ public class UtilityCommands {
public int fill(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")
@Range(from=1, to=Integer.MAX_VALUE) @Arg(desc = "The radius to fill in")
Expression radiusExp,
@Range(min=1) @Arg(desc = "The depth to fill", def = "1")
@Range(from=1, to=Integer.MAX_VALUE) @Arg(desc = "The depth to fill", def = "1")
int depth,
@Arg(desc = "The direction to move", def = "down")
@Direction BlockVector3 direction) throws WorldEditException, EvaluationException {
@ -745,7 +744,7 @@ public class UtilityCommands {
}
try {
if (!MainUtil.isInSubDirectory(root, file)) {
throw new RuntimeException(new CommandException("Invalid path"));
throw new RuntimeException(new StopExecutionException(TextComponent.of("Invalid path")));
}
} catch (IOException ignore) {
}

View File

@ -1,18 +1,12 @@
package com.sk89q.worldedit.command.argument;
import com.google.common.collect.ImmutableSetMultimap;
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.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.World;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.converter.ArgumentConverter;
import org.enginehub.piston.converter.ConversionResult;
import org.enginehub.piston.converter.FailedConversion;
import org.enginehub.piston.converter.MultiKeyConverter;
import org.enginehub.piston.converter.SimpleArgumentConverter;
import org.enginehub.piston.converter.SuccessfulConversion;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
@ -31,9 +25,6 @@ public class ExpressionConverter implements ArgumentConverter<Expression> {
@Override
public ConversionResult<Expression> convert(String s, InjectedValueAccess injectedValueAccess) {
Expression expression;
try {
expression = new Expression(Double.parseDouble(s));
} catch (NumberFormatException e1) {
try {
expression = Expression.compile(s);
expression.optimize();
@ -42,6 +33,4 @@ public class ExpressionConverter implements ArgumentConverter<Expression> {
return FailedConversion.from(e);
}
}
return SuccessfulConversion.fromSingle(expression);
}
}

View File

@ -0,0 +1,44 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.factory;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.EditContext;
import com.sk89q.worldedit.function.generator.ForestGenerator;
import com.sk89q.worldedit.util.TreeGenerator;
public final class TreeGeneratorFactory implements Contextual<ForestGenerator> {
private final TreeGenerator.TreeType type;
public TreeGeneratorFactory(TreeGenerator.TreeType type) {
this.type = type;
}
@Override
public ForestGenerator createFromContext(EditContext input) {
return new ForestGenerator((EditSession) input.getDestination(), type);
}
@Override
public String toString() {
return "tree of type " + type;
}
}

View File

@ -23,6 +23,7 @@ import com.boydti.fawe.object.mask.IdMask;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
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;
@ -35,6 +36,8 @@ import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.Set;
/**
* A pickaxe mode that recursively finds adjacent blocks within range of
* an initial block and of the same type.

View File

@ -29,6 +29,7 @@ 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.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
public class GravityBrush implements Brush {
@ -58,10 +59,6 @@ public class GravityBrush implements Brush {
}
}
}
column.clear();
removedBlocks.clear();
}
}
}

View File

@ -62,9 +62,12 @@ import com.sk89q.worldedit.world.block.FuzzyBlockState;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -367,7 +370,7 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
}
}
// this should be impossible but IntelliJ isn't that smart
if (blockType == null) {
if (state == null) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'");
}
@ -398,23 +401,10 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
// Allow setting mob spawn type
if (blockAndExtraData.length > 1) {
String mobName = blockAndExtraData[1];
for (MobType mobType : MobType.values()) {
if (mobType.getName().toLowerCase().equals(mobName.toLowerCase(Locale.ROOT))) {
mobName = mobType.getName();
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())
.map(m -> m.getName().toLowerCase(Locale.ROOT))
.filter(s -> s.startsWith(finalMobName))
.collect(Collectors.toList()));
}
EntityType mobType = EntityTypes.parse(mobName);
return validate(context, new MobSpawnerBlock(state, mobName));
} else {
return validate(context, new MobSpawnerBlock(state, MobType.PIG.getName()));
return validate(context, new MobSpawnerBlock(state, EntityTypes.PIG.getId()));
}
} else if (blockType == BlockTypes.PLAYER_HEAD || blockType == BlockTypes.PLAYER_WALL_HEAD) {
// allow setting type/player/rotation

View File

@ -19,9 +19,16 @@
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 {
@ -48,4 +55,61 @@ public abstract class AbstractNonPlayerActor implements Actor {
@Override
public void dispatchCUIEvent(CUIEvent event) {
}
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();
}
}
});
/**
* 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

@ -498,7 +498,7 @@ public final class PlatformCommandManager {
this.registration.register(
commandManager,
ClipboardCommandsRegistration.builder(),
new ClipboardCommands(worldEdit)
new ClipboardCommands()
);
this.registration.register(
commandManager,
@ -523,7 +523,7 @@ public final class PlatformCommandManager {
this.registration.register(
commandManager,
RegionCommandsRegistration.builder(),
new RegionCommands(worldEdit)
new RegionCommands()
);
this.registration.register(
commandManager,

View File

@ -415,7 +415,6 @@ public class PlatformManager {
player.runAsyncIfFree(() -> reset((DoubleActionTraceTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING),
getConfiguration(), player, session));
event.setCancelled(true);
}
return;
}
@ -429,7 +428,6 @@ public class PlatformManager {
player.runAction(() -> reset((TraceTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING),
getConfiguration(), player, session), false, true);
event.setCancelled(true);
}
return;
}

View File

@ -1,46 +0,0 @@
package com.sk89q.worldedit.extension.platform.binding;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.internal.annotation.Validate;
import java.lang.annotation.Annotation;
public class AnnotatedBindings extends Bindings {
public AnnotatedBindings(WorldEdit worldEdit) {
super(worldEdit);
}
@Validate()
public String getText(String argument, Validate modifier) {
return validate(argument, modifier);
}
/**
* Validate a string value using relevant modifiers.
*
* @param string the string
* @param modifiers the list of modifiers to scan
* @throws InputParseException on a validation error
*/
private static String validate(String string, Annotation... modifiers) {
if (string != null) {
for (Annotation modifier : modifiers) {
if (modifier instanceof Validate) {
Validate validate = (Validate) modifier;
if (!validate.value().isEmpty()) {
if (!string.matches(validate.value())) {
throw new InputParseException(
String.format(
"The given text doesn't match the right format (technically speaking, the 'format' is %s)",
validate.value()));
}
}
}
}
}
return string;
}
}

View File

@ -14,7 +14,6 @@ import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Validate;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.world.World;

View File

@ -10,10 +10,9 @@ import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.annotation.Range;
import com.sk89q.worldedit.internal.expression.EvaluationException;
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.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector2;
@ -37,9 +36,6 @@ public class PrimitiveBindings extends Bindings {
*/
@Binding
public Expression getExpression(String argument) throws ExpressionException {
try {
return new Expression(Double.parseDouble(argument));
} catch (NumberFormatException e1) {
try {
Expression expression = Expression.compile(argument);
expression.optimize();
@ -52,7 +48,6 @@ public class PrimitiveBindings extends Bindings {
"Expected '%s' to be a number or valid math expression (error: %s)", argument, e.getMessage()));
}
}
}
/**
* Gets an {@link com.sk89q.worldedit.extent.Extent} from a {@link ArgumentStack}.

View File

@ -25,11 +25,8 @@ import com.boydti.fawe.object.schematic.PNGWriter;
import com.boydti.fawe.object.schematic.MinecraftStructure;
import com.google.common.collect.ImmutableSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.NamedTag;
import com.sk89q.jnbt.Tag;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@ -38,7 +35,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@ -95,7 +91,7 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
}
BufferedInputStream buffered = new BufferedInputStream(inputStream);
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
return new SpongeSchematicReader(nbtStream);
return new FastSchematicReader(nbtStream);
}
@Override
@ -108,7 +104,7 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
gzip = new PGZIPOutputStream(outputStream);
}
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
return new SpongeSchematicWriter(nbtStream);
return new FastSchematicWriter(nbtStream);
}
@Override

View File

@ -0,0 +1,343 @@
/*
* 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.extent.clipboard.io;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.jnbt.streamer.IntValueReader;
import com.boydti.fawe.jnbt.streamer.StreamDelegate;
import com.boydti.fawe.jnbt.streamer.ValueReader;
import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.clipboard.LinearClipboard;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.DataFixer;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.function.Function;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Reads schematic files using the Sponge Schematic Specification.
*/
public class FastSchematicReader extends NBTSchematicReader {
private static final Logger log = LoggerFactory.getLogger(FastSchematicReader.class);
private final NBTInputStream inputStream;
private DataFixer fixer = null;
private int dataVersion = -1;
private FastByteArrayOutputStream blocksOut;
private FaweOutputStream blocks;
private FastByteArrayOutputStream biomesOut;
private FaweOutputStream biomes;
private List<Map<String, Object>> tiles;
private List<Map<String, Object>> entities;
private int width, height, length;
private int offsetX, offsetY, offsetZ;
private char[] palette, biomePalette;
private BlockVector3 min = BlockVector3.ZERO;
/**
* Create a new instance.
*
* @param inputStream the input stream to read from
*/
public FastSchematicReader(NBTInputStream inputStream) {
checkNotNull(inputStream);
this.inputStream = inputStream;
}
private String fix(String palettePart) {
if (fixer == null || dataVersion == -1) return palettePart;
return fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, palettePart, dataVersion);
}
private CompoundTag fixBlockEntity(CompoundTag tag) {
if (fixer == null || dataVersion == -1) return tag;
return fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, tag, dataVersion);
}
private CompoundTag fixEntity(CompoundTag tag) {
if (fixer == null || dataVersion == -1) return tag;
return fixer.fixUp(DataFixer.FixTypes.ENTITY, tag, dataVersion);
}
public StreamDelegate createDelegate() {
StreamDelegate root = new StreamDelegate();
StreamDelegate schematic = root.add("Schematic");
schematic.add("DataVersion").withInt((i, v) -> dataVersion = v);
schematic.add("Width").withInt((i, v) -> width = v);
schematic.add("Height").withInt((i, v) -> height = v);
schematic.add("Length").withInt((i, v) -> length = v);
schematic.add("Offset").withValue((ValueReader<int[]>) (index, v) -> min = BlockVector3.at(v[0], v[1], v[2]));
StreamDelegate metadata = schematic.add("Metadata");
metadata.add("WEOffsetX").withInt((i, v) -> offsetX = v);
metadata.add("WEOffsetY").withInt((i, v) -> offsetY = v);
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = v);
StreamDelegate paletteDelegate = schematic.add("Palette");
paletteDelegate.withValue((ValueReader<Map<String, Object>>) (ignore, v) -> {
palette = new char[v.size()];
for (Entry<String, Object> entry : v.entrySet()) {
BlockState state = null;
try {
String palettePart = fix(entry.getKey());
state = BlockState.get(palettePart);
} catch (InputParseException e) {
e.printStackTrace();
}
int index = (int) entry.getValue();
palette[index] = (char) state.getOrdinal();
}
});
StreamDelegate blockData = schematic.add("BlockData");
blockData.withInfo((length, type) -> {
blocksOut = new FastByteArrayOutputStream();
blocks = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut));
});
blockData.withInt((index, value) -> blocks.writeVarInt(value));
StreamDelegate tilesDelegate = schematic.add("TileEntities");
tilesDelegate.withInfo((length, type) -> tiles = new ArrayList<>(length));
tilesDelegate.withElem((ValueReader<Map<String, Object>>) (index, tile) -> tiles.add(tile));
StreamDelegate entitiesDelegate = schematic.add("Entities");
entitiesDelegate.withInfo((length, type) -> entities = new ArrayList<>(length));
entitiesDelegate.withElem((ValueReader<Map<String, Object>>) (index, entity) -> entities.add(entity));
StreamDelegate biomeData = schematic.add("BiomeData");
biomeData.withInfo((length, type) -> {
biomesOut = new FastByteArrayOutputStream();
biomes = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut));
});
biomeData.withElem((IntValueReader) (index, value) -> {
try {
biomes.write(value); // byte of varInt
} catch (IOException e) {
e.printStackTrace();
}
});
StreamDelegate biomePaletteDelegate = schematic.add("BiomePalette");
biomePaletteDelegate.withInfo((length, type) -> biomePalette = new char[length]);
biomePaletteDelegate.withElem(new ValueReader<Map.Entry<String, Number>>() {
@Override
public void apply(int index, Map.Entry<String, Number> palettePart) {
String key = palettePart.getKey();
if (fixer != null) {
key = fixer.fixUp(DataFixer.FixTypes.BIOME, key, dataVersion);
}
BiomeType biome = BiomeTypes.get(key);
if (biome == null) {
System. out.println("Unknown biome " + key);
biome = BiomeTypes.FOREST;
}
int paletteIndex = palettePart.getValue().intValue();
biomePalette[paletteIndex] = (char) biome.getInternalId();
}
});
return root;
}
private BlockState getBlockState(int id) {
return BlockTypesCache.states[palette[id]];
}
private BiomeType getBiomeType(FaweInputStream fis) throws IOException {
char biomeId = biomePalette[fis.readVarInt()];
BiomeType biome = BiomeTypes.get(biomeId);
return biome;
}
@Override
public Clipboard read(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException {
StreamDelegate root = createDelegate();
inputStream.readNamedTagLazy(root);
if (blocks != null) blocks.close();
if (biomes != null) biomes.close();
blocks = null;
biomes = null;
BlockVector3 dimensions = BlockVector3.at(width, height, length);
BlockVector3 origin = BlockVector3.ZERO;
if (offsetX != Integer.MIN_VALUE && offsetY != Integer.MIN_VALUE && offsetZ != Integer.MIN_VALUE) {
origin = BlockVector3.at(-offsetX, -offsetY, -offsetZ);
}
Clipboard clipboard = createOutput.apply(dimensions);
if (blocksOut != null && blocksOut.getSize() != 0) {
try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(blocksOut.toByteArrays())))) {
if (clipboard instanceof LinearClipboard) {
LinearClipboard linear = (LinearClipboard) clipboard;
int volume = width * height * length;
if (palette.length < 128) {
for (int index = 0; index < volume; index++) {
linear.setBlock(index, getBlockState(fis.read()));
}
} else {
for (int index = 0; index < volume; index++) {
linear.setBlock(index, getBlockState(fis.readVarInt()));
}
}
} else {
if (palette.length < 128) {
for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) {
clipboard.setBlock(x, y, z, getBlockState(fis.read()));
}
}
}
} else {
for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) {
clipboard.setBlock(x, y, z, getBlockState(fis.readVarInt()));
}
}
}
}
}
}
}
if (biomesOut != null && biomesOut.getSize() != 0) {
try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(biomesOut.toByteArrays())))) {
if (clipboard instanceof LinearClipboard) {
LinearClipboard linear = (LinearClipboard) clipboard;
int volume = width * length;
for (int index = 0; index < volume; index++) {
linear.setBiome(index, getBiomeType(fis));
}
} else {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) {
clipboard.setBiome(x, 0, z, getBiomeType(fis));
}
}
}
}
}
// tiles
if (tiles != null && !tiles.isEmpty()) {
for (Map<String, Object> tileRaw : tiles) {
CompoundTag tile = FaweCache.IMP.asTag(tileRaw);
int[] pos = tile.getIntArray("Pos");
int x,y,z;
if (pos.length != 3) {
if (!tile.containsKey("x") || !tile.containsKey("y") || !tile.containsKey("z")) {
return null;
}
x = tile.getInt("x");
y = tile.getInt("y");
z = tile.getInt("z");
} else {
x = pos[0];
y = pos[1];
z = pos[2];
}
Map<String, Tag> values = tile.getValue();
Tag id = values.get("Id");
if (id != null) {
values.put("x", new IntTag(x));
values.put("y", new IntTag(y));
values.put("z", new IntTag(z));
values.put("id", id);
}
values.remove("Id");
values.remove("Pos");
tile = fixBlockEntity(tile);
clipboard.setTile(x, y, z, tile);
}
}
// entities
if (entities != null && !entities.isEmpty()) {
for (Map<String, Object> entRaw : entities) {
CompoundTag ent = FaweCache.IMP.asTag(entRaw);
Map<String, Tag> value = ent.getValue();
StringTag id = (StringTag) value.get("Id");
if (id == null) {
id = (StringTag) value.get("id");
if (id == null) {
return null;
}
}
value.put("id", id);
value.remove("Id");
EntityType type = EntityTypes.parse(id.getValue());
if (type != null) {
ent = fixEntity(ent);
BaseEntity state = new BaseEntity(type, ent);
Location loc = ent.getEntityLocation(clipboard);
clipboard.createEntity(loc, state);
} else {
log.debug("Invalid entity: " + id);
}
}
}
clipboard.setOrigin(origin);
if (!min.equals(BlockVector3.ZERO)) {
new BlockArrayClipboard(clipboard, min);
}
return clipboard;
}
@Override
public void close() throws IOException {
inputStream.close();
}
}

View File

@ -0,0 +1,341 @@
/*
* 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.extent.clipboard.io;
import com.boydti.fawe.jnbt.streamer.IntValueReader;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.clipboard.LinearClipboard;
import com.boydti.fawe.util.IOUtil;
import com.google.common.collect.Maps;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.visitor.Order;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Writes schematic files using the Sponge schematic format.
*/
public class FastSchematicWriter implements ClipboardWriter {
private static final int CURRENT_VERSION = 2;
private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE;
private final NBTOutputStream outputStream;
/**
* Create a new schematic writer.
*
* @param outputStream the output stream to write to
*/
public FastSchematicWriter(NBTOutputStream outputStream) {
checkNotNull(outputStream);
this.outputStream = outputStream;
}
@Override
public void write(Clipboard clipboard) throws IOException {
// For now always write the latest version. Maybe provide support for earlier if more appear.
write2(clipboard);
}
/**
* Writes a version 2 schematic file.
*
* @param clipboard The clipboard
*/
private void write2(Clipboard clipboard) throws IOException {
Region region = clipboard.getRegion();
BlockVector3 origin = clipboard.getOrigin();
BlockVector3 min = region.getMinimumPoint();
BlockVector3 offset = min.subtract(origin);
int width = region.getWidth();
int height = region.getHeight();
int length = region.getLength();
if (width > MAX_SIZE) {
throw new IllegalArgumentException("Width of region too large for a .schematic");
}
if (height > MAX_SIZE) {
throw new IllegalArgumentException("Height of region too large for a .schematic");
}
if (length > MAX_SIZE) {
throw new IllegalArgumentException("Length of region too large for a .schematic");
}
final DataOutput rawStream = outputStream.getOutputStream();
outputStream.writeLazyCompoundTag("Schematic", out -> {
out.writeNamedTag("DataVersion", WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion());
out.writeNamedTag("Version", CURRENT_VERSION);
out.writeNamedTag("Width", (short) width);
out.writeNamedTag("Height", (short) height);
out.writeNamedTag("Length", (short) length);
// The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin'
out.writeNamedTag("Offset", new int[]{
min.getBlockX(),
min.getBlockY(),
min.getBlockZ(),
});
out.writeLazyCompoundTag("Metadata", out1 -> {
out1.writeNamedTag("WEOffsetX", offset.getBlockX());
out1.writeNamedTag("WEOffsetY", offset.getBlockY());
out1.writeNamedTag("WEOffsetZ", offset.getBlockZ());
});
ByteArrayOutputStream blocksCompressed = new ByteArrayOutputStream();
FaweOutputStream blocksOut = new FaweOutputStream(new DataOutputStream(new LZ4BlockOutputStream(blocksCompressed)));
ByteArrayOutputStream tilesCompressed = new ByteArrayOutputStream();
NBTOutputStream tilesOut = new NBTOutputStream(new LZ4BlockOutputStream(tilesCompressed));
List<Integer> paletteList = new ArrayList<>();
char[] palette = new char[BlockTypesCache.states.length];
Arrays.fill(palette, Character.MAX_VALUE);
int paletteMax = 0;
int numTiles = 0;
Clipboard finalClipboard;
if (clipboard instanceof BlockArrayClipboard) {
finalClipboard = ((BlockArrayClipboard) clipboard).getParent();
} else {
finalClipboard = clipboard;
}
Iterator<BlockVector3> iterator = finalClipboard.iterator(Order.YZX);
while (iterator.hasNext()) {
BlockVector3 pos = iterator.next();
BaseBlock block = pos.getFullBlock(finalClipboard);
CompoundTag nbt = block.getNbtData();
if (nbt != null) {
Map<String, Tag> values = nbt.getValue();
values.remove("id"); // Remove 'id' if it exists. We want 'Id'
// Positions are kept in NBT, we don't want that.
values.remove("x");
values.remove("y");
values.remove("z");
if (!values.containsKey("Id")) {
values.put("Id", new StringTag(block.getNbtId()));
}
values.put("Pos", new IntArrayTag(new int[]{
pos.getX(),
pos.getY(),
pos.getZ()
}));
numTiles++;
tilesOut.writeTagPayload(block.getNbtData());
}
int ordinal = block.getOrdinal();
char value = palette[ordinal];
if (value == Character.MAX_VALUE) {
int size = paletteMax++;
palette[ordinal] = value = (char) size;
paletteList.add(ordinal);
}
blocksOut.writeVarInt(value);
}
// close
tilesOut.close();
blocksOut.close();
out.writeNamedTag("PaletteMax", paletteMax);
out.writeLazyCompoundTag("Palette", out12 -> {
for (int i = 0; i < paletteList.size(); i++) {
int stateOrdinal = paletteList.get(i);
BlockState state = BlockTypesCache.states[stateOrdinal];
out12.writeNamedTag(state.getAsString(), i);
}
});
out.writeNamedTagName("BlockData", NBTConstants.TYPE_BYTE_ARRAY);
rawStream.writeInt(blocksOut.size());
try (LZ4BlockInputStream in = new LZ4BlockInputStream(new ByteArrayInputStream(blocksCompressed.toByteArray()))) {
IOUtil.copy(in, rawStream);
}
if (numTiles != 0) {
out.writeNamedTagName("TileEntities", NBTConstants.TYPE_LIST);
rawStream.write(NBTConstants.TYPE_COMPOUND);
rawStream.writeInt(numTiles);
try (LZ4BlockInputStream in = new LZ4BlockInputStream(new ByteArrayInputStream(tilesCompressed.toByteArray()))) {
IOUtil.copy(in, rawStream);
}
} else {
out.writeNamedEmptyList("TileEntities");
}
if (finalClipboard.hasBiomes()) {
writeBiomes(finalClipboard, out);
}
List<Tag> entities = new ArrayList<>();
for (Entity entity : finalClipboard.getEntities()) {
BaseEntity state = entity.getState();
if (state != null) {
Map<String, Tag> values = new HashMap<>();
// Put NBT provided data
CompoundTag rawTag = state.getNbtData();
if (rawTag != null) {
values.putAll(rawTag.getValue());
}
// Store our location data, overwriting any
values.remove("id");
values.put("Id", new StringTag(state.getType().getId()));
values.put("Pos", writeVector(entity.getLocation()));
values.put("Rotation", writeRotation(entity.getLocation()));
CompoundTag entityTag = new CompoundTag(values);
entities.add(entityTag);
}
}
if (entities.isEmpty()) {
out.writeNamedEmptyList("Entities");
} else {
out.writeNamedTag("Entities", new ListTag(CompoundTag.class, entities));
}
});
}
private void writeBiomes(Clipboard clipboard, NBTOutputStream out) throws IOException {
ByteArrayOutputStream biomesCompressed = new ByteArrayOutputStream();
DataOutputStream biomesOut = new DataOutputStream(new LZ4BlockOutputStream(biomesCompressed));
List<Integer> paletteList = new ArrayList<>();
int[] palette = new int[BiomeTypes.getMaxId() + 1];
Arrays.fill(palette, Integer.MAX_VALUE);
int[] paletteMax = {0};
IntValueReader task = new IntValueReader() {
@Override
public void applyInt(int index, int ordinal) {
try {
int value = palette[ordinal];
if (value == Integer.MAX_VALUE) {
int size = paletteMax[0]++;
palette[ordinal] = value = size;
paletteList.add(ordinal);
}
IOUtil.writeVarInt(biomesOut, value);
} catch (IOException e) {
e.printStackTrace();
}
}
};
BlockVector3 min = clipboard.getMinimumPoint();
int width = clipboard.getRegion().getWidth();
int length = clipboard.getRegion().getLength();
for (int z = 0, i = 0; z < length; z++) {
int z0 = min.getBlockZ() + z;
for (int x = 0; x < width; x++, i++) {
int x0 = min.getBlockX() + x;
BlockVector2 pt = BlockVector2.at(x0, z0);
BiomeType biome = clipboard.getBiome(pt);
task.applyInt(i, biome.getInternalId());
}
}
biomesOut.close();
out.writeNamedTag("BiomePaletteMax", paletteMax[0]);
out.writeLazyCompoundTag("BiomePalette", out12 -> {
for (int i = 0; i < paletteList.size(); i++) {
int ordinal = paletteList.get(i);
BiomeType state = BiomeTypes.get(ordinal);
out12.writeNamedTag(state.getId(), i);
}
});
out.writeNamedTagName("BiomeData", NBTConstants.TYPE_BYTE_ARRAY);
out.writeInt(biomesOut.size());
try (LZ4BlockInputStream in = new LZ4BlockInputStream(new ByteArrayInputStream(biomesCompressed.toByteArray()))) {
IOUtil.copy(in, (DataOutput) out);
}
}
private void writeEntities(Clipboard clipboard, NBTOutputStream schematic) throws IOException {
List<CompoundTag> entities = clipboard.getEntities().stream().map(e -> {
BaseEntity state = e.getState();
if (state == null) {
return null;
}
Map<String, Tag> values = Maps.newHashMap();
CompoundTag rawData = state.getNbtData();
if (rawData != null) {
values.putAll(rawData.getValue());
}
values.remove("id");
values.put("Id", new StringTag(state.getType().getId()));
values.put("Pos", writeVector(e.getLocation().toVector()));
values.put("Rotation", writeRotation(e.getLocation()));
return new CompoundTag(values);
}).filter(Objects::nonNull).collect(Collectors.toList());
if (entities.isEmpty()) {
return;
}
schematic.writeNamedTag("Entities", new ListTag(CompoundTag.class, entities));
}
@Override
public void close() throws IOException {
outputStream.close();
}
}

View File

@ -56,6 +56,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

View File

@ -19,88 +19,63 @@
package com.sk89q.worldedit.extent.clipboard.io;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.streamer.InfoReader;
import com.boydti.fawe.jnbt.streamer.IntValueReader;
import com.boydti.fawe.jnbt.streamer.StreamDelegate;
import com.boydti.fawe.jnbt.streamer.ValueReader;
import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
import com.boydti.fawe.object.clipboard.LinearClipboard;
import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.google.common.collect.Maps;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NamedTag;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.DataFixer;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extension.platform.Capability;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import com.sk89q.worldedit.world.storage.NBTConversions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.function.Function;
import java.util.OptionalInt;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.world.storage.NBTConversions;
import java.util.OptionalInt;
/**
* Reads schematic files using the Sponge Schematic Specification.
*/
@Deprecated // High mem usage + slow
public class SpongeSchematicReader extends NBTSchematicReader {
private static final Logger log = LoggerFactory.getLogger(SpongeSchematicReader.class);
private final NBTInputStream inputStream;
private DataFixer fixer = null;
private int dataVersion = -1;
private FastByteArrayOutputStream blocksOut;
private FaweOutputStream blocks;
private FastByteArrayOutputStream biomesOut;
private FaweOutputStream biomes;
private List<Map<String, Object>> tiles;
private List<Map<String, Object>> entities;
private int width, height, length;
private int offsetX, offsetY, offsetZ;
private char[] palette, biomePalette;
private BlockVector3 min = BlockVector3.ZERO;
private int schematicVersion = -1;
private int dataVersion = -1;
/**
* Create a new instance.
@ -112,107 +87,6 @@ public class SpongeSchematicReader extends NBTSchematicReader {
this.inputStream = inputStream;
}
private String fix(String palettePart) {
if (fixer == null || dataVersion == -1) return palettePart;
return fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, palettePart, dataVersion);
}
private CompoundTag fixBlockEntity(CompoundTag tag) {
if (fixer == null || dataVersion == -1) return tag;
return fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, tag, dataVersion);
}
private CompoundTag fixEntity(CompoundTag tag) {
if (fixer == null || dataVersion == -1) return tag;
return fixer.fixUp(DataFixer.FixTypes.ENTITY, tag, dataVersion);
}
public StreamDelegate createDelegate() {
StreamDelegate root = new StreamDelegate();
StreamDelegate schematic = root.add("Schematic");
schematic.add("DataVersion").withInt((i, v) -> dataVersion = v);
schematic.add("Width").withInt((i, v) -> width = v);
schematic.add("Height").withInt((i, v) -> height = v);
schematic.add("Length").withInt((i, v) -> length = v);
schematic.add("Offset").withValue((ValueReader<int[]>) (index, v) -> min = BlockVector3.at(v[0], v[1], v[2]));
StreamDelegate metadata = schematic.add("Metadata");
metadata.add("WEOffsetX").withInt((i, v) -> offsetX = v);
metadata.add("WEOffsetY").withInt((i, v) -> offsetY = v);
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = v);
StreamDelegate paletteDelegate = schematic.add("Palette");
paletteDelegate.withValue((ValueReader<Map<String, Object>>) (ignore, v) -> {
palette = new char[v.size()];
for (Entry<String, Object> entry : v.entrySet()) {
BlockState state = null;
try {
String palettePart = fix(entry.getKey());
System.out.println("Read " + palettePart);
state = BlockState.get(palettePart);
} catch (InputParseException e) {
e.printStackTrace();
}
int index = (int) entry.getValue();
palette[index] = (char) state.getOrdinal();
}
});
StreamDelegate blockData = schematic.add("BlockData");
blockData.withInfo((length, type) -> {
blocksOut = new FastByteArrayOutputStream();
blocks = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut));
});
blockData.withInt((index, value) -> blocks.writeVarInt(value));
StreamDelegate tilesDelegate = schematic.add("TileEntities");
tilesDelegate.withInfo((length, type) -> tiles = new ArrayList<>(length));
tilesDelegate.withElem((ValueReader<Map<String, Object>>) (index, tile) -> tiles.add(tile));
StreamDelegate entitiesDelegate = schematic.add("Entities");
entitiesDelegate.withInfo((length, type) -> entities = new ArrayList<>(length));
entitiesDelegate.withElem((ValueReader<Map<String, Object>>) (index, entity) -> entities.add(entity));
StreamDelegate biomeData = schematic.add("BiomeData");
biomeData.withInfo((length, type) -> {
biomesOut = new FastByteArrayOutputStream();
biomes = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut));
});
biomeData.withElem((IntValueReader) (index, value) -> {
try {
biomes.write(value); // byte of varInt
} catch (IOException e) {
e.printStackTrace();
}
});
StreamDelegate biomePaletteDelegate = schematic.add("BiomePalette");
biomePaletteDelegate.withInfo((length, type) -> biomePalette = new char[length]);
biomePaletteDelegate.withElem(new ValueReader<Map.Entry<String, Number>>() {
@Override
public void apply(int index, Map.Entry<String, Number> palettePart) {
String key = palettePart.getKey();
if (fixer != null) {
key = fixer.fixUp(DataFixer.FixTypes.BIOME, key, dataVersion);
}
BiomeType biome = BiomeTypes.get(key);
if (biome == null) {
System. out.println("Unknown biome " + key);
biome = BiomeTypes.FOREST;
}
int paletteIndex = palettePart.getValue().intValue();
biomePalette[paletteIndex] = (char) biome.getInternalId();
}
});
return root;
}
private BlockState getBlockState(int id) {
return BlockTypesCache.states[palette[id]];
}
private BiomeType getBiomeType(FaweInputStream fis) throws IOException {
char biomeId = biomePalette[fis.readVarInt()];
BiomeType biome = BiomeTypes.get(biomeId);
return biome;
}
@Override
public Clipboard read() throws IOException {
CompoundTag schematicTag = getBaseTag();
@ -264,141 +138,156 @@ public class SpongeSchematicReader extends NBTSchematicReader {
}
}
@Override
public Clipboard getBaseTag(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException {
StreamDelegate root = createDelegate();
inputStream.readNamedTagLazy(root);
if (blocks != null) blocks.close();
if (biomes != null) biomes.close();
blocks = null;
biomes = null;
private CompoundTag getBaseTag() throws IOException {
NamedTag rootTag = inputStream.readNamedTag();
if (!rootTag.getName().equals("Schematic")) {
throw new IOException("Tag 'Schematic' does not exist or is not first");
}
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
BlockVector3 dimensions = BlockVector3.at(width, height, length);
BlockVector3 origin = BlockVector3.ZERO;
if (offsetX != Integer.MIN_VALUE && offsetY != Integer.MIN_VALUE && offsetZ != Integer.MIN_VALUE) {
origin = BlockVector3.at(-offsetX, -offsetY, -offsetZ);
// Check
Map<String, Tag> schematic = schematicTag.getValue();
schematicVersion = requireTag(schematic, "Version", IntTag.class).getValue();
return schematicTag;
}
Clipboard clipboard = createOutput.apply(dimensions);
private BlockArrayClipboard readVersion1(CompoundTag schematicTag) throws IOException {
BlockVector3 origin;
Region region;
Map<String, Tag> schematic = schematicTag.getValue();
if (blocksOut != null && blocksOut.getSize() != 0) {
try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(blocksOut.toByteArrays())))) {
if (clipboard instanceof LinearClipboard) {
LinearClipboard linear = (LinearClipboard) clipboard;
int volume = width * height * length;
if (palette.length < 128) {
for (int index = 0; index < volume; index++) {
linear.setBlock(index, getBlockState(fis.read()));
}
} else {
for (int index = 0; index < volume; index++) {
linear.setBlock(index, getBlockState(fis.readVarInt()));
}
}
} else {
if (palette.length < 128) {
for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) {
clipboard.setBlock(x, y, z, getBlockState(fis.read()));
}
}
}
} else {
for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) {
clipboard.setBlock(x, y, z, getBlockState(fis.readVarInt()));
}
}
}
}
}
}
}
if (biomesOut != null && biomesOut.getSize() != 0) {
try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(biomesOut.toByteArrays())))) {
if (clipboard instanceof LinearClipboard) {
LinearClipboard linear = (LinearClipboard) clipboard;
int volume = width * length;
for (int index = 0; index < volume; index++) {
linear.setBiome(index, getBiomeType(fis));
}
} else {
for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) {
clipboard.setBiome(x, 0, z, getBiomeType(fis));
}
}
}
}
}
// tiles
if (tiles != null && !tiles.isEmpty()) {
for (Map<String, Object> tileRaw : tiles) {
CompoundTag tile = FaweCache.IMP.asTag(tileRaw);
int width = requireTag(schematic, "Width", ShortTag.class).getValue();
int height = requireTag(schematic, "Height", ShortTag.class).getValue();
int length = requireTag(schematic, "Length", ShortTag.class).getValue();
int[] pos = tile.getIntArray("Pos");
int x,y,z;
if (pos.length != 3) {
if (!tile.containsKey("x") || !tile.containsKey("y") || !tile.containsKey("z")) {
return null;
IntArrayTag offsetTag = getTag(schematic, "Offset", IntArrayTag.class);
int[] offsetParts;
if (offsetTag != null) {
offsetParts = offsetTag.getValue();
if (offsetParts.length != 3) {
throw new IOException("Invalid offset specified in schematic.");
}
x = tile.getInt("x");
y = tile.getInt("y");
z = tile.getInt("z");
} else {
x = pos[0];
y = pos[1];
z = pos[2];
offsetParts = new int[] {0, 0, 0};
}
Map<String, Tag> values = tile.getValue();
Tag id = values.get("Id");
if (id != null) {
values.put("x", new IntTag(x));
values.put("y", new IntTag(y));
values.put("z", new IntTag(z));
values.put("id", id);
BlockVector3 min = BlockVector3.at(offsetParts[0], offsetParts[1], offsetParts[2]);
CompoundTag metadataTag = getTag(schematic, "Metadata", CompoundTag.class);
if (metadataTag != null && metadataTag.containsKey("WEOffsetX")) {
// We appear to have WorldEdit Metadata
Map<String, Tag> metadata = metadataTag.getValue();
int offsetX = requireTag(metadata, "WEOffsetX", IntTag.class).getValue();
int offsetY = requireTag(metadata, "WEOffsetY", IntTag.class).getValue();
int offsetZ = requireTag(metadata, "WEOffsetZ", IntTag.class).getValue();
BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ);
origin = min.subtract(offset);
region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE));
} else {
origin = min;
region = new CuboidRegion(origin, origin.add(width, height, length).subtract(BlockVector3.ONE));
}
IntTag paletteMaxTag = getTag(schematic, "PaletteMax", IntTag.class);
Map<String, Tag> paletteObject = requireTag(schematic, "Palette", CompoundTag.class).getValue();
if (paletteMaxTag != null && paletteObject.size() != paletteMaxTag.getValue()) {
throw new IOException("Block palette size does not match expected size.");
}
Map<Integer, BlockState> palette = new HashMap<>();
ParserContext parserContext = new ParserContext();
parserContext.setRestricted(false);
parserContext.setTryLegacy(false);
parserContext.setPreferringWildcard(false);
for (String palettePart : paletteObject.keySet()) {
int id = requireTag(paletteObject, palettePart, IntTag.class).getValue();
if (fixer != null) {
palettePart = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, palettePart, dataVersion);
}
BlockState state;
try {
state = WorldEdit.getInstance().getBlockFactory().parseFromInput(palettePart, parserContext).toImmutableState();
} catch (InputParseException e) {
log.warn("Invalid BlockState in palette: " + palettePart + ". Block will be replaced with air.");
state = BlockTypes.AIR.getDefaultState();
}
palette.put(id, state);
}
byte[] blocks = requireTag(schematic, "BlockData", ByteArrayTag.class).getValue();
Map<BlockVector3, Map<String, Tag>> tileEntitiesMap = new HashMap<>();
ListTag tileEntities = getTag(schematic, "BlockEntities", ListTag.class);
if (tileEntities == null) {
tileEntities = getTag(schematic, "TileEntities", ListTag.class);
}
if (tileEntities != null) {
List<Map<String, Tag>> tileEntityTags = tileEntities.getValue().stream()
.map(tag -> (CompoundTag) tag)
.map(CompoundTag::getValue)
.collect(Collectors.toList());
for (Map<String, Tag> tileEntity : tileEntityTags) {
int[] pos = requireTag(tileEntity, "Pos", IntArrayTag.class).getValue();
final BlockVector3 pt = BlockVector3.at(pos[0], pos[1], pos[2]);
Map<String, Tag> values = Maps.newHashMap(tileEntity);
values.put("x", new IntTag(pt.getBlockX()));
values.put("y", new IntTag(pt.getBlockY()));
values.put("z", new IntTag(pt.getBlockZ()));
values.put("id", values.get("Id"));
values.remove("Id");
values.remove("Pos");
tile = fixBlockEntity(tile);
clipboard.setTile(x, y, z, tile);
}
}
// entities
if (entities != null && !entities.isEmpty()) {
for (Map<String, Object> entRaw : entities) {
CompoundTag ent = FaweCache.IMP.asTag(entRaw);
Map<String, Tag> value = ent.getValue();
StringTag id = (StringTag) value.get("Id");
if (id == null) {
id = (StringTag) value.get("id");
if (id == null) {
return null;
}
}
value.put("id", id);
value.remove("Id");
EntityType type = EntityTypes.parse(id.getValue());
if (type != null) {
ent = fixEntity(ent);
BaseEntity state = new BaseEntity(type, ent);
Location loc = ent.getEntityLocation(clipboard);
clipboard.createEntity(loc, state);
if (fixer != null) {
tileEntity = fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, new CompoundTag(values), dataVersion).getValue();
} else {
log.debug("Invalid entity: " + id);
}
tileEntity = values;
}
tileEntitiesMap.put(pt, tileEntity);
}
}
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
clipboard.setOrigin(origin);
if (!min.equals(BlockVector3.ZERO)) {
new BlockArrayClipboard(clipboard, min);
int index = 0;
int i = 0;
int value;
int varintLength;
while (i < blocks.length) {
value = 0;
varintLength = 0;
while (true) {
value |= (blocks[i] & 127) << (varintLength++ * 7);
if (varintLength > 5) {
throw new IOException("VarInt too big (probably corrupted data)");
}
if ((blocks[i] & 128) != 128) {
i++;
break;
}
i++;
}
// index = (y * length * width) + (z * width) + x
int y = index / (width * length);
int z = (index % (width * length)) / width;
int x = (index % (width * length)) % width;
BlockState state = palette.get(value);
BlockVector3 pt = BlockVector3.at(x, y, z);
try {
if (tileEntitiesMap.containsKey(pt)) {
clipboard.setBlock(clipboard.getMinimumPoint().add(pt), state.toBaseBlock(new CompoundTag(tileEntitiesMap.get(pt))));
} else {
clipboard.setBlock(clipboard.getMinimumPoint().add(pt), state);
}
} catch (WorldEditException e) {
throw new IOException("Failed to load a block in the schematic");
}
index++;
}
return clipboard;

View File

@ -19,61 +19,45 @@
package com.sk89q.worldedit.extent.clipboard.io;
import com.boydti.fawe.jnbt.streamer.IntValueReader;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Maps;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.clipboard.LinearClipboard;
import com.boydti.fawe.util.IOUtil;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.FloatTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.FloatTag;
import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.visitor.Order;
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.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.sk89q.worldedit.math.Vector3;
import java.util.Objects;
import com.sk89q.worldedit.util.Location;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Writes schematic files using the Sponge schematic format.
*/
@Deprecated // High mem usage + slow
public class SpongeSchematicWriter implements ClipboardWriter {
private static final int CURRENT_VERSION = 2;
@ -94,15 +78,16 @@ public class SpongeSchematicWriter implements ClipboardWriter {
@Override
public void write(Clipboard clipboard) throws IOException {
// For now always write the latest version. Maybe provide support for earlier if more appear.
write2(clipboard);
outputStream.writeNamedTag("Schematic", new CompoundTag(write2(clipboard)));
}
/**
* Writes a version 2 schematic file.
*
* @param clipboard The clipboard
* @return The schematic map
*/
private void write2(Clipboard clipboard) throws IOException {
private Map<String, Tag> write2(Clipboard clipboard) {
Region region = clipboard.getRegion();
BlockVector3 origin = clipboard.getOrigin();
BlockVector3 min = region.getMinimumPoint();
@ -121,51 +106,46 @@ public class SpongeSchematicWriter implements ClipboardWriter {
throw new IllegalArgumentException("Length of region too large for a .schematic");
}
final DataOutput rawStream = outputStream.getOutputStream();
outputStream.writeLazyCompoundTag("Schematic", out -> {
out.writeNamedTag("DataVersion", WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion());
out.writeNamedTag("Version", CURRENT_VERSION);
out.writeNamedTag("Width", (short) width);
out.writeNamedTag("Height", (short) height);
out.writeNamedTag("Length", (short) length);
Map<String, Tag> schematic = new HashMap<>();
schematic.put("Version", new IntTag(CURRENT_VERSION));
schematic.put("DataVersion", new IntTag(
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion()));
Map<String, Tag> metadata = new HashMap<>();
metadata.put("WEOffsetX", new IntTag(offset.getBlockX()));
metadata.put("WEOffsetY", new IntTag(offset.getBlockY()));
metadata.put("WEOffsetZ", new IntTag(offset.getBlockZ()));
schematic.put("Metadata", new CompoundTag(metadata));
schematic.put("Width", new ShortTag((short) width));
schematic.put("Height", new ShortTag((short) height));
schematic.put("Length", new ShortTag((short) length));
// The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin'
out.writeNamedTag("Offset", new int[]{
schematic.put("Offset", new IntArrayTag(new int[]{
min.getBlockX(),
min.getBlockY(),
min.getBlockZ(),
});
}));
out.writeLazyCompoundTag("Metadata", out1 -> {
out1.writeNamedTag("WEOffsetX", offset.getBlockX());
out1.writeNamedTag("WEOffsetY", offset.getBlockY());
out1.writeNamedTag("WEOffsetZ", offset.getBlockZ());
});
ByteArrayOutputStream blocksCompressed = new ByteArrayOutputStream();
FaweOutputStream blocksOut = new FaweOutputStream(new DataOutputStream(new LZ4BlockOutputStream(blocksCompressed)));
ByteArrayOutputStream tilesCompressed = new ByteArrayOutputStream();
NBTOutputStream tilesOut = new NBTOutputStream(new LZ4BlockOutputStream(tilesCompressed));
List<Integer> paletteList = new ArrayList<>();
char[] palette = new char[BlockTypesCache.states.length];
Arrays.fill(palette, Character.MAX_VALUE);
int paletteMax = 0;
int numTiles = 0;
Clipboard finalClipboard;
if (clipboard instanceof BlockArrayClipboard) {
finalClipboard = ((BlockArrayClipboard) clipboard).getParent();
} else {
finalClipboard = clipboard;
}
Iterator<BlockVector3> iterator = finalClipboard.iterator(Order.YZX);
while (iterator.hasNext()) {
BlockVector3 pos = iterator.next();
BaseBlock block = pos.getFullBlock(finalClipboard);
CompoundTag nbt = block.getNbtData();
if (nbt != null) {
Map<String, Tag> values = nbt.getValue();
Map<String, Integer> palette = new HashMap<>();
List<CompoundTag> tileEntities = new ArrayList<>();
ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length);
for (int y = 0; y < height; y++) {
int y0 = min.getBlockY() + y;
for (int z = 0; z < length; z++) {
int z0 = min.getBlockZ() + z;
for (int x = 0; x < width; x++) {
int x0 = min.getBlockX() + x;
BlockVector3 point = BlockVector3.at(x0, y0, z0);
BaseBlock block = clipboard.getFullBlock(point);
if (block.getNbtData() != null) {
Map<String, Tag> values = new HashMap<>(block.getNbtData().getValue());
values.remove("id"); // Remove 'id' if it exists. We want 'Id'
@ -173,170 +153,55 @@ public class SpongeSchematicWriter implements ClipboardWriter {
values.remove("x");
values.remove("y");
values.remove("z");
if (!values.containsKey("Id")) {
values.put("Id", new StringTag(block.getNbtId()));
}
values.put("Pos", new IntArrayTag(new int[]{
pos.getX(),
pos.getY(),
pos.getZ()
x,
y,
z
}));
numTiles++;
tilesOut.writeTagPayload(block.getNbtData());
tileEntities.add(new CompoundTag(values));
}
int ordinal = block.getOrdinal();
char value = palette[ordinal];
if (value == Character.MAX_VALUE) {
int size = paletteMax++;
palette[ordinal] = value = (char) size;
paletteList.add(ordinal);
}
blocksOut.writeVarInt(value);
}
// close
tilesOut.close();
blocksOut.close();
out.writeNamedTag("PaletteMax", paletteMax);
out.writeLazyCompoundTag("Palette", out12 -> {
for (int i = 0; i < paletteList.size(); i++) {
int stateOrdinal = paletteList.get(i);
BlockState state = BlockTypesCache.states[stateOrdinal];
out12.writeNamedTag(state.getAsString(), i);
}
});
out.writeNamedTagName("BlockData", NBTConstants.TYPE_BYTE_ARRAY);
rawStream.writeInt(blocksOut.size());
try (LZ4BlockInputStream in = new LZ4BlockInputStream(new ByteArrayInputStream(blocksCompressed.toByteArray()))) {
IOUtil.copy(in, rawStream);
}
if (numTiles != 0) {
out.writeNamedTagName("TileEntities", NBTConstants.TYPE_LIST);
rawStream.write(NBTConstants.TYPE_COMPOUND);
rawStream.writeInt(numTiles);
try (LZ4BlockInputStream in = new LZ4BlockInputStream(new ByteArrayInputStream(tilesCompressed.toByteArray()))) {
IOUtil.copy(in, rawStream);
}
String blockKey = block.toImmutableState().getAsString();
int blockId;
if (palette.containsKey(blockKey)) {
blockId = palette.get(blockKey);
} else {
out.writeNamedEmptyList("TileEntities");
blockId = paletteMax;
palette.put(blockKey, blockId);
paletteMax++;
}
if (finalClipboard.hasBiomes()) {
writeBiomes(finalClipboard, out);
while ((blockId & -128) != 0) {
buffer.write(blockId & 127 | 128);
blockId >>>= 7;
}
List<Tag> entities = new ArrayList<>();
for (Entity entity : finalClipboard.getEntities()) {
BaseEntity state = entity.getState();
if (state != null) {
Map<String, Tag> values = new HashMap<>();
// Put NBT provided data
CompoundTag rawTag = state.getNbtData();
if (rawTag != null) {
values.putAll(rawTag.getValue());
buffer.write(blockId);
}
// Store our location data, overwriting any
values.remove("id");
values.put("Id", new StringTag(state.getType().getId()));
values.put("Pos", writeVector(entity.getLocation()));
values.put("Rotation", writeRotation(entity.getLocation()));
CompoundTag entityTag = new CompoundTag(values);
entities.add(entityTag);
}
}
if (entities.isEmpty()) {
out.writeNamedEmptyList("Entities");
} else {
out.writeNamedTag("Entities", new ListTag(CompoundTag.class, entities));
}
});
}
private void writeBiomes(Clipboard clipboard, NBTOutputStream out) throws IOException {
ByteArrayOutputStream biomesCompressed = new ByteArrayOutputStream();
DataOutputStream biomesOut = new DataOutputStream(new LZ4BlockOutputStream(biomesCompressed));
List<Integer> paletteList = new ArrayList<>();
int[] palette = new int[BiomeTypes.getMaxId() + 1];
Arrays.fill(palette, Integer.MAX_VALUE);
int[] paletteMax = {0};
IntValueReader task = new IntValueReader() {
@Override
public void applyInt(int index, int ordinal) {
try {
int value = palette[ordinal];
if (value == Integer.MAX_VALUE) {
int size = paletteMax[0]++;
palette[ordinal] = value = size;
paletteList.add(ordinal);
}
IOUtil.writeVarInt(biomesOut, value);
} catch (IOException e) {
e.printStackTrace();
}
}
};
BlockVector3 min = clipboard.getMinimumPoint();
int width = clipboard.getRegion().getWidth();
int length = clipboard.getRegion().getLength();
for (int z = 0, i = 0; z < length; z++) {
int z0 = min.getBlockZ() + z;
for (int x = 0; x < width; x++, i++) {
int x0 = min.getBlockX() + x;
BlockVector2 pt = BlockVector2.at(x0, z0);
BiomeType biome = clipboard.getBiome(pt);
task.applyInt(i, biome.getInternalId());
}
}
biomesOut.close();
out.writeNamedTag("BiomePaletteMax", paletteMax[0]);
out.writeLazyCompoundTag("BiomePalette", out12 -> {
for (int i = 0; i < paletteList.size(); i++) {
int ordinal = paletteList.get(i);
BiomeType state = BiomeTypes.get(ordinal);
out12.writeNamedTag(state.getId(), i);
}
});
out.writeNamedTagName("BiomeData", NBTConstants.TYPE_BYTE_ARRAY);
out.writeInt(biomesOut.size());
try (LZ4BlockInputStream in = new LZ4BlockInputStream(new ByteArrayInputStream(biomesCompressed.toByteArray()))) {
IOUtil.copy(in, (DataOutput) out);
}
}
private void writeEntities(Clipboard clipboard, NBTOutputStream schematic) throws IOException {
List<CompoundTag> entities = clipboard.getEntities().stream().map(e -> {
BaseEntity state = e.getState();
if (state == null) {
return null;
}
Map<String, Tag> values = Maps.newHashMap();
CompoundTag rawData = state.getNbtData();
if (rawData != null) {
values.putAll(rawData.getValue());
}
values.remove("id");
values.put("Id", new StringTag(state.getType().getId()));
values.put("Pos", writeVector(e.getLocation().toVector()));
values.put("Rotation", writeRotation(e.getLocation()));
schematic.put("PaletteMax", new IntTag(paletteMax));
return new CompoundTag(values);
}).filter(Objects::nonNull).collect(Collectors.toList());
if (entities.isEmpty()) {
return;
Map<String, Tag> paletteTag = new HashMap<>();
palette.forEach((key, value) -> paletteTag.put(key, new IntTag(value)));
schematic.put("Palette", new CompoundTag(paletteTag));
schematic.put("BlockData", new ByteArrayTag(buffer.toByteArray()));
schematic.put("BlockEntities", new ListTag(CompoundTag.class, tileEntities));
// version 2 stuff
if (clipboard.hasBiomes()) {
writeBiomes(clipboard, schematic);
}
schematic.writeNamedTag("Entities", new ListTag(CompoundTag.class, entities));
if (!clipboard.getEntities().isEmpty()) {
writeEntities(clipboard, schematic);
}
return schematic;
}
private void writeBiomes(Clipboard clipboard, Map<String, Tag> schematic) {
@ -408,7 +273,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
schematic.put("Entities", new ListTag(CompoundTag.class, entities));
}
private Tag writeVector(Vector3 vector) {
public Tag writeVector(Vector3 vector) {
List<DoubleTag> list = new ArrayList<>();
list.add(new DoubleTag(vector.getX()));
list.add(new DoubleTag(vector.getY()));
@ -416,7 +281,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
return new ListTag(DoubleTag.class, list);
}
private Tag writeRotation(Location location) {
public Tag writeRotation(Location location) {
List<FloatTag> list = new ArrayList<>();
list.add(new FloatTag(location.getYaw()));
list.add(new FloatTag(location.getPitch()));

View File

@ -22,8 +22,8 @@ package com.sk89q.worldedit.function.mask;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
@ -75,7 +75,8 @@ public class ExpressionMask extends AbstractMask {
if (timeout == null) {
return expression.evaluate(vector.getX(), vector.getY(), vector.getZ()) > 0;
} else {
return expression.evaluateTimeout(timeout.getAsInt(), vector.getX(), vector.getY(), vector.getZ()) > 0;
return expression.evaluate(new double[]{vector.getX(), vector.getY(), vector.getZ()},
timeout.getAsInt()) > 0;
}
} catch (EvaluationException e) {
return false;

View File

@ -411,6 +411,7 @@ public class ForwardExtentCopy implements Operation {
}
}
int affected;
affected = region.getArea();
return null;
}

View File

@ -40,7 +40,6 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.io.file.FileSelectionAbortedException;
import com.sk89q.worldedit.util.io.file.FilenameResolutionException;
import com.sk89q.worldedit.util.io.file.InvalidFilenameException;
import com.sk89q.worldedit.world.storage.MissingWorldException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.enginehub.piston.exception.CommandException;

View File

@ -22,25 +22,23 @@ package com.sk89q.worldedit.internal.expression;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.SetMultimap;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.antlr.ExpressionLexer;
import com.sk89q.worldedit.antlr.ExpressionParser;
import com.sk89q.worldedit.session.request.Request;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import com.sk89q.worldedit.session.request.Request;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import java.util.ArrayDeque;
import java.lang.invoke.MethodHandle;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.Stack;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@ -75,7 +73,7 @@ import java.util.concurrent.TimeoutException;
*/
public class Expression {
private static final ThreadLocal<ArrayDeque<Expression>> instance = ThreadLocal.withInitial(ArrayDeque::new);
private static final ThreadLocal<Stack<Expression>> instance = new ThreadLocal<>();
private static final ExecutorService evalThread = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors(),
new ThreadFactoryBuilder()
@ -85,7 +83,6 @@ public class Expression {
private final SlotTable slots = new SlotTable();
private final List<String> providedSlots;
private Variable[] variableArray;
private ExpressionParser.AllStatementsContext root;
private final SetMultimap<String, MethodHandle> functions = Functions.getFunctionMap();
private ExpressionEnvironment environment;
@ -124,43 +121,11 @@ public class Expression {
ParseTreeWalker.DEFAULT.walk(new ExpressionValidator(slots.keySet(), functions), root);
}
public Expression(double constant) {
root = new Constant(0, constant);
}
public double evaluate(double x, double y, double z) throws EvaluationException {
return evaluateTimeout(WorldEdit.getInstance().getConfiguration().calculationTimeout, x, y, z);
}
public double evaluate() throws EvaluationException {
return evaluateFinal(WorldEdit.getInstance().getConfiguration().calculationTimeout);
}
public double evaluate(double... values) throws EvaluationException {
return evaluateTimeout(WorldEdit.getInstance().getConfiguration().calculationTimeout, values);
}
private double evaluateTimeout(int timeout, double x, double y, double z) throws EvaluationException {
if (root instanceof Constant) return root.getValue();
variableArray[0].value = x;
variableArray[1].value = y;
variableArray[2].value = z;
return evaluateFinal(timeout);
}
public double evaluateTimeout(int timeout, double... values) throws EvaluationException {
if (root instanceof Constant) return root.getValue();
for (int i = 0; i < values.length; ++i) {
final Variable var = variableArray[i];
var.value = values[i];
}
return evaluateFinal(timeout);
return evaluate(values, WorldEdit.getInstance().getConfiguration().calculationTimeout);
}
public double evaluate(double[] values, int timeout) throws EvaluationException {
if (root instanceof Constant) {
return root.getValue();
}
for (int i = 0; i < values.length; ++i) {
String slotName = providedSlots.get(i);
LocalSlot.Variable slot = slots.getVariable(slotName)
@ -177,17 +142,6 @@ public class Expression {
return evaluateRootTimed(timeout);
}
private double evaluateFinal(int timeout) throws EvaluationException {
try {
if (timeout < 0) {
return evaluateRoot();
}
return evaluateRootTimed(timeout);
} catch (ReturnException e) {
return e.getValue();
} // other evaluation exceptions are thrown out of this method
}
private double evaluateRootTimed(int timeout) throws EvaluationException {
CountDownLatch startLatch = new CountDownLatch(1);
Request request = Request.request();
@ -233,32 +187,36 @@ public class Expression {
// TODO optimizing
}
public SlotTable getSlots() {
return slots;
}
public RValue getRoot() {
return root;
}
@Override
public String toString() {
return root.toString();
}
public SlotTable getSlots() {
return slots;
}
public static Expression getInstance() {
return instance.get().peek();
}
private void pushInstance() {
ArrayDeque<Expression> foo = instance.get();
foo.push(this);
Stack<Expression> threadLocalExprStack = instance.get();
if (threadLocalExprStack == null) {
instance.set(threadLocalExprStack = new Stack<>());
}
threadLocalExprStack.push(this);
}
private void popInstance() {
ArrayDeque<Expression> foo = instance.get();
Stack<Expression> threadLocalExprStack = instance.get();
foo.pop();
threadLocalExprStack.pop();
if (threadLocalExprStack.isEmpty()) {
instance.set(null);
}
}
public ExpressionEnvironment getEnvironment() {

View File

@ -0,0 +1,52 @@
/*
* 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.math;
public final class BitMath {
public static int mask(int bits) {
return ~(~0 << bits);
}
public static int unpackX(long packed) {
return extractSigned(packed, 0, 26);
}
public static int unpackZ(long packed) {
return extractSigned(packed, 26, 26);
}
public static int unpackY(long packed) {
return extractSigned(packed, 26 + 26, 12);
}
public static int extractSigned(long i, int shift, int bits) {
return fixSign((int) (i >> shift) & mask(bits), bits);
}
public static int fixSign(int i, int bits) {
// Using https://stackoverflow.com/a/29266331/436524
return i << (32 - bits) >> (32 - bits);
}
private BitMath() {
}
}

View File

@ -124,7 +124,7 @@ public abstract class BlockVector3 {
public long toLongPackedForm() {
checkLongPackable(this);
return (x & BITS_26) | ((z & BITS_26) << 26) | (((y & (long) BITS_12) << (26 + 26)));
return (getX() & BITS_26) | ((getZ() & BITS_26) << 26) | (((getY() & (long) BITS_12) << (26 + 26)));
}
public MutableBlockVector3 mutX(double x) {

View File

@ -54,7 +54,15 @@ public interface Subject {
* @param permission the permission
* @return false if the permission was removed, true if this subject has permission
*/
boolean togglePermission(String permission);
default boolean togglePermission(String permission) {
if (this.hasPermission(permission)) {
setPermission(permission, false);
return false;
} else {
setPermission(permission, true);
return true;
}
}
void setPermission(String permission, boolean value);
}

View File

@ -103,15 +103,16 @@ public class BlockType implements FawePattern, Keyed {
return name;
}
}
/*
private BlockState computeDefaultState() {
BlockState defaultState = Iterables.getFirst(getBlockStatesMap().values(), null);
if (values != null) {
defaultState = values.apply(defaultState);
}
return defaultState;
}
*/
@Deprecated
public BlockState withPropertyId(int propertyId) {
if (settings.stateOrdinals == null) return settings.defaultState;

View File

@ -102,7 +102,7 @@ public final class LegacyMapper {
Integer combinedId = getCombinedId(blockEntry.getKey());
final String value = blockEntry.getValue();
blockEntries.put(id, value);
BlockState blockState;
BlockState blockState = null;
try {
blockState = BlockState.get(null, blockEntry.getValue());
BlockType type = blockState.getBlockType();
@ -114,10 +114,10 @@ public final class LegacyMapper {
String newEntry = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, value, 1631);
try {
blockState = WorldEdit.getInstance().getBlockFactory().parseFromInput(newEntry, parserContext).toImmutableState();
} catch (InputParseException ignored) {
log.warn("Unknown block: " + value);
continue;
} catch (InputParseException ignored) {}
}
if (blockState == null) {
log.warn("Unknown block: " + value);
}
}
blockArr[combinedId] = blockState.getInternalId();
@ -135,9 +135,21 @@ public final class LegacyMapper {
}
for (Map.Entry<String, String> itemEntry : dataFile.items.entrySet()) {
try {
itemMap.put(getCombinedId(itemEntry.getKey()), ItemTypes.get(itemEntry.getValue()));
String id = itemEntry.getKey();
String value = itemEntry.getValue();
ItemType type = ItemTypes.get(value);
if (type == null && fixer != null) {
value = fixer.fixUp(DataFixer.FixTypes.ITEM_TYPE, value, 1631);
type = ItemTypes.get(value);
}
if (type != null) {
try {
itemMap.put(getCombinedId(id), type);
continue;
} catch (Exception e) {
}
}
log.warn("Unknown item: " + value);
}
}