Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-02 17:40:09 +01:00
Fix some merge issues
Dieser Commit ist enthalten in:
Ursprung
0e22d4718a
Commit
60759934a3
@ -21,6 +21,7 @@ repositories {
|
|||||||
maven { url = uri("http://repo.dmulloy2.net/content/groups/public/") }
|
maven { url = uri("http://repo.dmulloy2.net/content/groups/public/") }
|
||||||
maven { url = uri("http://ci.ender.zone/plugin/repository/everything/") }
|
maven { url = uri("http://ci.ender.zone/plugin/repository/everything/") }
|
||||||
maven { url = uri("https://repo.inventivetalent.org/content/groups/public/")}
|
maven { url = uri("https://repo.inventivetalent.org/content/groups/public/")}
|
||||||
|
flatDir {dir(File("lib"))}
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.all {
|
configurations.all {
|
||||||
@ -34,6 +35,7 @@ dependencies {
|
|||||||
"api"(project(":worldedit-core"))
|
"api"(project(":worldedit-core"))
|
||||||
"api"(project(":worldedit-libs:core"))
|
"api"(project(":worldedit-libs:core"))
|
||||||
"api"(project(":worldedit-libs:bukkit"))
|
"api"(project(":worldedit-libs:bukkit"))
|
||||||
|
"compile"(":worldedit-adapters:")
|
||||||
"compile"("it.unimi.dsi:fastutil:8.2.1")
|
"compile"("it.unimi.dsi:fastutil:8.2.1")
|
||||||
"api"("com.destroystokyo.paper:paper-api:1.14.4-R0.1-SNAPSHOT") {
|
"api"("com.destroystokyo.paper:paper-api:1.14.4-R0.1-SNAPSHOT") {
|
||||||
exclude("junit", "junit")
|
exclude("junit", "junit")
|
||||||
|
@ -230,16 +230,6 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
|||||||
|| plugin.getPermissionsResolver().hasPermission(player.getWorld().getName(), player, perm);
|
|| 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
|
@Override
|
||||||
public boolean isAllowedToFly() {
|
public boolean isAllowedToFly() {
|
||||||
return player.getAllowFlight();
|
return player.getAllowFlight();
|
||||||
@ -257,13 +247,13 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
|||||||
* - The `/wea` command will give/remove the required bypass permission
|
* - The `/wea` command will give/remove the required bypass permission
|
||||||
*/
|
*/
|
||||||
if (Fawe.<FaweBukkit>imp().getVault() == null || Fawe.<FaweBukkit> imp().getVault().permission == null) {
|
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) {
|
} else if (value) {
|
||||||
if (!Fawe.<FaweBukkit> imp().getVault().permission.playerAdd(player, permission)) {
|
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)) {
|
} 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ plugins {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven { url = uri("http://ci.athion.net/job/PlotSquared-breaking/ws/mvn/") }
|
maven { url = uri("http://ci.athion.net/job/PlotSquared-breaking/ws/mvn/") }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
applyPlatformAndCoreConfiguration()
|
applyPlatformAndCoreConfiguration()
|
||||||
@ -23,7 +24,7 @@ configurations.all {
|
|||||||
dependencies {
|
dependencies {
|
||||||
"compile"(project(":worldedit-libs:core"))
|
"compile"(project(":worldedit-libs:core"))
|
||||||
"compile"("de.schlichtherle:truezip:6.8.3")
|
"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"("org.yaml:snakeyaml:1.23")
|
||||||
"compile"("com.google.guava:guava:21.0")
|
"compile"("com.google.guava:guava:21.0")
|
||||||
"compile"("com.google.code.findbugs:jsr305:3.0.2")
|
"compile"("com.google.code.findbugs:jsr305:3.0.2")
|
||||||
|
@ -16,10 +16,9 @@ import com.sk89q.worldedit.extension.platform.Actor;
|
|||||||
import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
|
import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
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.Expression;
|
||||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
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.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -39,6 +38,8 @@ public class BrushSettings {
|
|||||||
SCROLL_ACTION,
|
SCROLL_ACTION,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Expression DEFAULT_SIZE = Expression.compile("1");
|
||||||
|
|
||||||
private final Map<SettingType, Object> constructor = new ConcurrentHashMap<>();
|
private final Map<SettingType, Object> constructor = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private Brush brush;
|
private Brush brush;
|
||||||
@ -46,7 +47,7 @@ public class BrushSettings {
|
|||||||
private Mask sourceMask;
|
private Mask sourceMask;
|
||||||
private ResettableExtent transform;
|
private ResettableExtent transform;
|
||||||
private Pattern material;
|
private Pattern material;
|
||||||
private Expression size = new Expression(1);
|
private Expression size = DEFAULT_SIZE;
|
||||||
private Set<String> permissions;
|
private Set<String> permissions;
|
||||||
private Scroll scrollAction;
|
private Scroll scrollAction;
|
||||||
private String lastWorld;
|
private String lastWorld;
|
||||||
@ -135,7 +136,7 @@ public class BrushSettings {
|
|||||||
transform = null;
|
transform = null;
|
||||||
material = null;
|
material = null;
|
||||||
scrollAction = null;
|
scrollAction = null;
|
||||||
size = new Expression(1);
|
size = DEFAULT_SIZE;
|
||||||
permissions.clear();
|
permissions.clear();
|
||||||
constructor.clear();
|
constructor.clear();
|
||||||
return this;
|
return this;
|
||||||
@ -182,7 +183,7 @@ public class BrushSettings {
|
|||||||
public BrushSettings setSize(Expression size) {
|
public BrushSettings setSize(Expression size) {
|
||||||
checkNotNull(size);
|
checkNotNull(size);
|
||||||
this.size = size;
|
this.size = size;
|
||||||
if (size.getRoot() instanceof Constant && ((Constant) size.getRoot()).getValue() == -1) {
|
if (size == DEFAULT_SIZE) {
|
||||||
constructor.remove(SettingType.SIZE);
|
constructor.remove(SettingType.SIZE);
|
||||||
} else {
|
} else {
|
||||||
constructor.put(SettingType.SIZE, size.toString());
|
constructor.put(SettingType.SIZE, size.toString());
|
||||||
@ -191,7 +192,7 @@ public class BrushSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BrushSettings setSize(double size) {
|
public BrushSettings setSize(double size) {
|
||||||
return setSize(new Expression(size));
|
return setSize(Expression.compile(Double.toString(size)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BrushSettings setScrollAction(Scroll scrollAction) {
|
public BrushSettings setScrollAction(Scroll scrollAction) {
|
||||||
|
@ -3,9 +3,9 @@ package com.boydti.fawe.object.pattern;
|
|||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import com.sk89q.worldedit.function.pattern.AbstractPattern;
|
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.Expression;
|
||||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
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.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
|
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -49,7 +49,7 @@ public class ExpressionPattern extends AbstractPattern {
|
|||||||
((WorldEditExpressionEnvironment) expression.getEnvironment()).setCurrentBlock(vector.toVector3());
|
((WorldEditExpressionEnvironment) expression.getEnvironment()).setCurrentBlock(vector.toVector3());
|
||||||
}
|
}
|
||||||
double combined = expression.evaluate(vector.getX(), vector.getY(), vector.getZ());
|
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) {
|
} catch (EvaluationException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return BlockTypes.AIR.getDefaultState().toBaseBlock();
|
return BlockTypes.AIR.getDefaultState().toBaseBlock();
|
||||||
|
@ -22,7 +22,7 @@ import com.sk89q.worldedit.EditSession;
|
|||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
|
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.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@ -78,7 +78,7 @@ public class FaweSchematicHandler extends SchematicHandler {
|
|||||||
if (cTag instanceof CompressedSchematicTag) {
|
if (cTag instanceof CompressedSchematicTag) {
|
||||||
Clipboard clipboard = (Clipboard) cTag.getSource();
|
Clipboard clipboard = (Clipboard) cTag.getSource();
|
||||||
try (OutputStream stream = new FileOutputStream(tmp); NBTOutputStream output = new NBTOutputStream(new BufferedOutputStream(new PGZIPOutputStream(stream)))) {
|
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 {
|
} else {
|
||||||
try (OutputStream stream = new FileOutputStream(tmp); BufferedOutputStream output = new BufferedOutputStream(new PGZIPOutputStream(stream))) {
|
try (OutputStream stream = new FileOutputStream(tmp); BufferedOutputStream output = new BufferedOutputStream(new PGZIPOutputStream(stream))) {
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ package com.sk89q.jnbt;
|
|||||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||||
import com.boydti.fawe.object.io.FastByteArraysInputStream;
|
import com.boydti.fawe.object.io.FastByteArraysInputStream;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
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.LZ4BlockInputStream;
|
||||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ public class CompressedSchematicTag extends CompressedCompoundTag<Clipboard> {
|
|||||||
FastByteArrayOutputStream blocksOut = new FastByteArrayOutputStream();
|
FastByteArrayOutputStream blocksOut = new FastByteArrayOutputStream();
|
||||||
try (LZ4BlockOutputStream lz4out = new LZ4BlockOutputStream(blocksOut)) {
|
try (LZ4BlockOutputStream lz4out = new LZ4BlockOutputStream(blocksOut)) {
|
||||||
NBTOutputStream nbtOut = new NBTOutputStream(lz4out);
|
NBTOutputStream nbtOut = new NBTOutputStream(lz4out);
|
||||||
new SpongeSchematicWriter(nbtOut).write(getSource());
|
new FastSchematicWriter(nbtOut).write(getSource());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,7 @@ import com.sk89q.worldedit.world.block.BlockState;
|
|||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
|
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.slf4j.Logger;
|
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.
|
* Stack a cuboid region. For compatibility, entities are copied by biomes are not.
|
||||||
* Use {@link #stackCuboidRegion(Region, BlockVector3, int, boolean, boolean, boolean)} to fine tune.
|
* 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 region the region to stack
|
||||||
* @param dir the direction to stack
|
* @param dir the direction to stack
|
||||||
@ -1439,7 +1454,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
|||||||
* @return number of blocks affected
|
* @return number of blocks affected
|
||||||
* @throws MaxChangedBlocksException thrown if too many blocks are changed
|
* @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(region);
|
||||||
checkNotNull(dir);
|
checkNotNull(dir);
|
||||||
checkArgument(count >= 1, "count >= 1 required");
|
checkArgument(count >= 1, "count >= 1 required");
|
||||||
@ -1451,14 +1467,10 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
|||||||
copy.setCopyingBiomes(copyBiomes);
|
copy.setCopyingBiomes(copyBiomes);
|
||||||
copy.setRepetitions(count);
|
copy.setRepetitions(count);
|
||||||
copy.setTransform(new AffineTransform().translate(dir.multiply(size)));
|
copy.setTransform(new AffineTransform().translate(dir.multiply(size)));
|
||||||
Mask sourceMask = getSourceMask();
|
mask = MaskIntersection.of(getSourceMask(), mask).optimize();
|
||||||
if (sourceMask != null) {
|
if (mask != Masks.alwaysTrue()) {
|
||||||
new MaskTraverser(sourceMask).reset(EditSession.this);
|
|
||||||
copy.setSourceMask(sourceMask);
|
|
||||||
setSourceMask(null);
|
setSourceMask(null);
|
||||||
}
|
copy.setSourceMask(mask);
|
||||||
if (!copyAir) {
|
|
||||||
copy.setSourceMask(new ExistingBlockMask(this));
|
|
||||||
}
|
}
|
||||||
Operations.completeBlindly(copy);
|
Operations.completeBlindly(copy);
|
||||||
return this.changes = copy.getAffected();
|
return this.changes = copy.getAffected();
|
||||||
@ -2327,15 +2339,15 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
|||||||
* @throws MaxChangedBlocksException
|
* @throws MaxChangedBlocksException
|
||||||
*/
|
*/
|
||||||
public int makeShape(final Region region, final Vector3 zero, final Vector3 unit,
|
public int makeShape(final Region region, final Vector3 zero, final Vector3 unit,
|
||||||
final Pattern pattern, final String expressionString, final boolean hollow, final int timeout)
|
final Pattern pattern, final String expressionString, final boolean hollow, final int timeout)
|
||||||
throws ExpressionException, MaxChangedBlocksException {
|
throws ExpressionException, MaxChangedBlocksException {
|
||||||
final Expression expression = Expression.compile(expressionString, "x", "y", "z", "type", "data");
|
final Expression expression = Expression.compile(expressionString, "x", "y", "z", "type", "data");
|
||||||
expression.optimize();
|
expression.optimize();
|
||||||
|
|
||||||
final Variable typeVariable = expression.getSlots().getVariable("type")
|
final Variable typeVariable = expression.getSlots().getVariable("type")
|
||||||
.orElseThrow(IllegalStateException::new);
|
.orElseThrow(IllegalStateException::new);
|
||||||
final Variable dataVariable = expression.getSlots().getVariable("data")
|
final Variable dataVariable = expression.getSlots().getVariable("data")
|
||||||
.orElseThrow(IllegalStateException::new);
|
.orElseThrow(IllegalStateException::new);
|
||||||
|
|
||||||
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
|
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
|
||||||
expression.setEnvironment(environment);
|
expression.setEnvironment(environment);
|
||||||
@ -2349,12 +2361,26 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
|||||||
final Vector3 scaled = current.subtract(zero).divide(unit);
|
final Vector3 scaled = current.subtract(zero).divide(unit);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (expression.evaluateTimeout(timeout, scaled.getX(), scaled.getY(), scaled.getZ(), defaultMaterial.getBlockType().getInternalId(), defaultMaterial.getInternalPropertiesId()) <= 0) {
|
int[] legacy = LegacyMapper.getInstance().getLegacyFromBlock(defaultMaterial.toImmutableState());
|
||||||
// TODO data
|
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 null;
|
||||||
}
|
}
|
||||||
|
int newType = (int) typeVariable.getValue();
|
||||||
return BlockTypes.get((int) typeVariable.getValue()).withPropertyId((int) dataVariable.getValue()).toBaseBlock();
|
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) {
|
} catch (ExpressionTimeoutException e) {
|
||||||
timedOut[0] = timedOut[0] + 1;
|
timedOut[0] = timedOut[0] + 1;
|
||||||
return null;
|
return null;
|
||||||
@ -2404,7 +2430,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
|||||||
final Vector3 scaled = position.toVector3().subtract(zero).divide(unit);
|
final Vector3 scaled = position.toVector3().subtract(zero).divide(unit);
|
||||||
|
|
||||||
// transform
|
// 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 xv = (int) (x.getValue() * unit.getX() + zero2.getX());
|
||||||
int yv = (int) (y.getValue() * unit.getY() + zero2.getY());
|
int yv = (int) (y.getValue() * unit.getY() + zero2.getY());
|
||||||
int zv = (int) (z.getValue() * unit.getZ() + zero2.getZ());
|
int zv = (int) (z.getValue() * unit.getZ() + zero2.getZ());
|
||||||
|
@ -78,6 +78,7 @@ import com.sk89q.worldedit.world.World;
|
|||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.item.ItemType;
|
import com.sk89q.worldedit.world.item.ItemType;
|
||||||
|
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||||
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -147,7 +148,6 @@ public class LocalSession implements TextureHolder {
|
|||||||
private transient ResettableExtent transform = null;
|
private transient ResettableExtent transform = null;
|
||||||
private transient ZoneId timezone = ZoneId.systemDefault();
|
private transient ZoneId timezone = ZoneId.systemDefault();
|
||||||
private transient World currentWorld;
|
private transient World currentWorld;
|
||||||
private transient boolean tickingWatchdog = false;
|
|
||||||
private transient UUID uuid;
|
private transient UUID uuid;
|
||||||
private transient volatile long historySize = 0;
|
private transient volatile long historySize = 0;
|
||||||
|
|
||||||
@ -992,6 +992,8 @@ public class LocalSession implements TextureHolder {
|
|||||||
return getTool(item, player);
|
return getTool(item, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private transient boolean loadDefaults = true;
|
||||||
|
|
||||||
public Tool getTool(BaseItem item, Player player) {
|
public Tool getTool(BaseItem item, Player player) {
|
||||||
if (Settings.IMP.EXPERIMENTAL.PERSISTENT_BRUSHES && item.getNativeItem() != null) {
|
if (Settings.IMP.EXPERIMENTAL.PERSISTENT_BRUSHES && item.getNativeItem() != null) {
|
||||||
BrushTool tool = BrushCache.getTool(player, this, item);
|
BrushTool tool = BrushCache.getTool(player, this, item);
|
||||||
@ -1612,7 +1614,9 @@ public class LocalSession implements TextureHolder {
|
|||||||
|
|
||||||
private void prepareEditingExtents(EditSession editSession, Actor actor) {
|
private void prepareEditingExtents(EditSession editSession, Actor actor) {
|
||||||
editSession.setFastMode(fastMode);
|
editSession.setFastMode(fastMode);
|
||||||
|
/*
|
||||||
editSession.setReorderMode(reorderMode);
|
editSession.setReorderMode(reorderMode);
|
||||||
|
*/
|
||||||
if (editSession.getSurvivalExtent() != null) {
|
if (editSession.getSurvivalExtent() != null) {
|
||||||
editSession.getSurvivalExtent().setStripNbt(!actor.hasPermission("worldedit.setnbt"));
|
editSession.getSurvivalExtent().setStripNbt(!actor.hasPermission("worldedit.setnbt"));
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,6 @@ import com.sk89q.worldedit.extent.inventory.BlockBag;
|
|||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
import com.sk89q.worldedit.internal.expression.Expression;
|
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.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.scripting.CraftScriptContext;
|
import com.sk89q.worldedit.scripting.CraftScriptContext;
|
||||||
import com.sk89q.worldedit.scripting.CraftScriptEngine;
|
import com.sk89q.worldedit.scripting.CraftScriptEngine;
|
||||||
@ -397,8 +395,8 @@ public final class WorldEdit {
|
|||||||
|
|
||||||
public void checkMaxBrushRadius(Expression radius) throws MaxBrushRadiusException {
|
public void checkMaxBrushRadius(Expression radius) throws MaxBrushRadiusException {
|
||||||
if (getConfiguration().maxBrushRadius > 0) {
|
if (getConfiguration().maxBrushRadius > 0) {
|
||||||
RValue r = radius.getRoot();
|
double val = radius.evaluate();
|
||||||
if (r instanceof Constant && ((Constant) r).getValue() > getConfiguration().maxBrushRadius) {
|
if (val > getConfiguration().maxBrushRadius) {
|
||||||
throw new MaxBrushRadiusException();
|
throw new MaxBrushRadiusException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ public class ApplyBrushCommands {
|
|||||||
Contextual<? extends RegionFunction> generatorFactory) throws WorldEditException {
|
Contextual<? extends RegionFunction> generatorFactory) throws WorldEditException {
|
||||||
double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class));
|
double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class));
|
||||||
RegionFactory regionFactory = REGION_FACTORY.value(parameters).asSingle(RegionFactory.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");
|
new Apply(generatorFactory), regionFactory, "worldedit.brush.apply");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ import com.sk89q.worldedit.function.operation.Operations;
|
|||||||
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
|
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
|
||||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.regions.FlatRegion;
|
import com.sk89q.worldedit.regions.FlatRegion;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
@ -98,9 +98,8 @@ import com.sk89q.worldedit.function.mask.SingleBlockTypeMask;
|
|||||||
import com.sk89q.worldedit.function.operation.Operation;
|
import com.sk89q.worldedit.function.operation.Operation;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
import com.sk89q.worldedit.internal.annotation.ClipboardMask;
|
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.Expression;
|
||||||
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.math.Vector3;
|
import com.sk89q.worldedit.math.Vector3;
|
||||||
import com.sk89q.worldedit.regions.factory.RegionFactory;
|
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.annotation.param.Switch;
|
||||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||||
import org.enginehub.piston.inject.Key;
|
import org.enginehub.piston.inject.Key;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -308,7 +308,7 @@ public class BrushCommands {
|
|||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.brush.spline")
|
@CommandPermissions("worldedit.brush.spline")
|
||||||
public void catenaryBrush(InjectedValueAccess context, @Arg(desc = "Pattern") Pattern fill,
|
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")
|
@Arg(desc = "The radius to sample for blending", def = "0")
|
||||||
Expression radius,
|
Expression radius,
|
||||||
@Switch(name = 'h', desc = "Create only a shell")
|
@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,
|
public void stencilBrush(LocalSession session, InjectedValueAccess context, @Arg(desc = "Pattern") Pattern fill,
|
||||||
@Arg(desc = "Expression", def = "5") Expression radius,
|
@Arg(desc = "Expression", def = "5") Expression radius,
|
||||||
@Arg(desc = "String", def = "") String image,
|
@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,
|
@Arg(desc = "double", def = "1") double yscale,
|
||||||
@Switch(name = 'w', desc = "Apply at maximum saturation") boolean onlyWhite,
|
@Switch(name = 'w', desc = "Apply at maximum saturation") boolean onlyWhite,
|
||||||
@Switch(name = 'r', desc = "Apply random rotation") boolean randomRotate) throws WorldEditException, FileNotFoundException {
|
@Switch(name = 'r', desc = "Apply random rotation") boolean randomRotate) throws WorldEditException, FileNotFoundException {
|
||||||
@ -470,7 +470,7 @@ public class BrushCommands {
|
|||||||
@Arg(desc = "Expression", def = "5")
|
@Arg(desc = "Expression", def = "5")
|
||||||
Expression radius,
|
Expression radius,
|
||||||
ProvideBindings.ImageUri imageUri,
|
ProvideBindings.ImageUri imageUri,
|
||||||
@Arg(def = "1", desc = "scale height") @Range(min = Double.MIN_NORMAL)
|
@Arg(def = "1", desc = "scale height")
|
||||||
double yscale,
|
double yscale,
|
||||||
@Switch(name = 'a', desc = "Use image Alpha")
|
@Switch(name = 'a', desc = "Use image Alpha")
|
||||||
boolean alpha,
|
boolean alpha,
|
||||||
@ -660,13 +660,14 @@ public class BrushCommands {
|
|||||||
boolean ignoreAir,
|
boolean ignoreAir,
|
||||||
@Switch(name = 'o', desc = "Paste starting at the target location, instead of centering on it")
|
@Switch(name = 'o', desc = "Paste starting at the target location, instead of centering on it")
|
||||||
boolean usingOrigin,
|
boolean usingOrigin,
|
||||||
@Switch(name = 'e', desc = "Paste entities if available")
|
@Switch(name = 'e', desc = "Skip paste entities if available")
|
||||||
boolean pasteEntities,
|
boolean skipEntities,
|
||||||
@Switch(name = 'b', desc = "Paste biomes if available")
|
@Switch(name = 'b', desc = "Paste biomes if available")
|
||||||
boolean pasteBiomes,
|
boolean pasteBiomes,
|
||||||
@ArgFlag(name = 'm', desc = "Skip blocks matching this mask in the clipboard", def = "")
|
@ArgFlag(name = 'm', desc = "Skip blocks matching this mask in the clipboard", def = "")
|
||||||
@ClipboardMask
|
@ClipboardMask
|
||||||
Mask sourceMask) throws WorldEditException {
|
Mask sourceMask,
|
||||||
|
InjectedValueAccess context) throws WorldEditException {
|
||||||
ClipboardHolder holder = session.getClipboard();
|
ClipboardHolder holder = session.getClipboard();
|
||||||
|
|
||||||
Clipboard clipboard = holder.getClipboard();
|
Clipboard clipboard = holder.getClipboard();
|
||||||
@ -695,7 +696,8 @@ public class BrushCommands {
|
|||||||
@Arg(desc = "The number of iterations to perform", def = "4")
|
@Arg(desc = "The number of iterations to perform", def = "4")
|
||||||
int iterations,
|
int iterations,
|
||||||
@Arg(desc = "The mask of blocks to use for the heightmap", def = "")
|
@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);
|
worldEdit.checkMaxBrushRadius(radius);
|
||||||
|
|
||||||
FaweLimit limit = Settings.IMP.getLimit(player);
|
FaweLimit limit = Settings.IMP.getLimit(player);
|
||||||
@ -752,7 +754,7 @@ public class BrushCommands {
|
|||||||
"Snow Pic: https://i.imgur.com/Hrzn0I4.png"
|
"Snow Pic: https://i.imgur.com/Hrzn0I4.png"
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.brush.height")
|
@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);
|
terrainBrush(session, radius, image, rotation, yscale, false, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -768,7 +770,7 @@ public class BrushCommands {
|
|||||||
Expression radius,
|
Expression radius,
|
||||||
@Arg(desc = "String", def = "")
|
@Arg(desc = "String", def = "")
|
||||||
String image,
|
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,
|
int rotation,
|
||||||
@Arg(desc = "double", def = "1")
|
@Arg(desc = "double", def = "1")
|
||||||
double yscale,
|
double yscale,
|
||||||
@ -787,7 +789,7 @@ public class BrushCommands {
|
|||||||
desc = "This brush raises or lowers land towards the clicked point"
|
desc = "This brush raises or lowers land towards the clicked point"
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.brush.height")
|
@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")
|
@Switch(name = 'r', desc = "Enables random off-axis rotation")
|
||||||
boolean randomRotate,
|
boolean randomRotate,
|
||||||
@Switch(name = 'l', desc = "Will work on snow layers")
|
@Switch(name = 'l', desc = "Will work on snow layers")
|
||||||
|
@ -39,10 +39,12 @@ import com.boydti.fawe.util.MaskTraverser;
|
|||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.command.util.CommandPermissions;
|
import com.sk89q.worldedit.command.util.CommandPermissions;
|
||||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||||
import com.sk89q.worldedit.command.util.Logging;
|
import com.sk89q.worldedit.command.util.Logging;
|
||||||
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.event.extent.PasteEvent;
|
import com.sk89q.worldedit.event.extent.PasteEvent;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
@ -314,8 +316,8 @@ public class ClipboardCommands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final LocalConfiguration config = this.worldEdit.getConfiguration();
|
final LocalConfiguration config = WorldEdit.getInstance().getConfiguration();
|
||||||
final File working = this.worldEdit.getWorkingDirectoryFile(config.saveDir).getAbsoluteFile();
|
final File working = WorldEdit.getInstance().getWorkingDirectoryFile(config.saveDir).getAbsoluteFile();
|
||||||
|
|
||||||
url = MainUtil.upload(null, null, "zip", new RunnableVal<OutputStream>() {
|
url = MainUtil.upload(null, null, "zip", new RunnableVal<OutputStream>() {
|
||||||
@Override
|
@Override
|
||||||
@ -484,7 +486,7 @@ public class ClipboardCommands {
|
|||||||
uri = ((URIClipboardHolder) holder).getURI(clipboard);
|
uri = ((URIClipboardHolder) holder).getURI(clipboard);
|
||||||
}
|
}
|
||||||
PasteEvent event = new PasteEvent(player, clipboard, uri, editSession, to);
|
PasteEvent event = new PasteEvent(player, clipboard, uri, editSession, to);
|
||||||
worldEdit.getEventBus().post(event);
|
WorldEdit.getInstance().getEventBus().post(event);
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
|
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MANUAL);
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,7 @@ public class GeneralCommands {
|
|||||||
desc = "Set the global mask"
|
desc = "Set the global mask"
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.global-texture")
|
@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>
|
// gtexture <randomize> <min=0> <max=100>
|
||||||
// TODO NOT IMPLEMENTED convert this to an ArgumentConverter
|
// TODO NOT IMPLEMENTED convert this to an ArgumentConverter
|
||||||
if (arguments.isEmpty()) {
|
if (arguments.isEmpty()) {
|
||||||
@ -375,7 +375,7 @@ public class GeneralCommands {
|
|||||||
} else {
|
} else {
|
||||||
ParserContext parserContext = new ParserContext();
|
ParserContext parserContext = new ParserContext();
|
||||||
parserContext.setActor(player);
|
parserContext.setActor(player);
|
||||||
parserContext.setWorld(world);
|
parserContext.setWorld(worldArg);
|
||||||
parserContext.setSession(session);
|
parserContext.setSession(session);
|
||||||
parserContext.setExtent(editSession);
|
parserContext.setExtent(editSession);
|
||||||
Mask mask = worldEdit.getMaskFactory().parseFromInput(arg, parserContext);
|
Mask mask = worldEdit.getMaskFactory().parseFromInput(arg, parserContext);
|
||||||
|
@ -47,8 +47,8 @@ import com.sk89q.worldedit.function.operation.Operations;
|
|||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||||
import com.sk89q.worldedit.internal.annotation.Radii;
|
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.annotation.Selection;
|
||||||
|
import com.sk89q.worldedit.internal.expression.Expression;
|
||||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
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 static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commands for the generation of shapes and other objects.
|
* Commands for the generation of shapes and other objects.
|
||||||
@ -173,7 +174,7 @@ public class GenerationCommands {
|
|||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.generation.ore")
|
@CommandPermissions("worldedit.generation.ore")
|
||||||
@Logging(PLACEMENT)
|
@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(() -> {
|
actor.checkConfirmationRegion(() -> {
|
||||||
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
|
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
|
||||||
BBC.VISITOR_BLOCK.send(actor, editSession.getBlockChangeCount());
|
BBC.VISITOR_BLOCK.send(actor, editSession.getBlockChangeCount());
|
||||||
@ -186,15 +187,14 @@ public class GenerationCommands {
|
|||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.generation.cylinder")
|
@CommandPermissions("worldedit.generation.cylinder")
|
||||||
@Logging(PLACEMENT)
|
@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")
|
@Arg(desc = "The pattern of blocks to generate")
|
||||||
Pattern pattern,
|
Pattern pattern,
|
||||||
@Arg(desc = "The radii of the cylinder. 1st is N/S, 2nd is E/W")
|
@Arg(desc = "The radii of the cylinder. 1st is N/S, 2nd is E/W")
|
||||||
@Radii(2)
|
BlockVector2 radii,
|
||||||
List<Double> radii,
|
|
||||||
@Arg(desc = "The height of the cylinder", def = "1")
|
@Arg(desc = "The height of the cylinder", def = "1")
|
||||||
int height) throws WorldEditException {
|
int height) throws WorldEditException {
|
||||||
return cyl(actor, session, editSession, pattern, radii, height, true);
|
cyl(actor, session, editSession, pattern, radii, height, true, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
@ -206,7 +206,7 @@ public class GenerationCommands {
|
|||||||
public void cyl(Actor actor, LocalSession session, EditSession editSession,
|
public void cyl(Actor actor, LocalSession session, EditSession editSession,
|
||||||
@Arg(desc = "The pattern of blocks to generate")
|
@Arg(desc = "The pattern of blocks to generate")
|
||||||
Pattern pattern,
|
Pattern pattern,
|
||||||
@Arg(desc = "The radii of the cylinder. Order is N/S, E/W") BlockVector2 radius,
|
@Arg(desc = "The radii of the cylinder. Order is N/S, E/W") BlockVector2 radius,
|
||||||
@Arg(desc = "The height of the cylinder", def = "1")
|
@Arg(desc = "The height of the cylinder", def = "1")
|
||||||
int height,
|
int height,
|
||||||
@Switch(name = 'h', desc = "Make a hollow cylinder")
|
@Switch(name = 'h', desc = "Make a hollow cylinder")
|
||||||
@ -293,9 +293,12 @@ public class GenerationCommands {
|
|||||||
@Logging(POSITION)
|
@Logging(POSITION)
|
||||||
public int pumpkins(Actor actor, LocalSession session, EditSession editSession,
|
public int pumpkins(Actor actor, LocalSession session, EditSession editSession,
|
||||||
@Arg(desc = "The size of the patch", def = "10")
|
@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);
|
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.");
|
actor.print(affected + " pumpkin patches created.");
|
||||||
return affected;
|
return affected;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,6 @@ import com.sk89q.worldedit.command.util.CommandPermissions;
|
|||||||
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.internal.annotation.Range;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Location;
|
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.Arg;
|
||||||
import org.enginehub.piston.annotation.param.Switch;
|
import org.enginehub.piston.annotation.param.Switch;
|
||||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ public class HistoryCommands {
|
|||||||
" - Import from disk: /frb #import"
|
" - Import from disk: /frb #import"
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.history.rollback")
|
@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) {
|
if (!Settings.IMP.HISTORY.USE_DATABASE) {
|
||||||
BBC.SETTING_DISABLE.send(player, "history.use-database (Import with /frb #import )");
|
BBC.SETTING_DISABLE.send(player, "history.use-database (Import with /frb #import )");
|
||||||
return;
|
return;
|
||||||
@ -214,32 +214,22 @@ public class HistoryCommands {
|
|||||||
" - Import from disk: /frb #import"
|
" - Import from disk: /frb #import"
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.history.rollback")
|
@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);
|
faweRollback(player, session, user, radius, time, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "/undo",
|
name = "/undo",
|
||||||
aliases = { "/un", "/ud", "undo" },
|
aliases = { "/un", "/ud", "undo" },
|
||||||
desc = "Undoes the last action (from history)"
|
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"})
|
@CommandPermissions({"worldedit.history.undo", "worldedit.history.undo.self"})
|
||||||
public void undo(Player player, LocalSession session,
|
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,
|
int times,
|
||||||
@Arg(name = "player", desc = "Undo this player's operations", def = "")
|
@Arg(name = "player", desc = "Undo this player's operations", def = "")
|
||||||
String playerName,
|
String playerName,
|
||||||
InjectedValueAccess context) throws WorldEditException {
|
InjectedValueAccess context) throws WorldEditException {
|
||||||
times = Math.max(1, times);
|
times = Math.max(1, times);
|
||||||
LocalSession undoSession;
|
LocalSession undoSession;
|
||||||
if (session.hasFastMode()) {
|
if (session.hasFastMode()) {
|
||||||
@ -253,6 +243,16 @@ public class HistoryCommands {
|
|||||||
BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, playerName);
|
BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, playerName);
|
||||||
return;
|
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);
|
worldEdit.flushBlockBag(player, undone);
|
||||||
}
|
}
|
||||||
if (undone == null) i--;
|
if (undone == null) i--;
|
||||||
@ -272,7 +272,7 @@ public class HistoryCommands {
|
|||||||
)
|
)
|
||||||
@CommandPermissions({"worldedit.history.redo", "worldedit.history.redo.self"})
|
@CommandPermissions({"worldedit.history.redo", "worldedit.history.redo.self"})
|
||||||
public void redo(Player player, LocalSession session,
|
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,
|
int times,
|
||||||
@Arg(name = "player", desc = "Redo this player's operations", def = "")
|
@Arg(name = "player", desc = "Redo this player's operations", def = "")
|
||||||
String playerName) throws WorldEditException {
|
String playerName) throws WorldEditException {
|
||||||
|
@ -39,8 +39,8 @@ import com.sk89q.worldedit.function.mask.OffsetMask;
|
|||||||
import com.sk89q.worldedit.function.mask.RegionMask;
|
import com.sk89q.worldedit.function.mask.RegionMask;
|
||||||
import com.sk89q.worldedit.function.mask.SolidBlockMask;
|
import com.sk89q.worldedit.function.mask.SolidBlockMask;
|
||||||
import com.sk89q.worldedit.internal.expression.Expression;
|
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.ExpressionException;
|
||||||
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.math.Vector3;
|
import com.sk89q.worldedit.math.Vector3;
|
||||||
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
|
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
|
||||||
|
@ -104,7 +104,7 @@ public class PaintBrushCommands {
|
|||||||
double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class));
|
double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class));
|
||||||
double density = requireNonNull(DENSITY.value(parameters).asSingle(double.class)) / 100;
|
double density = requireNonNull(DENSITY.value(parameters).asSingle(double.class)) / 100;
|
||||||
RegionFactory regionFactory = REGION_FACTORY.value(parameters).asSingle(RegionFactory.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 Paint(generatorFactory, density), regionFactory, "worldedit.brush.paint");
|
new Paint(generatorFactory, density), regionFactory, "worldedit.brush.paint");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,6 @@ import com.sk89q.worldedit.function.mask.Mask;
|
|||||||
import com.sk89q.worldedit.function.pattern.ClipboardPattern;
|
import com.sk89q.worldedit.function.pattern.ClipboardPattern;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
import com.sk89q.worldedit.function.pattern.RandomPattern;
|
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.Expression;
|
||||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||||
import com.sk89q.worldedit.math.Vector3;
|
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.Command;
|
||||||
import org.enginehub.piston.annotation.CommandContainer;
|
import org.enginehub.piston.annotation.CommandContainer;
|
||||||
import org.enginehub.piston.annotation.param.Arg;
|
import org.enginehub.piston.annotation.param.Arg;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
//@Command(aliases = {"patterns"},
|
//@Command(aliases = {"patterns"},
|
||||||
// desc = "Help for the various patterns. [More Info](https://git.io/vSPmA)",
|
// 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" +
|
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"
|
" - 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);
|
return new IdDataMaskPattern(extent, pattern, bitmask);
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,6 @@ import com.sk89q.worldedit.function.pattern.Pattern;
|
|||||||
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
|
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
|
||||||
import com.sk89q.worldedit.function.visitor.LayerVisitor;
|
import com.sk89q.worldedit.function.visitor.LayerVisitor;
|
||||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
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.annotation.Selection;
|
||||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
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.ArgFlag;
|
||||||
import org.enginehub.piston.annotation.param.Switch;
|
import org.enginehub.piston.annotation.param.Switch;
|
||||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -254,7 +254,7 @@ public class RegionCommands {
|
|||||||
desc = "Set block lighting in a selection"
|
desc = "Set block lighting in a selection"
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.light.set")
|
@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
|
// TODO NOT IMPLEMENTED
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ public class RegionCommands {
|
|||||||
desc = "Set sky lighting in a selection"
|
desc = "Set sky lighting in a selection"
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.light.set")
|
@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
|
// TODO NOT IMPLEMENTED
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,7 +314,7 @@ public class RegionCommands {
|
|||||||
boolean shell, InjectedValueAccess context) throws WorldEditException {
|
boolean shell, InjectedValueAccess context) throws WorldEditException {
|
||||||
if (!(region instanceof ConvexPolyhedralRegion)) {
|
if (!(region instanceof ConvexPolyhedralRegion)) {
|
||||||
actor.printError("//curve only works with convex polyhedral selections");
|
actor.printError("//curve only works with convex polyhedral selections");
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
checkCommandArgument(thickness >= 0, "Thickness must be >= 0");
|
checkCommandArgument(thickness >= 0, "Thickness must be >= 0");
|
||||||
|
|
||||||
@ -523,22 +523,24 @@ public class RegionCommands {
|
|||||||
@CommandPermissions("worldedit.region.move")
|
@CommandPermissions("worldedit.region.move")
|
||||||
@Logging(ORIENTATION_REGION)
|
@Logging(ORIENTATION_REGION)
|
||||||
public void move(Actor actor, World world, EditSession editSession, LocalSession session,
|
public void move(Actor actor, World world, EditSession editSession, LocalSession session,
|
||||||
@Selection Region region,
|
@Selection Region region,
|
||||||
@Arg(desc = "# of blocks to move", def = "1")
|
@Arg(desc = "# of blocks to move", def = "1")
|
||||||
int count,
|
int count,
|
||||||
@Arg(desc = "The direction to move", def = Direction.AIM)
|
@Arg(desc = "The direction to move", def = Direction.AIM)
|
||||||
@Direction(includeDiagonals = true)
|
@Direction(includeDiagonals = true)
|
||||||
BlockVector3 direction,
|
BlockVector3 direction,
|
||||||
@Arg(desc = "The pattern of blocks to leave", def = "air")
|
@Arg(desc = "The pattern of blocks to leave", def = "air")
|
||||||
Pattern replace,
|
Pattern replace,
|
||||||
@Switch(name = 's', desc = "Shift the selection to the target location")
|
@Switch(name = 's', desc = "Shift the selection to the target location")
|
||||||
boolean moveSelection,
|
boolean moveSelection,
|
||||||
@Switch(name = 'a', desc = "Ignore air blocks")
|
@Switch(name = 'a', desc = "Ignore air blocks")
|
||||||
boolean ignoreAirBlocks,
|
boolean ignoreAirBlocks,
|
||||||
@Switch(name = 'e', desc = "Ignore entities")
|
@Switch(name = 'e', desc = "Skip copy entities")
|
||||||
boolean skipEntities,
|
boolean skipEntities,
|
||||||
@Switch(name = 'b', desc = "Also copy biomes")
|
@Switch(name = 'b', desc = "Also copy biomes")
|
||||||
boolean copyBiomes,
|
boolean copyBiomes,
|
||||||
|
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air", def = "")
|
||||||
|
Mask mask,
|
||||||
InjectedValueAccess context) throws WorldEditException {
|
InjectedValueAccess context) throws WorldEditException {
|
||||||
checkCommandArgument(count >= 1, "Count must be >= 1");
|
checkCommandArgument(count >= 1, "Count must be >= 1");
|
||||||
|
|
||||||
@ -554,7 +556,7 @@ public class RegionCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actor.checkConfirmationRegion(() -> {
|
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) {
|
if (moveSelection) {
|
||||||
try {
|
try {
|
||||||
@ -612,7 +614,7 @@ public class RegionCommands {
|
|||||||
@Switch(name = 'b', desc = "Also copy biomes")
|
@Switch(name = 'b', desc = "Also copy biomes")
|
||||||
boolean copyBiomes,
|
boolean copyBiomes,
|
||||||
@ArgFlag(name = 'm', desc = "Source mask", def="")
|
@ArgFlag(name = 'm', desc = "Source mask", def="")
|
||||||
Mask sourceMask,
|
Mask mask,
|
||||||
InjectedValueAccess context) throws WorldEditException {
|
InjectedValueAccess context) throws WorldEditException {
|
||||||
|
|
||||||
Mask combinedMask;
|
Mask combinedMask;
|
||||||
@ -627,9 +629,6 @@ public class RegionCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actor.checkConfirmationStack(() -> {
|
actor.checkConfirmationStack(() -> {
|
||||||
if (sourceMask != null) {
|
|
||||||
editSession.addSourceMask(sourceMask);
|
|
||||||
}
|
|
||||||
int affected = editSession.stackCuboidRegion(region, direction, count, !skipEntities, copyBiomes, combinedMask);
|
int affected = editSession.stackCuboidRegion(region, direction, count, !skipEntities, copyBiomes, combinedMask);
|
||||||
|
|
||||||
if (moveSelection) {
|
if (moveSelection) {
|
||||||
@ -751,7 +750,7 @@ public class RegionCommands {
|
|||||||
@Logging(REGION)
|
@Logging(REGION)
|
||||||
public void hollow(Actor actor, EditSession editSession,
|
public void hollow(Actor actor, EditSession editSession,
|
||||||
@Selection Region region,
|
@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,
|
int thickness,
|
||||||
@Arg(desc = "The pattern of blocks to replace the hollowed area with", def = "air")
|
@Arg(desc = "The pattern of blocks to replace the hollowed area with", def = "air")
|
||||||
Pattern pattern,
|
Pattern pattern,
|
||||||
@ -799,6 +798,7 @@ public class RegionCommands {
|
|||||||
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density / 100));
|
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density / 100));
|
||||||
Operations.completeLegacy(visitor);
|
Operations.completeLegacy(visitor);
|
||||||
|
|
||||||
|
int affected = ground.getAffected();
|
||||||
actor.print(affected + " flora created.");
|
actor.print(affected + " flora created.");
|
||||||
}, "/flora", region, context);
|
}, "/flora", region, context);
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
private List<File> getFiles(ClipboardHolder clipboard) {
|
||||||
Collection<URI> uris = Collections.emptyList();
|
Collection<URI> uris = Collections.emptyList();
|
||||||
if (clipboard instanceof URIClipboardHolder) {
|
if (clipboard instanceof URIClipboardHolder) {
|
||||||
@ -853,17 +810,43 @@ public class SchematicCommands {
|
|||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.schematic.delete")
|
@CommandPermissions("worldedit.schematic.delete")
|
||||||
public void delete(Actor actor,
|
public void delete(Actor actor,
|
||||||
|
LocalSession session,
|
||||||
@Arg(desc = "File name.")
|
@Arg(desc = "File name.")
|
||||||
String filename) throws WorldEditException {
|
String filename) throws WorldEditException, IOException {
|
||||||
LocalConfiguration config = worldEdit.getConfiguration();
|
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,
|
if (filename.equalsIgnoreCase("*")) {
|
||||||
dir, filename, "schematic", ClipboardFormats.getFileExtensionArray());
|
files.addAll(getFiles(session.getClipboard()));
|
||||||
|
} else {
|
||||||
|
File f = MainUtil.resolveRelative(new File(dir, filename));
|
||||||
|
files.add(f);
|
||||||
|
}
|
||||||
|
|
||||||
if (!f.exists()) {
|
if (files.isEmpty()) {
|
||||||
actor.printError("Schematic " + filename + " does not exist!");
|
actor.printError(BBC.SCHEMATIC_NONE.s());
|
||||||
return;
|
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) {
|
private boolean delete(File file) {
|
||||||
if (file.delete()) {
|
if (file.delete()) {
|
||||||
new File(file.getParentFile(), "." + file.getName() + ".cached").delete();
|
new File(file.getParentFile(), "." + file.getName() + ".cached").delete();
|
||||||
|
@ -58,15 +58,6 @@ public class ScriptingCommands {
|
|||||||
this.worldEdit = worldEdit;
|
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(
|
@Command(
|
||||||
name = "cs",
|
name = "cs",
|
||||||
desc = "Execute a CraftScript"
|
desc = "Execute a CraftScript"
|
||||||
|
@ -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.event.ClickEvent;
|
||||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||||
import com.sk89q.worldedit.world.World;
|
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.ItemType;
|
||||||
import com.sk89q.worldedit.world.item.ItemTypes;
|
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||||
import com.sk89q.worldedit.world.storage.ChunkStore;
|
import com.sk89q.worldedit.world.storage.ChunkStore;
|
||||||
@ -108,6 +109,7 @@ public class SelectionCommands {
|
|||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "/pos1",
|
name = "/pos1",
|
||||||
|
aliases = "/1",
|
||||||
desc = "Set position 1"
|
desc = "Set position 1"
|
||||||
)
|
)
|
||||||
@Logging(POSITION)
|
@Logging(POSITION)
|
||||||
@ -136,6 +138,7 @@ public class SelectionCommands {
|
|||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "/pos2",
|
name = "/pos2",
|
||||||
|
aliases = "/2",
|
||||||
desc = "Set position 2"
|
desc = "Set position 2"
|
||||||
)
|
)
|
||||||
@Logging(POSITION)
|
@Logging(POSITION)
|
||||||
@ -544,7 +547,7 @@ public class SelectionCommands {
|
|||||||
|
|
||||||
|
|
||||||
if (distribution.isEmpty()) { // *Should* always be false
|
if (distribution.isEmpty()) { // *Should* always be false
|
||||||
actor.printError("No blocks counted.");
|
player.printError("No blocks counted.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,9 +19,6 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.command;
|
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.EditSession;
|
||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
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.snapshot.SnapshotRestore;
|
||||||
import com.sk89q.worldedit.world.storage.ChunkStore;
|
import com.sk89q.worldedit.world.storage.ChunkStore;
|
||||||
import com.sk89q.worldedit.world.storage.MissingWorldException;
|
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.Command;
|
||||||
import org.enginehub.piston.annotation.CommandContainer;
|
import org.enginehub.piston.annotation.CommandContainer;
|
||||||
import org.enginehub.piston.annotation.param.Arg;
|
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)
|
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
||||||
public class SnapshotUtilCommands {
|
public class SnapshotUtilCommands {
|
||||||
|
|
||||||
@ -55,15 +55,15 @@ public class SnapshotUtilCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "restore",
|
name = "restore",
|
||||||
aliases = { "/restore" },
|
aliases = { "/restore" },
|
||||||
desc = "Restore the selection from a snapshot"
|
desc = "Restore the selection from a snapshot"
|
||||||
)
|
)
|
||||||
@Logging(REGION)
|
@Logging(REGION)
|
||||||
@CommandPermissions("worldedit.snapshots.restore")
|
@CommandPermissions("worldedit.snapshots.restore")
|
||||||
public void restore(Actor actor, World world, LocalSession session, EditSession editSession,
|
public void restore(Actor actor, World world, LocalSession session, EditSession editSession,
|
||||||
@Arg(name = "snapshot", desc = "The snapshot to restore", def = "")
|
@Arg(name = "snapshot", desc = "The snapshot to restore", def = "")
|
||||||
String snapshotName) throws WorldEditException {
|
String snapshotName) throws WorldEditException {
|
||||||
|
|
||||||
LocalConfiguration config = we.getConfiguration();
|
LocalConfiguration config = we.getConfiguration();
|
||||||
|
|
||||||
@ -98,10 +98,10 @@ public class SnapshotUtilCommands {
|
|||||||
File dir = config.snapshotRepo.getDirectory();
|
File dir = config.snapshotRepo.getDirectory();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
WorldEdit.logger.info("FAWE found no snapshots: looked in: "
|
WorldEdit.logger.info("WorldEdit found no snapshots: looked in: "
|
||||||
+ dir.getCanonicalPath());
|
+ dir.getCanonicalPath());
|
||||||
} catch (IOException e) {
|
} 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?): "
|
+ "(NON-RESOLVABLE PATH - does it exist?): "
|
||||||
+ dir.getPath());
|
+ dir.getPath());
|
||||||
}
|
}
|
||||||
@ -125,6 +125,7 @@ public class SnapshotUtilCommands {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
// Restore snapshot
|
// Restore snapshot
|
||||||
SnapshotRestore restore = new SnapshotRestore(chunkStore, editSession, region);
|
SnapshotRestore restore = new SnapshotRestore(chunkStore, editSession, region);
|
||||||
//player.print(restore.getChunksAffected() + " chunk(s) will be loaded.");
|
//player.print(restore.getChunksAffected() + " chunk(s) will be loaded.");
|
||||||
@ -143,12 +144,15 @@ public class SnapshotUtilCommands {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
actor.print(String.format("Restored; %d "
|
actor.print(String.format("Restored; %d "
|
||||||
+ "missing chunks and %d other errors.",
|
+ "missing chunks and %d other errors.",
|
||||||
restore.getMissingChunks().size(),
|
restore.getMissingChunks().size(),
|
||||||
restore.getErrorChunks().size()));
|
restore.getErrorChunks().size()));
|
||||||
}
|
}
|
||||||
} catch (DataException | IOException e) {
|
} finally {
|
||||||
actor.printError("Failed to load snapshot: " + e.getMessage());
|
try {
|
||||||
|
chunkStore.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
@ -42,13 +42,13 @@ import com.sk89q.worldedit.event.platform.CommandEvent;
|
|||||||
import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
|
import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
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.internal.command.CommandArgParser;
|
||||||
import com.sk89q.worldedit.util.HandSide;
|
import com.sk89q.worldedit.util.HandSide;
|
||||||
import org.enginehub.piston.annotation.Command;
|
import org.enginehub.piston.annotation.Command;
|
||||||
import org.enginehub.piston.annotation.CommandContainer;
|
import org.enginehub.piston.annotation.CommandContainer;
|
||||||
import org.enginehub.piston.annotation.param.Arg;
|
import org.enginehub.piston.annotation.param.Arg;
|
||||||
import org.enginehub.piston.annotation.param.Switch;
|
import org.enginehub.piston.annotation.param.Switch;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ public class ToolUtilCommands {
|
|||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.brush.visualize")
|
@CommandPermissions("worldedit.brush.visualize")
|
||||||
public void visual(Player player, LocalSession session,
|
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)
|
int mode)
|
||||||
throws WorldEditException {
|
throws WorldEditException {
|
||||||
BrushTool tool = session.getBrushTool(player, false);
|
BrushTool tool = session.getBrushTool(player, false);
|
||||||
|
@ -45,6 +45,7 @@ import com.sk89q.worldedit.command.util.Logging;
|
|||||||
import com.sk89q.worldedit.command.util.PrintCommandHelp;
|
import com.sk89q.worldedit.command.util.PrintCommandHelp;
|
||||||
import com.sk89q.worldedit.command.util.SkipQueue;
|
import com.sk89q.worldedit.command.util.SkipQueue;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
||||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
|
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.mask.BlockTypeMask;
|
||||||
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
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.Expression;
|
||||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
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.Arg;
|
||||||
import org.enginehub.piston.annotation.param.ArgFlag;
|
import org.enginehub.piston.annotation.param.ArgFlag;
|
||||||
import org.enginehub.piston.annotation.param.Switch;
|
import org.enginehub.piston.annotation.param.Switch;
|
||||||
|
import org.enginehub.piston.exception.StopExecutionException;
|
||||||
|
import org.jetbrains.annotations.Range;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility commands.
|
* Utility commands.
|
||||||
*/
|
*/
|
||||||
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
@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 {
|
public class UtilityCommands {
|
||||||
|
|
||||||
private final WorldEdit we;
|
private final WorldEdit we;
|
||||||
@ -201,9 +200,9 @@ public class UtilityCommands {
|
|||||||
public int fill(Actor actor, LocalSession session, EditSession editSession,
|
public int fill(Actor actor, LocalSession session, EditSession editSession,
|
||||||
@Arg(desc = "The blocks to fill with")
|
@Arg(desc = "The blocks to fill with")
|
||||||
Pattern pattern,
|
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,
|
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,
|
int depth,
|
||||||
@Arg(desc = "The direction to move", def = "down")
|
@Arg(desc = "The direction to move", def = "down")
|
||||||
@Direction BlockVector3 direction) throws WorldEditException, EvaluationException {
|
@Direction BlockVector3 direction) throws WorldEditException, EvaluationException {
|
||||||
@ -745,7 +744,7 @@ public class UtilityCommands {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (!MainUtil.isInSubDirectory(root, file)) {
|
if (!MainUtil.isInSubDirectory(root, file)) {
|
||||||
throw new RuntimeException(new CommandException("Invalid path"));
|
throw new RuntimeException(new StopExecutionException(TextComponent.of("Invalid path")));
|
||||||
}
|
}
|
||||||
} catch (IOException ignore) {
|
} catch (IOException ignore) {
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
package com.sk89q.worldedit.command.argument;
|
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.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.Component;
|
||||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||||
import com.sk89q.worldedit.world.World;
|
|
||||||
import org.enginehub.piston.CommandManager;
|
import org.enginehub.piston.CommandManager;
|
||||||
import org.enginehub.piston.converter.ArgumentConverter;
|
import org.enginehub.piston.converter.ArgumentConverter;
|
||||||
import org.enginehub.piston.converter.ConversionResult;
|
import org.enginehub.piston.converter.ConversionResult;
|
||||||
import org.enginehub.piston.converter.FailedConversion;
|
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.converter.SuccessfulConversion;
|
||||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||||
import org.enginehub.piston.inject.Key;
|
import org.enginehub.piston.inject.Key;
|
||||||
@ -32,16 +26,11 @@ public class ExpressionConverter implements ArgumentConverter<Expression> {
|
|||||||
public ConversionResult<Expression> convert(String s, InjectedValueAccess injectedValueAccess) {
|
public ConversionResult<Expression> convert(String s, InjectedValueAccess injectedValueAccess) {
|
||||||
Expression expression;
|
Expression expression;
|
||||||
try {
|
try {
|
||||||
expression = new Expression(Double.parseDouble(s));
|
expression = Expression.compile(s);
|
||||||
} catch (NumberFormatException e1) {
|
expression.optimize();
|
||||||
try {
|
return SuccessfulConversion.fromSingle(expression);
|
||||||
expression = Expression.compile(s);
|
} catch (Exception e) {
|
||||||
expression.optimize();
|
return FailedConversion.from(e);
|
||||||
return SuccessfulConversion.fromSingle(expression);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return FailedConversion.from(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return SuccessfulConversion.fromSingle(expression);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import com.boydti.fawe.object.mask.IdMask;
|
|||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.extension.platform.Platform;
|
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.BlockType;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A pickaxe mode that recursively finds adjacent blocks within range of
|
* A pickaxe mode that recursively finds adjacent blocks within range of
|
||||||
* an initial block and of the same type.
|
* an initial block and of the same type.
|
||||||
|
@ -29,6 +29,7 @@ import java.util.LinkedHashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.util.collection.LocatedBlockList;
|
import com.sk89q.worldedit.util.collection.LocatedBlockList;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
|
|
||||||
public class GravityBrush implements Brush {
|
public class GravityBrush implements Brush {
|
||||||
@ -53,15 +54,11 @@ public class GravityBrush implements Brush {
|
|||||||
if (y != freeSpot) {
|
if (y != freeSpot) {
|
||||||
editSession.setBlock((int)x, (int)y, (int)z, BlockTypes.AIR.getDefaultState());
|
editSession.setBlock((int)x, (int)y, (int)z, BlockTypes.AIR.getDefaultState());
|
||||||
editSession.setBlock((int)x, (int)freeSpot, (int)z, block);
|
editSession.setBlock((int)x, (int)freeSpot, (int)z, block);
|
||||||
}
|
}
|
||||||
freeSpot = y + 1;
|
freeSpot = y + 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
column.clear();
|
|
||||||
removedBlocks.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,12 @@ import com.sk89q.worldedit.world.block.FuzzyBlockState;
|
|||||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import com.sk89q.worldedit.world.entity.EntityType;
|
import com.sk89q.worldedit.world.entity.EntityType;
|
||||||
import com.sk89q.worldedit.world.entity.EntityTypes;
|
import com.sk89q.worldedit.world.entity.EntityTypes;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
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
|
// 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 + "'");
|
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
|
// Allow setting mob spawn type
|
||||||
if (blockAndExtraData.length > 1) {
|
if (blockAndExtraData.length > 1) {
|
||||||
String mobName = blockAndExtraData[1];
|
String mobName = blockAndExtraData[1];
|
||||||
for (MobType mobType : MobType.values()) {
|
EntityType mobType = EntityTypes.parse(mobName);
|
||||||
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()));
|
|
||||||
}
|
|
||||||
return validate(context, new MobSpawnerBlock(state, mobName));
|
return validate(context, new MobSpawnerBlock(state, mobName));
|
||||||
} else {
|
} 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) {
|
} else if (blockType == BlockTypes.PLAYER_HEAD || blockType == BlockTypes.PLAYER_WALL_HEAD) {
|
||||||
// allow setting type/player/rotation
|
// allow setting type/player/rotation
|
||||||
|
@ -19,9 +19,16 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.extension.platform;
|
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 com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||||
|
|
||||||
import java.io.File;
|
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 {
|
public abstract class AbstractNonPlayerActor implements Actor {
|
||||||
|
|
||||||
@ -48,4 +55,61 @@ public abstract class AbstractNonPlayerActor implements Actor {
|
|||||||
@Override
|
@Override
|
||||||
public void dispatchCUIEvent(CUIEvent event) {
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,7 +498,7 @@ public final class PlatformCommandManager {
|
|||||||
this.registration.register(
|
this.registration.register(
|
||||||
commandManager,
|
commandManager,
|
||||||
ClipboardCommandsRegistration.builder(),
|
ClipboardCommandsRegistration.builder(),
|
||||||
new ClipboardCommands(worldEdit)
|
new ClipboardCommands()
|
||||||
);
|
);
|
||||||
this.registration.register(
|
this.registration.register(
|
||||||
commandManager,
|
commandManager,
|
||||||
@ -523,7 +523,7 @@ public final class PlatformCommandManager {
|
|||||||
this.registration.register(
|
this.registration.register(
|
||||||
commandManager,
|
commandManager,
|
||||||
RegionCommandsRegistration.builder(),
|
RegionCommandsRegistration.builder(),
|
||||||
new RegionCommands(worldEdit)
|
new RegionCommands()
|
||||||
);
|
);
|
||||||
this.registration.register(
|
this.registration.register(
|
||||||
commandManager,
|
commandManager,
|
||||||
|
@ -415,7 +415,6 @@ public class PlatformManager {
|
|||||||
player.runAsyncIfFree(() -> reset((DoubleActionTraceTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING),
|
player.runAsyncIfFree(() -> reset((DoubleActionTraceTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING),
|
||||||
getConfiguration(), player, session));
|
getConfiguration(), player, session));
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,7 +428,6 @@ public class PlatformManager {
|
|||||||
player.runAction(() -> reset((TraceTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING),
|
player.runAction(() -> reset((TraceTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING),
|
||||||
getConfiguration(), player, session), false, true);
|
getConfiguration(), player, session), false, true);
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,7 +14,6 @@ import com.sk89q.worldedit.extension.platform.Actor;
|
|||||||
import com.sk89q.worldedit.extension.platform.Capability;
|
import com.sk89q.worldedit.extension.platform.Capability;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
import com.sk89q.worldedit.internal.annotation.Direction;
|
||||||
import com.sk89q.worldedit.internal.annotation.Validate;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.util.TreeGenerator;
|
import com.sk89q.worldedit.util.TreeGenerator;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
|
@ -10,10 +10,9 @@ import com.sk89q.worldedit.extension.input.InputParseException;
|
|||||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
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.Expression;
|
||||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
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.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.math.Vector2;
|
import com.sk89q.worldedit.math.Vector2;
|
||||||
@ -38,19 +37,15 @@ public class PrimitiveBindings extends Bindings {
|
|||||||
@Binding
|
@Binding
|
||||||
public Expression getExpression(String argument) throws ExpressionException {
|
public Expression getExpression(String argument) throws ExpressionException {
|
||||||
try {
|
try {
|
||||||
return new Expression(Double.parseDouble(argument));
|
Expression expression = Expression.compile(argument);
|
||||||
} catch (NumberFormatException e1) {
|
expression.optimize();
|
||||||
try {
|
return expression;
|
||||||
Expression expression = Expression.compile(argument);
|
} catch (EvaluationException e) {
|
||||||
expression.optimize();
|
throw new InputParseException(String.format(
|
||||||
return expression;
|
"Expected '%s' to be a valid number (or a valid mathematical expression)", argument));
|
||||||
} catch (EvaluationException e) {
|
} catch (ExpressionException e) {
|
||||||
throw new InputParseException(String.format(
|
throw new InputParseException(String.format(
|
||||||
"Expected '%s' to be a valid number (or a valid mathematical expression)", argument));
|
"Expected '%s' to be a number or valid math expression (error: %s)", argument, e.getMessage()));
|
||||||
} catch (ExpressionException e) {
|
|
||||||
throw new InputParseException(String.format(
|
|
||||||
"Expected '%s' to be a number or valid math expression (error: %s)", argument, e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,11 +25,8 @@ import com.boydti.fawe.object.schematic.PNGWriter;
|
|||||||
import com.boydti.fawe.object.schematic.MinecraftStructure;
|
import com.boydti.fawe.object.schematic.MinecraftStructure;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
import com.sk89q.jnbt.NBTOutputStream;
|
import com.sk89q.jnbt.NBTOutputStream;
|
||||||
import com.sk89q.jnbt.NamedTag;
|
|
||||||
import com.sk89q.jnbt.Tag;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@ -38,7 +35,6 @@ import java.io.FileInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
@ -95,7 +91,7 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
|
|||||||
}
|
}
|
||||||
BufferedInputStream buffered = new BufferedInputStream(inputStream);
|
BufferedInputStream buffered = new BufferedInputStream(inputStream);
|
||||||
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
|
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
|
||||||
return new SpongeSchematicReader(nbtStream);
|
return new FastSchematicReader(nbtStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -108,7 +104,7 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
|
|||||||
gzip = new PGZIPOutputStream(outputStream);
|
gzip = new PGZIPOutputStream(outputStream);
|
||||||
}
|
}
|
||||||
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
|
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
|
||||||
return new SpongeSchematicWriter(nbtStream);
|
return new FastSchematicWriter(nbtStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -56,6 +56,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -19,88 +19,63 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.extent.clipboard.io;
|
package com.sk89q.worldedit.extent.clipboard.io;
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.google.common.collect.Maps;
|
||||||
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.sk89q.jnbt.ByteArrayTag;
|
import com.sk89q.jnbt.ByteArrayTag;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.IntArrayTag;
|
||||||
import com.sk89q.jnbt.IntTag;
|
import com.sk89q.jnbt.IntTag;
|
||||||
|
import com.sk89q.jnbt.ListTag;
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
|
import com.sk89q.jnbt.NamedTag;
|
||||||
|
import com.sk89q.jnbt.ShortTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
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.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
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.BlockArrayClipboard;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.world.DataFixer;
|
import com.sk89q.worldedit.world.DataFixer;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
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.EntityType;
|
||||||
import com.sk89q.worldedit.world.entity.EntityTypes;
|
import com.sk89q.worldedit.world.entity.EntityTypes;
|
||||||
import com.sk89q.worldedit.extension.platform.Platform;
|
import com.sk89q.worldedit.world.storage.NBTConversions;
|
||||||
import com.sk89q.worldedit.extension.platform.Capability;
|
|
||||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
|
||||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.UUID;
|
import java.util.OptionalInt;
|
||||||
import java.util.function.Function;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
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.
|
* Reads schematic files using the Sponge Schematic Specification.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated // High mem usage + slow
|
||||||
public class SpongeSchematicReader extends NBTSchematicReader {
|
public class SpongeSchematicReader extends NBTSchematicReader {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SpongeSchematicReader.class);
|
private static final Logger log = LoggerFactory.getLogger(SpongeSchematicReader.class);
|
||||||
private final NBTInputStream inputStream;
|
private final NBTInputStream inputStream;
|
||||||
private DataFixer fixer = null;
|
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 schematicVersion = -1;
|
||||||
|
private int dataVersion = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance.
|
* Create a new instance.
|
||||||
@ -112,107 +87,6 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
this.inputStream = 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());
|
|
||||||
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
|
@Override
|
||||||
public Clipboard read() throws IOException {
|
public Clipboard read() throws IOException {
|
||||||
CompoundTag schematicTag = getBaseTag();
|
CompoundTag schematicTag = getBaseTag();
|
||||||
@ -264,141 +138,156 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private CompoundTag getBaseTag() throws IOException {
|
||||||
public Clipboard getBaseTag(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException {
|
NamedTag rootTag = inputStream.readNamedTag();
|
||||||
StreamDelegate root = createDelegate();
|
if (!rootTag.getName().equals("Schematic")) {
|
||||||
inputStream.readNamedTagLazy(root);
|
throw new IOException("Tag 'Schematic' does not exist or is not first");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
|
||||||
|
|
||||||
Clipboard clipboard = createOutput.apply(dimensions);
|
// Check
|
||||||
|
Map<String, Tag> schematic = schematicTag.getValue();
|
||||||
|
|
||||||
if (blocksOut != null && blocksOut.getSize() != 0) {
|
schematicVersion = requireTag(schematic, "Version", IntTag.class).getValue();
|
||||||
try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(blocksOut.toByteArrays())))) {
|
return schematicTag;
|
||||||
if (clipboard instanceof LinearClipboard) {
|
}
|
||||||
LinearClipboard linear = (LinearClipboard) clipboard;
|
|
||||||
int volume = width * height * length;
|
private BlockArrayClipboard readVersion1(CompoundTag schematicTag) throws IOException {
|
||||||
if (palette.length < 128) {
|
BlockVector3 origin;
|
||||||
for (int index = 0; index < volume; index++) {
|
Region region;
|
||||||
linear.setBlock(index, getBlockState(fis.read()));
|
Map<String, Tag> schematic = schematicTag.getValue();
|
||||||
}
|
|
||||||
} else {
|
int width = requireTag(schematic, "Width", ShortTag.class).getValue();
|
||||||
for (int index = 0; index < volume; index++) {
|
int height = requireTag(schematic, "Height", ShortTag.class).getValue();
|
||||||
linear.setBlock(index, getBlockState(fis.readVarInt()));
|
int length = requireTag(schematic, "Length", ShortTag.class).getValue();
|
||||||
}
|
|
||||||
}
|
IntArrayTag offsetTag = getTag(schematic, "Offset", IntArrayTag.class);
|
||||||
} else {
|
int[] offsetParts;
|
||||||
if (palette.length < 128) {
|
if (offsetTag != null) {
|
||||||
for (int y = 0; y < height; y++) {
|
offsetParts = offsetTag.getValue();
|
||||||
for (int z = 0; z < length; z++) {
|
if (offsetParts.length != 3) {
|
||||||
for (int x = 0; x < width; x++) {
|
throw new IOException("Invalid offset specified in schematic.");
|
||||||
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()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
offsetParts = new int[] {0, 0, 0};
|
||||||
}
|
}
|
||||||
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");
|
BlockVector3 min = BlockVector3.at(offsetParts[0], offsetParts[1], offsetParts[2]);
|
||||||
int x,y,z;
|
|
||||||
if (pos.length != 3) {
|
CompoundTag metadataTag = getTag(schematic, "Metadata", CompoundTag.class);
|
||||||
if (!tile.containsKey("x") || !tile.containsKey("y") || !tile.containsKey("z")) {
|
if (metadataTag != null && metadataTag.containsKey("WEOffsetX")) {
|
||||||
return null;
|
// We appear to have WorldEdit Metadata
|
||||||
}
|
Map<String, Tag> metadata = metadataTag.getValue();
|
||||||
x = tile.getInt("x");
|
int offsetX = requireTag(metadata, "WEOffsetX", IntTag.class).getValue();
|
||||||
y = tile.getInt("y");
|
int offsetY = requireTag(metadata, "WEOffsetY", IntTag.class).getValue();
|
||||||
z = tile.getInt("z");
|
int offsetZ = requireTag(metadata, "WEOffsetZ", IntTag.class).getValue();
|
||||||
} else {
|
BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ);
|
||||||
x = pos[0];
|
origin = min.subtract(offset);
|
||||||
y = pos[1];
|
region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE));
|
||||||
z = pos[2];
|
} else {
|
||||||
}
|
origin = min;
|
||||||
Map<String, Tag> values = tile.getValue();
|
region = new CuboidRegion(origin, origin.add(width, height, length).subtract(BlockVector3.ONE));
|
||||||
Tag id = values.get("Id");
|
}
|
||||||
if (id != null) {
|
|
||||||
values.put("x", new IntTag(x));
|
IntTag paletteMaxTag = getTag(schematic, "PaletteMax", IntTag.class);
|
||||||
values.put("y", new IntTag(y));
|
Map<String, Tag> paletteObject = requireTag(schematic, "Palette", CompoundTag.class).getValue();
|
||||||
values.put("z", new IntTag(z));
|
if (paletteMaxTag != null && paletteObject.size() != paletteMaxTag.getValue()) {
|
||||||
values.put("id", id);
|
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("Id");
|
||||||
values.remove("Pos");
|
values.remove("Pos");
|
||||||
|
if (fixer != null) {
|
||||||
tile = fixBlockEntity(tile);
|
tileEntity = fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, new CompoundTag(values), dataVersion).getValue();
|
||||||
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 {
|
} else {
|
||||||
log.debug("Invalid entity: " + id);
|
tileEntity = values;
|
||||||
}
|
}
|
||||||
|
tileEntitiesMap.put(pt, tileEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||||
clipboard.setOrigin(origin);
|
clipboard.setOrigin(origin);
|
||||||
|
|
||||||
if (!min.equals(BlockVector3.ZERO)) {
|
int index = 0;
|
||||||
new BlockArrayClipboard(clipboard, min);
|
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;
|
return clipboard;
|
||||||
@ -508,4 +397,4 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
inputStream.close();
|
inputStream.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,61 +19,45 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.extent.clipboard.io;
|
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.google.common.collect.Maps;
|
||||||
import com.boydti.fawe.object.FaweOutputStream;
|
import com.sk89q.jnbt.ByteArrayTag;
|
||||||
import com.boydti.fawe.object.clipboard.LinearClipboard;
|
|
||||||
import com.boydti.fawe.util.IOUtil;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
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.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.NBTOutputStream;
|
||||||
|
import com.sk89q.jnbt.ShortTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
|
||||||
import com.sk89q.worldedit.extension.platform.Capability;
|
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.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.function.visitor.Order;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector2;
|
import com.sk89q.worldedit.math.BlockVector2;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
import com.sk89q.worldedit.math.Vector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
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.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
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.ByteArrayOutputStream;
|
||||||
import java.io.DataOutput;
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.sk89q.worldedit.math.Vector3;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import com.sk89q.worldedit.util.Location;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes schematic files using the Sponge schematic format.
|
* Writes schematic files using the Sponge schematic format.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated // High mem usage + slow
|
||||||
public class SpongeSchematicWriter implements ClipboardWriter {
|
public class SpongeSchematicWriter implements ClipboardWriter {
|
||||||
|
|
||||||
private static final int CURRENT_VERSION = 2;
|
private static final int CURRENT_VERSION = 2;
|
||||||
@ -94,15 +78,16 @@ public class SpongeSchematicWriter implements ClipboardWriter {
|
|||||||
@Override
|
@Override
|
||||||
public void write(Clipboard clipboard) throws IOException {
|
public void write(Clipboard clipboard) throws IOException {
|
||||||
// For now always write the latest version. Maybe provide support for earlier if more appear.
|
// 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.
|
* Writes a version 2 schematic file.
|
||||||
*
|
*
|
||||||
* @param clipboard The clipboard
|
* @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();
|
Region region = clipboard.getRegion();
|
||||||
BlockVector3 origin = clipboard.getOrigin();
|
BlockVector3 origin = clipboard.getOrigin();
|
||||||
BlockVector3 min = region.getMinimumPoint();
|
BlockVector3 min = region.getMinimumPoint();
|
||||||
@ -121,222 +106,102 @@ public class SpongeSchematicWriter implements ClipboardWriter {
|
|||||||
throw new IllegalArgumentException("Length of region too large for a .schematic");
|
throw new IllegalArgumentException("Length of region too large for a .schematic");
|
||||||
}
|
}
|
||||||
|
|
||||||
final DataOutput rawStream = outputStream.getOutputStream();
|
Map<String, Tag> schematic = new HashMap<>();
|
||||||
outputStream.writeLazyCompoundTag("Schematic", out -> {
|
schematic.put("Version", new IntTag(CURRENT_VERSION));
|
||||||
out.writeNamedTag("DataVersion", WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion());
|
schematic.put("DataVersion", new IntTag(
|
||||||
out.writeNamedTag("Version", CURRENT_VERSION);
|
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion()));
|
||||||
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'
|
Map<String, Tag> metadata = new HashMap<>();
|
||||||
out.writeNamedTag("Offset", new int[]{
|
metadata.put("WEOffsetX", new IntTag(offset.getBlockX()));
|
||||||
min.getBlockX(),
|
metadata.put("WEOffsetY", new IntTag(offset.getBlockY()));
|
||||||
min.getBlockY(),
|
metadata.put("WEOffsetZ", new IntTag(offset.getBlockZ()));
|
||||||
min.getBlockZ(),
|
|
||||||
});
|
|
||||||
|
|
||||||
out.writeLazyCompoundTag("Metadata", out1 -> {
|
schematic.put("Metadata", new CompoundTag(metadata));
|
||||||
out1.writeNamedTag("WEOffsetX", offset.getBlockX());
|
|
||||||
out1.writeNamedTag("WEOffsetY", offset.getBlockY());
|
|
||||||
out1.writeNamedTag("WEOffsetZ", offset.getBlockZ());
|
|
||||||
});
|
|
||||||
|
|
||||||
ByteArrayOutputStream blocksCompressed = new ByteArrayOutputStream();
|
schematic.put("Width", new ShortTag((short) width));
|
||||||
FaweOutputStream blocksOut = new FaweOutputStream(new DataOutputStream(new LZ4BlockOutputStream(blocksCompressed)));
|
schematic.put("Height", new ShortTag((short) height));
|
||||||
|
schematic.put("Length", new ShortTag((short) length));
|
||||||
|
|
||||||
ByteArrayOutputStream tilesCompressed = new ByteArrayOutputStream();
|
// The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin'
|
||||||
NBTOutputStream tilesOut = new NBTOutputStream(new LZ4BlockOutputStream(tilesCompressed));
|
schematic.put("Offset", new IntArrayTag(new int[]{
|
||||||
|
min.getBlockX(),
|
||||||
|
min.getBlockY(),
|
||||||
|
min.getBlockZ(),
|
||||||
|
}));
|
||||||
|
|
||||||
List<Integer> paletteList = new ArrayList<>();
|
int paletteMax = 0;
|
||||||
char[] palette = new char[BlockTypesCache.states.length];
|
Map<String, Integer> palette = new HashMap<>();
|
||||||
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'
|
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'
|
||||||
|
|
||||||
|
// Positions are kept in NBT, we don't want that.
|
||||||
|
values.remove("x");
|
||||||
|
values.remove("y");
|
||||||
|
values.remove("z");
|
||||||
|
|
||||||
// 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("Id", new StringTag(block.getNbtId()));
|
||||||
}
|
values.put("Pos", new IntArrayTag(new int[]{
|
||||||
values.put("Pos", new IntArrayTag(new int[]{
|
x,
|
||||||
pos.getX(),
|
y,
|
||||||
pos.getY(),
|
z
|
||||||
pos.getZ()
|
}));
|
||||||
}));
|
|
||||||
numTiles++;
|
|
||||||
tilesOut.writeTagPayload(block.getNbtData());
|
|
||||||
}
|
|
||||||
|
|
||||||
int ordinal = block.getOrdinal();
|
tileEntities.add(new CompoundTag(values));
|
||||||
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
|
String blockKey = block.toImmutableState().getAsString();
|
||||||
values.remove("id");
|
int blockId;
|
||||||
values.put("Id", new StringTag(state.getType().getId()));
|
if (palette.containsKey(blockKey)) {
|
||||||
values.put("Pos", writeVector(entity.getLocation()));
|
blockId = palette.get(blockKey);
|
||||||
values.put("Rotation", writeRotation(entity.getLocation()));
|
} else {
|
||||||
|
blockId = paletteMax;
|
||||||
CompoundTag entityTag = new CompoundTag(values);
|
palette.put(blockKey, blockId);
|
||||||
entities.add(entityTag);
|
paletteMax++;
|
||||||
}
|
|
||||||
}
|
|
||||||
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) {
|
while ((blockId & -128) != 0) {
|
||||||
e.printStackTrace();
|
buffer.write(blockId & 127 | 128);
|
||||||
|
blockId >>>= 7;
|
||||||
|
}
|
||||||
|
buffer.write(blockId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
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]);
|
schematic.put("PaletteMax", new IntTag(paletteMax));
|
||||||
|
|
||||||
out.writeLazyCompoundTag("BiomePalette", out12 -> {
|
Map<String, Tag> paletteTag = new HashMap<>();
|
||||||
for (int i = 0; i < paletteList.size(); i++) {
|
palette.forEach((key, value) -> paletteTag.put(key, new IntTag(value)));
|
||||||
int ordinal = paletteList.get(i);
|
|
||||||
BiomeType state = BiomeTypes.get(ordinal);
|
|
||||||
out12.writeNamedTag(state.getId(), i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
out.writeNamedTagName("BiomeData", NBTConstants.TYPE_BYTE_ARRAY);
|
schematic.put("Palette", new CompoundTag(paletteTag));
|
||||||
out.writeInt(biomesOut.size());
|
schematic.put("BlockData", new ByteArrayTag(buffer.toByteArray()));
|
||||||
try (LZ4BlockInputStream in = new LZ4BlockInputStream(new ByteArrayInputStream(biomesCompressed.toByteArray()))) {
|
schematic.put("BlockEntities", new ListTag(CompoundTag.class, tileEntities));
|
||||||
IOUtil.copy(in, (DataOutput) out);
|
|
||||||
|
// version 2 stuff
|
||||||
|
if (clipboard.hasBiomes()) {
|
||||||
|
writeBiomes(clipboard, schematic);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void writeEntities(Clipboard clipboard, NBTOutputStream schematic) throws IOException {
|
if (!clipboard.getEntities().isEmpty()) {
|
||||||
List<CompoundTag> entities = clipboard.getEntities().stream().map(e -> {
|
writeEntities(clipboard, schematic);
|
||||||
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));
|
|
||||||
|
return schematic;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeBiomes(Clipboard clipboard, Map<String, Tag> 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));
|
schematic.put("Entities", new ListTag(CompoundTag.class, entities));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tag writeVector(Vector3 vector) {
|
public Tag writeVector(Vector3 vector) {
|
||||||
List<DoubleTag> list = new ArrayList<>();
|
List<DoubleTag> list = new ArrayList<>();
|
||||||
list.add(new DoubleTag(vector.getX()));
|
list.add(new DoubleTag(vector.getX()));
|
||||||
list.add(new DoubleTag(vector.getY()));
|
list.add(new DoubleTag(vector.getY()));
|
||||||
@ -416,7 +281,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
|
|||||||
return new ListTag(DoubleTag.class, list);
|
return new ListTag(DoubleTag.class, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tag writeRotation(Location location) {
|
public Tag writeRotation(Location location) {
|
||||||
List<FloatTag> list = new ArrayList<>();
|
List<FloatTag> list = new ArrayList<>();
|
||||||
list.add(new FloatTag(location.getYaw()));
|
list.add(new FloatTag(location.getYaw()));
|
||||||
list.add(new FloatTag(location.getPitch()));
|
list.add(new FloatTag(location.getPitch()));
|
||||||
@ -427,4 +292,4 @@ public class SpongeSchematicWriter implements ClipboardWriter {
|
|||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,8 +22,8 @@ package com.sk89q.worldedit.function.mask;
|
|||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import com.sk89q.worldedit.internal.expression.Expression;
|
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.ExpressionException;
|
||||||
|
import com.sk89q.worldedit.internal.expression.EvaluationException;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
|
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
|
||||||
|
|
||||||
@ -75,7 +75,8 @@ public class ExpressionMask extends AbstractMask {
|
|||||||
if (timeout == null) {
|
if (timeout == null) {
|
||||||
return expression.evaluate(vector.getX(), vector.getY(), vector.getZ()) > 0;
|
return expression.evaluate(vector.getX(), vector.getY(), vector.getZ()) > 0;
|
||||||
} else {
|
} 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) {
|
} catch (EvaluationException e) {
|
||||||
return false;
|
return false;
|
||||||
@ -88,4 +89,4 @@ public class ExpressionMask extends AbstractMask {
|
|||||||
return new ExpressionMask2D(expression, timeout);
|
return new ExpressionMask2D(expression, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -411,6 +411,7 @@ public class ForwardExtentCopy implements Operation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
int affected;
|
||||||
affected = region.getArea();
|
affected = region.getArea();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -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.FileSelectionAbortedException;
|
||||||
import com.sk89q.worldedit.util.io.file.FilenameResolutionException;
|
import com.sk89q.worldedit.util.io.file.FilenameResolutionException;
|
||||||
import com.sk89q.worldedit.util.io.file.InvalidFilenameException;
|
import com.sk89q.worldedit.util.io.file.InvalidFilenameException;
|
||||||
import com.sk89q.worldedit.world.storage.MissingWorldException;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import org.enginehub.piston.exception.CommandException;
|
import org.enginehub.piston.exception.CommandException;
|
||||||
|
@ -22,25 +22,23 @@ package com.sk89q.worldedit.internal.expression;
|
|||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.SetMultimap;
|
import com.google.common.collect.SetMultimap;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.antlr.ExpressionLexer;
|
import com.sk89q.worldedit.antlr.ExpressionLexer;
|
||||||
import com.sk89q.worldedit.antlr.ExpressionParser;
|
import com.sk89q.worldedit.antlr.ExpressionParser;
|
||||||
|
import com.sk89q.worldedit.session.request.Request;
|
||||||
import org.antlr.v4.runtime.CharStream;
|
import org.antlr.v4.runtime.CharStream;
|
||||||
import org.antlr.v4.runtime.CharStreams;
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
import org.antlr.v4.runtime.misc.ParseCancellationException;
|
import org.antlr.v4.runtime.misc.ParseCancellationException;
|
||||||
import com.sk89q.worldedit.session.request.Request;
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.Stack;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
@ -75,17 +73,16 @@ import java.util.concurrent.TimeoutException;
|
|||||||
*/
|
*/
|
||||||
public class Expression {
|
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(
|
private static final ExecutorService evalThread = Executors.newFixedThreadPool(
|
||||||
Runtime.getRuntime().availableProcessors(),
|
Runtime.getRuntime().availableProcessors(),
|
||||||
new ThreadFactoryBuilder()
|
new ThreadFactoryBuilder()
|
||||||
.setDaemon(true)
|
.setDaemon(true)
|
||||||
.setNameFormat("worldedit-expression-eval-%d")
|
.setNameFormat("worldedit-expression-eval-%d")
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
private final SlotTable slots = new SlotTable();
|
private final SlotTable slots = new SlotTable();
|
||||||
private final List<String> providedSlots;
|
private final List<String> providedSlots;
|
||||||
private Variable[] variableArray;
|
|
||||||
private ExpressionParser.AllStatementsContext root;
|
private ExpressionParser.AllStatementsContext root;
|
||||||
private final SetMultimap<String, MethodHandle> functions = Functions.getFunctionMap();
|
private final SetMultimap<String, MethodHandle> functions = Functions.getFunctionMap();
|
||||||
private ExpressionEnvironment environment;
|
private ExpressionEnvironment environment;
|
||||||
@ -102,8 +99,8 @@ public class Expression {
|
|||||||
|
|
||||||
for (String variableName : variableNames) {
|
for (String variableName : variableNames) {
|
||||||
slots.initVariable(variableName)
|
slots.initVariable(variableName)
|
||||||
.orElseThrow(() -> new ExpressionException(-1,
|
.orElseThrow(() -> new ExpressionException(-1,
|
||||||
"Tried to overwrite identifier '" + variableName + "'"));
|
"Tried to overwrite identifier '" + variableName + "'"));
|
||||||
}
|
}
|
||||||
this.providedSlots = ImmutableList.copyOf(variableNames);
|
this.providedSlots = ImmutableList.copyOf(variableNames);
|
||||||
|
|
||||||
@ -124,48 +121,16 @@ public class Expression {
|
|||||||
ParseTreeWalker.DEFAULT.walk(new ExpressionValidator(slots.keySet(), functions), root);
|
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 {
|
public double evaluate(double... values) throws EvaluationException {
|
||||||
return evaluateTimeout(WorldEdit.getInstance().getConfiguration().calculationTimeout, values);
|
return evaluate(values, WorldEdit.getInstance().getConfiguration().calculationTimeout);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double evaluate(double[] values, int timeout) throws EvaluationException {
|
public double evaluate(double[] values, int timeout) throws EvaluationException {
|
||||||
if (root instanceof Constant) {
|
|
||||||
return root.getValue();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < values.length; ++i) {
|
for (int i = 0; i < values.length; ++i) {
|
||||||
String slotName = providedSlots.get(i);
|
String slotName = providedSlots.get(i);
|
||||||
LocalSlot.Variable slot = slots.getVariable(slotName)
|
LocalSlot.Variable slot = slots.getVariable(slotName)
|
||||||
.orElseThrow(() -> new EvaluationException(-1,
|
.orElseThrow(() -> new EvaluationException(-1,
|
||||||
"Tried to assign to non-variable " + slotName + "."));
|
"Tried to assign to non-variable " + slotName + "."));
|
||||||
|
|
||||||
slot.setValue(values[i]);
|
slot.setValue(values[i]);
|
||||||
}
|
}
|
||||||
@ -177,17 +142,6 @@ public class Expression {
|
|||||||
return evaluateRootTimed(timeout);
|
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 {
|
private double evaluateRootTimed(int timeout) throws EvaluationException {
|
||||||
CountDownLatch startLatch = new CountDownLatch(1);
|
CountDownLatch startLatch = new CountDownLatch(1);
|
||||||
Request request = Request.request();
|
Request request = Request.request();
|
||||||
@ -233,32 +187,36 @@ public class Expression {
|
|||||||
// TODO optimizing
|
// TODO optimizing
|
||||||
}
|
}
|
||||||
|
|
||||||
public SlotTable getSlots() {
|
|
||||||
return slots;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RValue getRoot() {
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return root.toString();
|
return root.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SlotTable getSlots() {
|
||||||
|
return slots;
|
||||||
|
}
|
||||||
|
|
||||||
public static Expression getInstance() {
|
public static Expression getInstance() {
|
||||||
return instance.get().peek();
|
return instance.get().peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pushInstance() {
|
private void pushInstance() {
|
||||||
ArrayDeque<Expression> foo = instance.get();
|
Stack<Expression> threadLocalExprStack = instance.get();
|
||||||
foo.push(this);
|
if (threadLocalExprStack == null) {
|
||||||
|
instance.set(threadLocalExprStack = new Stack<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
threadLocalExprStack.push(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void popInstance() {
|
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() {
|
public ExpressionEnvironment getEnvironment() {
|
||||||
@ -269,4 +227,4 @@ public class Expression {
|
|||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
52
worldedit-core/src/main/java/com/sk89q/worldedit/math/BitMath.java
Normale Datei
52
worldedit-core/src/main/java/com/sk89q/worldedit/math/BitMath.java
Normale Datei
@ -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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -124,7 +124,7 @@ public abstract class BlockVector3 {
|
|||||||
|
|
||||||
public long toLongPackedForm() {
|
public long toLongPackedForm() {
|
||||||
checkLongPackable(this);
|
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) {
|
public MutableBlockVector3 mutX(double x) {
|
||||||
|
@ -54,7 +54,15 @@ public interface Subject {
|
|||||||
* @param permission the permission
|
* @param permission the permission
|
||||||
* @return false if the permission was removed, true if this subject has 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);
|
void setPermission(String permission, boolean value);
|
||||||
}
|
}
|
||||||
|
@ -103,15 +103,16 @@ public class BlockType implements FawePattern, Keyed {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
private BlockState computeDefaultState() {
|
private BlockState computeDefaultState() {
|
||||||
|
|
||||||
BlockState defaultState = Iterables.getFirst(getBlockStatesMap().values(), null);
|
BlockState defaultState = Iterables.getFirst(getBlockStatesMap().values(), null);
|
||||||
if (values != null) {
|
if (values != null) {
|
||||||
defaultState = values.apply(defaultState);
|
defaultState = values.apply(defaultState);
|
||||||
}
|
}
|
||||||
return defaultState;
|
return defaultState;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public BlockState withPropertyId(int propertyId) {
|
public BlockState withPropertyId(int propertyId) {
|
||||||
if (settings.stateOrdinals == null) return settings.defaultState;
|
if (settings.stateOrdinals == null) return settings.defaultState;
|
||||||
|
@ -102,7 +102,7 @@ public final class LegacyMapper {
|
|||||||
Integer combinedId = getCombinedId(blockEntry.getKey());
|
Integer combinedId = getCombinedId(blockEntry.getKey());
|
||||||
final String value = blockEntry.getValue();
|
final String value = blockEntry.getValue();
|
||||||
blockEntries.put(id, value);
|
blockEntries.put(id, value);
|
||||||
BlockState blockState;
|
BlockState blockState = null;
|
||||||
try {
|
try {
|
||||||
blockState = BlockState.get(null, blockEntry.getValue());
|
blockState = BlockState.get(null, blockEntry.getValue());
|
||||||
BlockType type = blockState.getBlockType();
|
BlockType type = blockState.getBlockType();
|
||||||
@ -114,10 +114,10 @@ public final class LegacyMapper {
|
|||||||
String newEntry = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, value, 1631);
|
String newEntry = fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, value, 1631);
|
||||||
try {
|
try {
|
||||||
blockState = WorldEdit.getInstance().getBlockFactory().parseFromInput(newEntry, parserContext).toImmutableState();
|
blockState = WorldEdit.getInstance().getBlockFactory().parseFromInput(newEntry, parserContext).toImmutableState();
|
||||||
} catch (InputParseException ignored) {
|
} catch (InputParseException ignored) {}
|
||||||
log.warn("Unknown block: " + value);
|
}
|
||||||
continue;
|
if (blockState == null) {
|
||||||
}
|
log.warn("Unknown block: " + value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blockArr[combinedId] = blockState.getInternalId();
|
blockArr[combinedId] = blockState.getInternalId();
|
||||||
@ -135,9 +135,21 @@ public final class LegacyMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, String> itemEntry : dataFile.items.entrySet()) {
|
for (Map.Entry<String, String> itemEntry : dataFile.items.entrySet()) {
|
||||||
try {
|
String id = itemEntry.getKey();
|
||||||
itemMap.put(getCombinedId(itemEntry.getKey()), ItemTypes.get(itemEntry.getValue()));
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren