Target offset + code cleanup

This commit is contained in:
Jesse Boyd 2017-08-15 13:36:10 +10:00
parent 46d1d70f9e
commit 83317563a3
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
8 changed files with 119 additions and 43 deletions

View File

@ -6,6 +6,7 @@ import com.boydti.fawe.object.extent.NullExtent;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.Player;
@ -183,6 +184,38 @@ public class FawePrimitiveBinding extends BindingHelper {
return context.nextBoolean();
}
/**
* Gets a type from a {@link ArgumentStack}.
*
* @param context the context
* @return the requested type
* @throws ParameterException on error
*/
@BindingMatch(type = Vector.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true)
public Vector getVector(ArgumentStack context, Annotation[] modifiers) throws ParameterException {
String radiusString = context.next();
String[] radii = radiusString.split(",");
final double radiusX, radiusY, radiusZ;
switch (radii.length) {
case 1:
radiusX = radiusY = radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0]));
break;
case 3:
radiusX = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0]));
radiusY = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[1]));
radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[2]));
break;
default:
throw new ParameterException("You must either specify 1 or 3 radius values.");
}
return new Vector(radiusX, radiusY, radiusZ);
}
/**
* Try to parse numeric input as either a number or a mathematical expression.
*

View File

@ -122,6 +122,7 @@ public enum BBC {
BRUSH_VISUAL_MODE_SET("Set visual mode to %s0", "WorldEdit.Brush"),
BRUSH_TARGET_MODE_SET("Set target mode to %s0", "WorldEdit.Brush"),
BRUSH_TARGET_MASK_SET("Set target mask to %s0", "WorldEdit.Brush"),
BRUSH_TARGET_OFFSET_SET("Set target offset to %s0", "WorldEdit.Brush"),
BRUSH_EQUIPPED("Equipped brush %s0", "WorldEdit.Brush"),
BRUSH_TRY_OTHER("&cThere are other more suitable brushes e.g.\n&8 - &7//br height [radius=5] [#clipboard|file=null] [rotation=0] [yscale=1.00]", "WorldEdit.Brush"),
BRUSH_COPY("Left click the base of an object to copy, right click to paste. Increase the brush radius if necessary.", "WorldEdit.Brush"),

View File

@ -11,10 +11,12 @@ import java.util.concurrent.ThreadLocalRandom;
public class BlobBrush implements Brush {
private final double amplitude;
private final double frequency;
private final Vector radius;
public BlobBrush(double frequency, double amplitude) {
public BlobBrush(Vector radius, double frequency, double amplitude) {
this.frequency = frequency;
this.amplitude = amplitude;
this.radius = radius;
}
@Override
@ -29,17 +31,21 @@ public class BlobBrush implements Brush {
double distort = this.frequency / size;
double modX = 1d/radius.getX();
double modY = 1d/radius.getY();
double modZ = 1d/radius.getZ();
int radiusSqr = (int) (size * size);
int sizeInt = (int) size * 2;
for (int x = -sizeInt; x <= sizeInt; x++) {
double nx = seedX + x * distort;
int d1 = x * x;
double d1 = x * x * modX;
for (int y = -sizeInt; y <= sizeInt; y++) {
int d2 = d1 + y * y;
double d2 = d1 + y * y * modY;
double ny = seedY + y * distort;
for (int z = -sizeInt; z <= sizeInt; z++) {
double nz = seedZ + z * distort;
double distance = d2 + z * z;
double distance = d2 + z * z * modZ;
double noise = this.amplitude * SimplexNoise.noise(nx, ny, nz);
if (distance + distance * noise < radiusSqr) {
editSession.setBlock(px + x, py + y, pz + z, pattern);

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.DataAngleMask;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.Vector;
@ -10,7 +11,7 @@ import com.sk89q.worldedit.extent.Extent;
import java.io.IOException;
public class AngleColorPattern extends DataAngleMask {
private static final double FACTOR = 1d / 196;
private static final double FACTOR = 1d / 256;
private transient TextureUtil util;
private final boolean randomize;
@ -25,7 +26,7 @@ public class AngleColorPattern extends DataAngleMask {
public int getColor(int color, int slope) {
if (slope == 0) return color;
double newFactor = (196 - Math.min(196, slope)) * FACTOR;
double newFactor = (256 - Math.min(256, slope)) * FACTOR;
int newRed = (int) (((color >> 16) & 0xFF) * newFactor);
int newGreen = (int) (((color >> 8) & 0xFF) * newFactor);
int newBlue = (int) (((color >> 0) & 0xFF) * newFactor);
@ -43,6 +44,24 @@ public class AngleColorPattern extends DataAngleMask {
return util.getNearestBlock(newColor);
}
@Override
public int getSlope(BaseBlock block, Vector vector) {
int slope = super.getSlope(block, vector);
if (slope != -1) {
int x = vector.getBlockX();
int y = vector.getBlockY();
int z = vector.getBlockZ();
int height = extent.getNearestSurfaceTerrainBlock(x, y, z, 0, maxY);
if (height > 0) {
BaseBlock below = extent.getLazyBlock(x, height - 1, z);
if (FaweCache.canPassThrough(block.getId(), block.getData())) {
return Integer.MAX_VALUE;
}
}
}
return slope;
}
@Override
public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException {
BaseBlock block = extent.getBlock(getPosition);

View File

@ -52,6 +52,7 @@ import com.boydti.fawe.object.brush.SurfaceSpline;
import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
import com.boydti.fawe.object.mask.IdMask;
import com.boydti.fawe.util.ColorUtil;
import com.boydti.fawe.util.MathMan;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandLocals;
@ -296,12 +297,13 @@ public class BrushCommands extends MethodCommands {
max = 4
)
@CommandPermissions("worldedit.brush.blob")
public BrushSettings blobBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") double radius, @Optional("30") double frequency, @Optional("50") double amplitude, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
Brush brush = new BlobBrush(frequency / 100, amplitude / 100);
public BrushSettings blobBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") Vector radius, @Optional("30") double frequency, @Optional("50") double amplitude, CommandContext context) throws WorldEditException {
double max = MathMan.max(radius.getBlockX(), radius.getBlockY(), radius.getBlockZ());
worldEdit.checkMaxBrushRadius(max);
Brush brush = new BlobBrush(radius.divide(max), frequency / 100, amplitude / 100);
return get(context)
.setBrush(brush)
.setSize(radius)
.setSize(max)
.setFill(fill);
}

View File

@ -289,6 +289,23 @@ public class BrushOptionsCommands extends MethodCommands {
BBC.BRUSH_TARGET_MASK_SET.send(player, context.getJoinedStrings(0));
}
@Command(
aliases = {"targetoffset", "to"},
usage = "[mask]",
desc = "Set the targeting mask",
min = 1,
max = -1
)
public void targetOffset(Player player, EditSession editSession, LocalSession session, int offset) throws WorldEditException {
BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {
BBC.BRUSH_NONE.send(player);
return;
}
tool.setTargetOffset(offset);
BBC.BRUSH_TARGET_OFFSET_SET.send(player, offset);
}
@Command(
aliases = {"scroll"},
usage = "[none|clipboard|mask|pattern|range|size|visual|target]",

View File

@ -247,8 +247,8 @@ public class GenerationCommands extends MethodCommands {
)
@CommandPermissions("worldedit.generation.sphere")
@Logging(PLACEMENT)
public void hsphere(FawePlayer fp, Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("false") boolean raised, CommandContext context) throws WorldEditException, ParameterException {
sphere(fp, player, session, editSession, pattern, radiusString, raised, true, context);
public void hsphere(FawePlayer fp, Player player, LocalSession session, EditSession editSession, Pattern pattern, Vector radius, @Optional("false") boolean raised, CommandContext context) throws WorldEditException, ParameterException {
sphere(fp, player, session, editSession, pattern, radius, raised, true, context);
}
@Command(
@ -266,37 +266,17 @@ public class GenerationCommands extends MethodCommands {
)
@CommandPermissions("worldedit.generation.sphere")
@Logging(PLACEMENT)
public void sphere(FawePlayer fp, Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("false") boolean raised, @Switch('h') boolean hollow, CommandContext context) throws WorldEditException, ParameterException {
String[] radii = radiusString.split(",");
final double radiusX, radiusY, radiusZ;
switch (radii.length) {
case 1:
radiusX = radiusY = radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0]));
break;
case 3:
radiusX = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0]));
radiusY = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[1]));
radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[2]));
break;
default:
fp.sendMessage(BBC.getPrefix() + "You must either specify 1 or 3 radius values.");
return;
}
worldEdit.checkMaxRadius(radiusX);
worldEdit.checkMaxRadius(radiusY);
worldEdit.checkMaxRadius(radiusZ);
double max = MathMan.max(radiusX, radiusY, radiusZ);
public void sphere(FawePlayer fp, Player player, LocalSession session, EditSession editSession, Pattern pattern, Vector radius, @Optional("false") boolean raised, @Switch('h') boolean hollow, CommandContext context) throws WorldEditException, ParameterException {
double max = MathMan.max(radius.getBlockX(), radius.getBlockY(), radius.getBlockZ());
worldEdit.checkMaxBrushRadius(max);
fp.checkConfirmationRadius(getArguments(context), (int) max);
Vector pos = session.getPlacementPosition(player);
if (raised) {
pos = pos.add(0, radiusY, 0);
pos = pos.add(0, radius.getBlockY(), 0);
}
int affected = editSession.makeSphere(pos, pattern, radiusX, radiusY, radiusZ, !hollow);
int affected = editSession.makeSphere(pos, pattern, radius.getBlockX(), radius.getBlockY(), radius.getBlockZ(), !hollow);
player.findFreePosition();
BBC.VISITOR_BLOCK.send(fp, affected);
}

View File

@ -72,6 +72,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
private VisualMode visualMode = VisualMode.NONE;
private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE;
private Mask targetMask = null;
private int targetOffset;
private transient BrushSettings primary = new BrushSettings();
private transient BrushSettings secondary = new BrushSettings();
@ -98,11 +99,13 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
VisualMode visual = VisualMode.valueOf((String) root.getOrDefault("visual", "NONE"));
TargetMode target = TargetMode.valueOf((String) root.getOrDefault("target", "TARGET_BLOCK_RANGE"));
int range = ((Number) root.getOrDefault("range", -1)).intValue();
int offset = ((Number) root.getOrDefault("offset", 0)).intValue();
BrushTool tool = new BrushTool();
tool.visualMode = visual;
tool.targetMode = target;
tool.range = range;
tool.targetOffset = offset;
BrushSettings primarySettings = BrushSettings.get(tool, player, session, primary);
tool.setPrimary(primarySettings);
@ -130,6 +133,9 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
if (range != -1) {
map.put("range", range);
}
if (targetOffset != 0) {
map.put("offset", targetOffset);
}
return new Gson().toJson(map);
}
@ -336,21 +342,20 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
}
public Vector getPosition(EditSession editSession, Player player) {
Location loc = player.getLocation();
switch (targetMode) {
case TARGET_BLOCK_RANGE:
return new MutableBlockVector(trace(editSession, player, getRange(), true));
return offset(new MutableBlockVector(trace(editSession, player, getRange(), true)), loc.toVector());
case FOWARD_POINT_PITCH: {
int d = 0;
Location loc = player.getLocation();
float pitch = loc.getPitch();
pitch = 23 - (pitch / 4);
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 new MutableBlockVector(vector);
return offset(new MutableBlockVector(vector), loc.toVector());
}
case TARGET_POINT_HEIGHT: {
Location loc = player.getLocation();
final int height = loc.getBlockY();
final int x = loc.getBlockX();
final int z = loc.getBlockZ();
@ -362,15 +367,20 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
}
}
final int distance = (height - y) + 8;
return new MutableBlockVector(trace(editSession, player, distance, true));
return offset(new MutableBlockVector(trace(editSession, player, distance, true)), loc.toVector());
}
case TARGET_FACE_RANGE:
return new MutableBlockVector(trace(editSession, player, getRange(), true));
return offset(new MutableBlockVector(trace(editSession, player, getRange(), true)), loc.toVector());
default:
return null;
}
}
private Vector offset(Vector target, Vector playerPos) {
if (targetOffset == 0) return target;
return target.subtract(target.subtract(playerPos).normalize().multiply(targetOffset));
}
private Vector trace(EditSession editSession, Player player, int range, boolean useLastBlock) {
Mask mask = targetMask == null ? new SolidBlockMask(editSession) : targetMask;
new MaskTraverser(mask).reset(editSession);
@ -464,6 +474,10 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
this.getContext().setScrollAction(scrollAction);
}
public void setTargetOffset(int targetOffset) {
this.targetOffset = targetOffset;
}
public void setTargetMode(TargetMode targetMode) {
this.targetMode = targetMode != null ? targetMode : TargetMode.TARGET_BLOCK_RANGE;
}
@ -493,6 +507,10 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
return targetMode;
}
public int getTargetOffset() {
return targetOffset;
}
public Mask getTargetMask() {
return targetMask;
}