Various
Fixes #456 Delay command registration WIP shatter/stencil brush Minor FaweQueue optimization
This commit is contained in:
parent
eb55f5fd7d
commit
b595ec2f2d
@ -121,6 +121,8 @@ public enum BBC {
|
||||
BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"),
|
||||
BRUSH_SMOOTH("Smooth brush equipped (%s0 x %s1 using %s2. Note: Use the blend brush if you want to smooth overhangs or caves.).", "WorldEdit.Brush"),
|
||||
BRUSH_SPHERE("Sphere brush shape equipped (%s0).", "WorldEdit.Brush"),
|
||||
BRUSH_SHATTER("Shatter brush shape equipped (%s0, %s1).", "WorldEdit.Brush"),
|
||||
BRUSH_STENCIL("Stencil brush equipped (%s0).", "WorldEdit.Brush"),
|
||||
BRUSH_LINE("Line brush shape equipped (%s0).", "WorldEdit.Brush"),
|
||||
BRUSH_SPLINE("Spline brush shape equipped (%s0). Right click an end to add a shape", "WorldEdit.Brush"),
|
||||
BRUSH_SPLINE_PRIMARY_2("Added position, Click the same spot to join!", "WorldEdit.Brush"),
|
||||
|
@ -572,14 +572,38 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> exte
|
||||
|
||||
@Override
|
||||
public int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
||||
FaweChunk fc = map.getCachedFaweChunk(x >> 4, z >> 4);
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
FaweChunk fc = map.getCachedFaweChunk(cx, cz);
|
||||
if (fc != null) {
|
||||
int combined = fc.getBlockCombinedId(x & 15, y, z & 15);
|
||||
if (combined != 0) {
|
||||
return combined;
|
||||
}
|
||||
}
|
||||
return getCombinedId4Data(x, y, z);
|
||||
int cy = y >> 4;
|
||||
if (cx != lastSectionX || cz != lastSectionZ) {
|
||||
lastSectionX = cx;
|
||||
lastSectionZ = cz;
|
||||
lastChunk = ensureChunkLoaded(cx, cz);
|
||||
if (lastChunk != null) {
|
||||
lastChunkSections = getSections(lastChunk);
|
||||
lastSection = getCachedSection(lastChunkSections, cy);
|
||||
} else {
|
||||
lastChunkSections = null;
|
||||
return 0;
|
||||
}
|
||||
} else if (cy != lastSectionY) {
|
||||
if (lastChunkSections != null) {
|
||||
lastSection = getCachedSection(lastChunkSections, cy);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (lastSection == null) {
|
||||
return 0;
|
||||
}
|
||||
return getCombinedId4Data(lastSection, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -24,6 +24,6 @@ public class FlattenBrush extends HeightBrush {
|
||||
mask = null;
|
||||
}
|
||||
heightMap.setSize(size);
|
||||
heightMap.apply(editSession, mask, position, size, rotation, yscale, true, true);
|
||||
heightMap.perform(editSession, mask, position, size, rotation, yscale, true, true);
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,6 @@ public class HeightBrush implements Brush {
|
||||
mask = null;
|
||||
}
|
||||
heightMap.setSize(size);
|
||||
heightMap.apply(editSession, mask, position, size, rotation, yscale, true, false);
|
||||
heightMap.perform(editSession, mask, position, size, rotation, yscale, true, false);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,135 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.object.collection.LocalBlockVectorSet;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.MutableBlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.command.tool.brush.Brush;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.visitor.BreadthFirstSearch;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
|
||||
public class ShatterBrush implements Brush {
|
||||
private final int count;
|
||||
|
||||
public ShatterBrush(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, final Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
// We'll want this to be somewhat circular, so the cuboid needs to fit.
|
||||
int r2Radius = (int) Math.ceil(size * Math.sqrt(2));
|
||||
int radius2 = (int) (Math.ceil(r2Radius * r2Radius));
|
||||
Vector bot = new MutableBlockVector(position.subtract(size, size, size));
|
||||
Vector top = new MutableBlockVector(position.add(size, size, size));
|
||||
CuboidRegion region = new CuboidRegion(bot, top);
|
||||
// We'll want to use a fast random
|
||||
PseudoRandom random = new PseudoRandom();
|
||||
// We don't need double precision, so use a BlockVector
|
||||
BlockVector min = region.getMinimumPoint().toBlockVector();
|
||||
BlockVector max = region.getMaximumPoint().toBlockVector();
|
||||
// Let's keep it inside the brush radius
|
||||
int dx = max.getBlockX() - min.getBlockX() + 1;
|
||||
int dy = max.getBlockY() - min.getBlockY() + 1;
|
||||
int dz = max.getBlockZ() - min.getBlockZ() + 1;
|
||||
// We'll store the points in a set
|
||||
LocalBlockVectorSet queue = new LocalBlockVectorSet();
|
||||
// User could select a single block and try to create 10 points = infinite loop
|
||||
// To avoid being stuck in an infinite loop, let's stop after 5 collisions
|
||||
int maxFails = 5;
|
||||
for (int added = 0; added < count;) {
|
||||
int x = (int) (random.nextDouble() * dx) + min.getBlockX();
|
||||
int z = (int) (random.nextDouble() * dz) + min.getBlockZ();
|
||||
int y = editSession.getHighestTerrainBlock(x, z, 0, 255);
|
||||
// Check the adjacent blocks efficiently (loops over the adjacent blocks, or the set; whichever is faster)
|
||||
if (!queue.containsRadius(x, y, z, 1)) {
|
||||
added++;
|
||||
queue.add(x, y, z);
|
||||
} else if (maxFails-- <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Ideally we'd calculate all the bisecting planes, but that's complex to program
|
||||
// With this algorithm compute time depends on the number of blocks rather than the number of points
|
||||
// - Expand from each point (block by block) until there is a collision
|
||||
{
|
||||
// Keep track of where we've visited
|
||||
LocalBlockVectorSet visited = queue;
|
||||
LocalBlockVectorSet tmp = new LocalBlockVectorSet();
|
||||
// Individual frontier for each point
|
||||
LocalBlockVectorSet[] frontiers = new LocalBlockVectorSet[queue.size()];
|
||||
// Keep track of where each frontier has visited
|
||||
LocalBlockVectorSet[] frontiersVisited = new LocalBlockVectorSet[queue.size()];
|
||||
// Initiate the frontier with the starting points
|
||||
int i = 0;
|
||||
for (Vector pos : queue) {
|
||||
LocalBlockVectorSet set = new LocalBlockVectorSet();
|
||||
set.add(pos);
|
||||
frontiers[i] = set;
|
||||
frontiersVisited[i] = set.clone();
|
||||
i++;
|
||||
}
|
||||
// Mask
|
||||
Mask mask = editSession.getMask();
|
||||
if (mask == null) {
|
||||
mask = Masks.alwaysTrue();
|
||||
}
|
||||
final Mask finalMask = mask;
|
||||
// Expand
|
||||
boolean notEmpty = true;
|
||||
while (notEmpty) {
|
||||
notEmpty = false;
|
||||
for (i = 0; i < frontiers.length; i++) {
|
||||
LocalBlockVectorSet frontier = frontiers[i];
|
||||
notEmpty |= !frontier.isEmpty();
|
||||
final LocalBlockVectorSet frontierVisited = frontiersVisited[i];
|
||||
// This is a temporary set with the next blocks the frontier will visit
|
||||
final LocalBlockVectorSet finalTmp = tmp;
|
||||
frontier.forEach(new LocalBlockVectorSet.BlockVectorSetVisitor() {
|
||||
@Override
|
||||
public void run(int x, int y, int z, int index) {
|
||||
if (PseudoRandom.random.random(2) == 0) {
|
||||
finalTmp.add(x, y, z);
|
||||
return;
|
||||
}
|
||||
for (Vector direction : BreadthFirstSearch.DEFAULT_DIRECTIONS) {
|
||||
int x2 = x + direction.getBlockX();
|
||||
int y2 = y + direction.getBlockY();
|
||||
int z2 = z + direction.getBlockZ();
|
||||
// Check boundary
|
||||
int dx = position.getBlockX() - x2;
|
||||
int dy = position.getBlockY() - y2;
|
||||
int dz = position.getBlockZ() - z2;
|
||||
int dSqr = (dx * dx) + (dy * dy) + (dz * dz);
|
||||
if (dSqr <= radius2) {
|
||||
if (finalMask.test(MutableBlockVector.get(x2, y2, z2))) {
|
||||
// (collision) If it's visited and part of another frontier, set the block
|
||||
if (!visited.add(x2, y2, z2)) {
|
||||
if (!frontierVisited.contains(x2, y2, z2)) {
|
||||
editSession.setBlock(x2, y2, z2, pattern);
|
||||
}
|
||||
} else {
|
||||
// Hasn't visited and not a collision = add it
|
||||
finalTmp.add(x2, y2, z2);
|
||||
frontierVisited.add(x2, y2, z2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// Swap the frontier with the temporary set
|
||||
frontiers[i] = tmp;
|
||||
tmp = frontier;
|
||||
tmp.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.boydti.fawe.object.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class StencilBrush extends HeightBrush {
|
||||
private final boolean onlyWhite;
|
||||
|
||||
public StencilBrush(InputStream stream, int rotation, double yscale, boolean onlyWhite, Clipboard clipboard) {
|
||||
super(stream, rotation, yscale, clipboard);
|
||||
this.onlyWhite = onlyWhite;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
|
||||
int size = (int) sizeDouble;
|
||||
Mask mask = editSession.getMask();
|
||||
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
|
||||
mask = null;
|
||||
}
|
||||
heightMap.setSize(size);
|
||||
for (int x = -size; x <= size; x++) {
|
||||
int xx = position.getBlockX() + x;
|
||||
for (int z = -size; z <= size; z++) {
|
||||
int zz = position.getBlockZ() + z;
|
||||
double raise;
|
||||
switch (rotation) {
|
||||
default:raise = heightMap.getHeight(x, z); break;
|
||||
case 1: raise = heightMap.getHeight(z, x); break;
|
||||
case 2: raise = heightMap.getHeight(-x, -z); break;
|
||||
case 3: raise = heightMap.getHeight(-z, -x);break;
|
||||
}
|
||||
raise *= yscale;
|
||||
if (raise == 0 || (onlyWhite && raise < 255)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int[] data = heightMap.generateHeightData(editSession, mask, position, size, rotation, yscale, true, false);
|
||||
int diameter = size * 2;
|
||||
int x = position.getBlockX();
|
||||
int y = position.getBlockY();
|
||||
int z = position.getBlockZ();
|
||||
}
|
||||
|
||||
}
|
@ -118,7 +118,32 @@ public class ScalableHeightMap {
|
||||
return new ArrayHeightMap(array);
|
||||
}
|
||||
|
||||
public void apply(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) throws MaxChangedBlocksException {
|
||||
public void perform(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) throws MaxChangedBlocksException {
|
||||
int[] data = generateHeightData(session, mask, pos, size, rotationMode, yscale, smooth, towards);
|
||||
applyHeightMapData(data, session, mask, pos, size, rotationMode, yscale, smooth, towards);
|
||||
}
|
||||
|
||||
public void applyHeightMapData(int[] data, EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) throws MaxChangedBlocksException {
|
||||
Vector top = session.getMaximumPoint();
|
||||
int maxY = top.getBlockY();
|
||||
int diameter = 2 * size + 1;
|
||||
int iterations = 1;
|
||||
WorldVector min = new WorldVector(LocalWorldAdapter.adapt(session.getWorld()), pos.subtract(size, maxY, size));
|
||||
Vector max = pos.add(size, maxY, size);
|
||||
Region region = new CuboidRegion(session.getWorld(), min, max);
|
||||
HeightMap heightMap = new HeightMap(session, region, true);
|
||||
if (smooth) {
|
||||
try {
|
||||
HeightMapFilter filter = (HeightMapFilter) HeightMapFilter.class.getConstructors()[0].newInstance(GaussianKernel.class.getConstructors()[0].newInstance(5, 1));
|
||||
data = filter.filter(data, diameter, diameter);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
heightMap.apply(data);
|
||||
}
|
||||
|
||||
public int[] generateHeightData(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) {
|
||||
Vector top = session.getMaximumPoint();
|
||||
int maxY = top.getBlockY();
|
||||
int diameter = 2 * size + 1;
|
||||
@ -201,19 +226,6 @@ public class ScalableHeightMap {
|
||||
}
|
||||
}
|
||||
}
|
||||
int iterations = 1;
|
||||
WorldVector min = new WorldVector(LocalWorldAdapter.adapt(session.getWorld()), pos.subtract(size, maxY, size));
|
||||
Vector max = pos.add(size, maxY, size);
|
||||
Region region = new CuboidRegion(session.getWorld(), min, max);
|
||||
HeightMap heightMap = new HeightMap(session, region, true);
|
||||
if (smooth) {
|
||||
try {
|
||||
HeightMapFilter filter = (HeightMapFilter) HeightMapFilter.class.getConstructors()[0].newInstance(GaussianKernel.class.getConstructors()[0].newInstance(5, 1));
|
||||
newData = filter.filter(newData, diameter, diameter);
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
}
|
||||
}
|
||||
heightMap.apply(newData);
|
||||
return newData;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,9 @@ import com.boydti.fawe.object.brush.LineBrush;
|
||||
import com.boydti.fawe.object.brush.RaiseBrush;
|
||||
import com.boydti.fawe.object.brush.RecurseBrush;
|
||||
import com.boydti.fawe.object.brush.SplineBrush;
|
||||
import com.boydti.fawe.object.brush.StencilBrush;
|
||||
import com.boydti.fawe.object.brush.TargetMode;
|
||||
import com.boydti.fawe.object.brush.ShatterBrush;
|
||||
import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
|
||||
import com.boydti.fawe.object.brush.scroll.ScrollClipboard;
|
||||
import com.boydti.fawe.object.brush.scroll.ScrollMask;
|
||||
@ -79,6 +81,7 @@ import com.sk89q.worldedit.extension.platform.CommandManager;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
@ -268,7 +271,7 @@ public class BrushCommands {
|
||||
File working = this.worldEdit.getWorkingDirectoryFile(config.saveDir);
|
||||
File dir = new File(working, (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? (player.getUniqueId().toString() + File.separator) : "") + filename);
|
||||
if (!dir.exists()) {
|
||||
if (!filename.contains("/") && !filename.contains("\\")) {
|
||||
if ((!filename.contains("/") && !filename.contains("\\")) || player.hasPermission("worldedit.schematic.load.other")) {
|
||||
dir = new File(this.worldEdit.getWorkingDirectoryFile(config.saveDir), filename);
|
||||
}
|
||||
}
|
||||
@ -507,27 +510,52 @@ public class BrushCommands {
|
||||
if (!FawePlayer.wrap(player).hasPermission("fawe.tips")) BBC.TIP_BRUSH_COMMAND.or(BBC.TIP_BRUSH_RELATIVE, BBC.TIP_BRUSH_TRANSFORM, BBC.TIP_BRUSH_MASK_SOURCE, BBC.TIP_BRUSH_MASK, BBC.TIP_BRUSH_COPY, BBC.TIP_BRUSH_HEIGHT, BBC.TIP_BRUSH_SPLINE).send(player);
|
||||
}
|
||||
|
||||
// @Command(
|
||||
// aliases = { "test" },
|
||||
// usage = "<pattern> [radius] [count] [distance]",
|
||||
// flags = "h",
|
||||
// desc = "Choose the sphere brush",
|
||||
// help =
|
||||
// "Chooses the sphere brush.\n" +
|
||||
// "The -h flag creates hollow spheres instead.",
|
||||
// min = 1,
|
||||
// max = -1
|
||||
// )
|
||||
// @CommandPermissions("worldedit.brush.test")
|
||||
// public void testBrush(Player player, LocalSession session, Pattern fill, @Optional("10") double radius, @Optional("10") int count, @Optional("10") int distance) throws WorldEditException {
|
||||
// worldEdit.checkMaxBrushRadius(radius);
|
||||
//
|
||||
// BrushTool tool = session.getBrushTool(player);
|
||||
// tool.setFill(fill);
|
||||
// tool.setSize(radius);
|
||||
// tool.setBrush(new Test(count), "worldedit.brush.test");
|
||||
// player.print("equiped");
|
||||
// }
|
||||
@Command(
|
||||
aliases = { "shatter", "partition", "split" },
|
||||
usage = "<pattern> [radius] [count] [distance]",
|
||||
desc = "Creates random lines to break the terrain into pieces",
|
||||
help =
|
||||
"Chooses the shatter brush",
|
||||
min = 1,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.shatter")
|
||||
public void shatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") double radius, @Optional("10") int count) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player);
|
||||
tool.setFill(fill);
|
||||
tool.setSize(radius);
|
||||
tool.setMask(new ExistingBlockMask(editSession));
|
||||
tool.setBrush(new ShatterBrush(count), "worldedit.brush.shatter");
|
||||
player.print(BBC.getPrefix() + BBC.BRUSH_SHATTER.f(radius, count));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "stencil", "color"},
|
||||
usage = "<pattern> [radius] [file|#clipboard|null] [rotation] [yscale]",
|
||||
desc = "Use a height map to paint a surface",
|
||||
help =
|
||||
"Chooses the stencil brush.\n" +
|
||||
"The -w flag will only apply at maximum saturation",
|
||||
min = 1,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.stencil")
|
||||
public void stencilBrush(Player player, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
BrushTool tool = session.getBrushTool(player);
|
||||
InputStream stream = getHeightmapStream(filename);
|
||||
tool.setFill(fill);
|
||||
tool.setSize(radius);
|
||||
try {
|
||||
tool.setBrush(new StencilBrush(stream, rotation, yscale, onlyWhite, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null), "worldedit.brush.height", player);
|
||||
} catch (EmptyClipboardException ignore) {
|
||||
tool.setBrush(new StencilBrush(stream, rotation, yscale, onlyWhite, null), "worldedit.brush.height", player);
|
||||
}
|
||||
|
||||
player.print(BBC.getPrefix() + BBC.BRUSH_STENCIL.f(radius));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "cylinder", "cyl", "c" },
|
||||
@ -701,11 +729,9 @@ public class BrushCommands {
|
||||
terrainBrush(player, session, radius, filename, rotation, yscale, true, ScalableHeightMap.Shape.CONE);
|
||||
}
|
||||
|
||||
private void terrainBrush(Player player, LocalSession session, double radius, String filename, int rotation, double yscale, boolean flat, ScalableHeightMap.Shape shape) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
private InputStream getHeightmapStream(String filename) {
|
||||
String filenamePng = (filename.endsWith(".png") ? filename : filename + ".png");
|
||||
File file = new File(Fawe.imp().getDirectory(), "heightmap" + File.separator + filenamePng);
|
||||
InputStream stream = null;
|
||||
if (!file.exists()) {
|
||||
if (!filename.equals("#clipboard") && filename.length() >= 7) {
|
||||
try {
|
||||
@ -719,19 +745,24 @@ public class BrushCommands {
|
||||
url = new URL("https://i.imgur.com/" + filenamePng);
|
||||
}
|
||||
ReadableByteChannel rbc = Channels.newChannel(url.openStream());
|
||||
stream = Channels.newInputStream(rbc);
|
||||
return Channels.newInputStream(rbc);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
} else if (!filename.equalsIgnoreCase("#clipboard")){
|
||||
try {
|
||||
stream = new FileInputStream(file);
|
||||
return new FileInputStream(file);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void terrainBrush(Player player, LocalSession session, double radius, String filename, int rotation, double yscale, boolean flat, ScalableHeightMap.Shape shape) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
InputStream stream = getHeightmapStream(filename);
|
||||
BrushTool tool = session.getBrushTool(player);
|
||||
tool.setSize(radius);
|
||||
if (flat) {
|
||||
|
@ -55,6 +55,7 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
@ -132,7 +133,7 @@ public class SchematicCommands {
|
||||
}
|
||||
}
|
||||
if (!f.exists()) {
|
||||
if (!filename.contains("/") && !filename.contains("\\")) {
|
||||
if ((!filename.contains("/") && !filename.contains("\\")) || player.hasPermission("worldedit.schematic.load.other")) {
|
||||
dir = this.worldEdit.getWorkingDirectoryFile(config.saveDir);
|
||||
f = this.worldEdit.getSafeSaveFile(player, dir, filename, format.getExtension(), format.getExtension());
|
||||
}
|
||||
@ -203,8 +204,13 @@ public class SchematicCommands {
|
||||
final File parent = f.getParentFile();
|
||||
if ((parent != null) && !parent.exists()) {
|
||||
if (!parent.mkdirs()) {
|
||||
log.info("Could not create folder for schematics!");
|
||||
return;
|
||||
try {
|
||||
Files.createDirectories(parent.toPath());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.info("Could not create folder for schematics!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
@ -18,6 +18,7 @@ import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.MutableBlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
@ -232,7 +233,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
|
||||
public Vector getPosition(EditSession editSession, Player player) {
|
||||
switch (targetMode) {
|
||||
case TARGET_BLOCK_RANGE:
|
||||
return player.getBlockTrace(getRange(), true);
|
||||
return new MutableBlockVector(player.getBlockTrace(getRange(), true));
|
||||
case FOWARD_POINT_PITCH: {
|
||||
int d = 0;
|
||||
Location loc = player.getLocation();
|
||||
@ -241,7 +242,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
|
||||
d += (int) (Math.sin(Math.toRadians(pitch)) * 50);
|
||||
final Vector vector = loc.getDirection().setY(0).normalize().multiply(d);
|
||||
vector.add(loc.getX(), loc.getY(), loc.getZ()).toBlockVector();
|
||||
return vector;
|
||||
return new MutableBlockVector(vector);
|
||||
}
|
||||
case TARGET_POINT_HEIGHT: {
|
||||
Location loc = player.getLocation();
|
||||
@ -256,10 +257,10 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
|
||||
}
|
||||
}
|
||||
final int distance = (height - y) + 8;
|
||||
return player.getBlockTrace(distance, true);
|
||||
return new MutableBlockVector(player.getBlockTrace(distance, true));
|
||||
}
|
||||
case TARGET_FACE_RANGE:
|
||||
return player.getBlockTraceFace(getRange(), true);
|
||||
return new MutableBlockVector(player.getBlockTraceFace(getRange(), true));
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ public final class CommandManager {
|
||||
private final WorldEdit worldEdit;
|
||||
private final PlatformManager platformManager;
|
||||
private volatile Dispatcher dispatcher;
|
||||
private volatile Platform platform;
|
||||
private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler();
|
||||
private final ExceptionConverter exceptionConverter;
|
||||
|
||||
@ -246,7 +247,9 @@ public final class CommandManager {
|
||||
.registerMethods(new BrushCommands(worldEdit))
|
||||
.parent().graph().getDispatcher();
|
||||
|
||||
|
||||
if (platform != null) {
|
||||
platform.registerCommands(dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
public static CommandManager getInstance() {
|
||||
@ -281,7 +284,7 @@ public final class CommandManager {
|
||||
}
|
||||
}
|
||||
|
||||
platform.registerCommands(dispatcher);
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
|
Loading…
Reference in New Issue
Block a user