2019-06-20 20:05:18 -04:00

178 lines
7.4 KiB
Java

package com.thevoxelbox.voxelsniper.brush;
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.thevoxelbox.voxelsniper.Message;
import com.thevoxelbox.voxelsniper.SnipeData;
import com.thevoxelbox.voxelsniper.Undo;
import org.bukkit.ChatColor;
public class CopyPastaBrush extends Brush {
private static final int BLOCK_LIMIT = 10000;
private boolean pasteAir = true; // False = no air, true = air
private int points = 0; //
private int numBlocks = 0;
private int[] firstPoint = new int[3];
private int[] secondPoint = new int[3];
private int[] pastePoint = new int[3];
private int[] minPoint = new int[3];
private int[] offsetPoint = new int[3];
private int[] blockArray;
private int[] arraySize = new int[3];
private int pivot = 0; // ccw degrees
public CopyPastaBrush() {
this.setName("CopyPasta");
}
private void doCopy(final SnipeData v) {
for (int i = 0; i < 3; i++) {
this.arraySize[i] = Math.abs(this.firstPoint[i] - this.secondPoint[i]) + 1;
this.minPoint[i] = Math.min(this.firstPoint[i], this.secondPoint[i]);
this.offsetPoint[i] = this.minPoint[i] - this.firstPoint[i]; // will always be negative or zero
}
this.numBlocks = (this.arraySize[0]) * (this.arraySize[1]) * (this.arraySize[2]);
if (this.numBlocks > 0 && this.numBlocks < CopyPastaBrush.BLOCK_LIMIT) {
this.blockArray = new int[this.numBlocks];
for (int i = 0; i < this.arraySize[0]; i++) {
for (int j = 0; j < this.arraySize[1]; j++) {
for (int k = 0; k < this.arraySize[2]; k++) {
final int currentPosition = i + this.arraySize[0] * j + this.arraySize[0] * this.arraySize[1] * k;
this.blockArray[currentPosition] = this.getWorld().getBlockAt(this.minPoint[0] + i, this.minPoint[1] + j, this.minPoint[2] + k).getCombinedId();
}
}
}
v.sendMessage(ChatColor.AQUA + "" + this.numBlocks + " blocks copied.");
} else {
v.sendMessage(ChatColor.RED + "Copy area too big: " + this.numBlocks + "(Limit: " + CopyPastaBrush.BLOCK_LIMIT + ")");
}
}
@SuppressWarnings("deprecation")
private void doPasta(final SnipeData v) {
final Undo undo = new Undo();
for (int i = 0; i < this.arraySize[0]; i++) {
for (int j = 0; j < this.arraySize[1]; j++) {
for (int k = 0; k < this.arraySize[2]; k++) {
final int currentPosition = i + this.arraySize[0] * j + this.arraySize[0] * this.arraySize[1] * k;
AsyncBlock block;
switch (this.pivot) {
case 180:
block = this.clampY(this.pastePoint[0] - this.offsetPoint[0] - i, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] - this.offsetPoint[2] - k);
break;
case 270:
block = this.clampY(this.pastePoint[0] + this.offsetPoint[2] + k, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] - this.offsetPoint[0] - i);
break;
case 90:
block = this.clampY(this.pastePoint[0] - this.offsetPoint[2] - k, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] + this.offsetPoint[0] + i);
break;
default: // assume no rotation
block = this.clampY(this.pastePoint[0] + this.offsetPoint[0] + i, this.pastePoint[1] + this.offsetPoint[1] + j, this.pastePoint[2] + this.offsetPoint[2] + k);
break;
}
if (!(BlockTypes.getFromStateId(this.blockArray[currentPosition]).getMaterial().isAir() && !this.pasteAir)) {
if (block.getCombinedId() != this.blockArray[currentPosition]) {
undo.put(block);
}
block.setCombinedId(this.blockArray[currentPosition]);
}
}
}
}
v.sendMessage(ChatColor.AQUA + "" + this.numBlocks + " blocks pasted.");
v.owner().storeUndo(undo);
}
@Override
protected final void arrow(final SnipeData v) {
switch (this.points) {
case 0:
this.firstPoint[0] = this.getTargetBlock().getX();
this.firstPoint[1] = this.getTargetBlock().getY();
this.firstPoint[2] = this.getTargetBlock().getZ();
v.sendMessage(ChatColor.GRAY + "First point");
this.points = 1;
break;
case 1:
this.secondPoint[0] = this.getTargetBlock().getX();
this.secondPoint[1] = this.getTargetBlock().getY();
this.secondPoint[2] = this.getTargetBlock().getZ();
v.sendMessage(ChatColor.GRAY + "Second point");
this.points = 2;
break;
default:
this.firstPoint = new int[3];
this.secondPoint = new int[3];
this.numBlocks = 0;
this.blockArray = new int[1];
this.points = 0;
v.sendMessage(ChatColor.GRAY + "Points cleared.");
break;
}
}
@Override
protected final void powder(final SnipeData v) {
if (this.points == 2) {
if (this.numBlocks == 0) {
this.doCopy(v);
} else if (this.numBlocks > 0 && this.numBlocks < CopyPastaBrush.BLOCK_LIMIT) {
this.pastePoint[0] = this.getTargetBlock().getX();
this.pastePoint[1] = this.getTargetBlock().getY();
this.pastePoint[2] = this.getTargetBlock().getZ();
this.doPasta(v);
} else {
v.sendMessage(ChatColor.RED + "Error");
}
} else {
v.sendMessage(ChatColor.RED + "You must select exactly two points.");
}
}
@Override
public final void info(final Message vm) {
vm.brushName(this.getName());
vm.custom(ChatColor.GOLD + "Paste air: " + this.pasteAir);
vm.custom(ChatColor.GOLD + "Pivot angle: " + this.pivot);
}
@Override
public final void parameters(final String[] par, final SnipeData v) {
final String parameter = par[1];
if (parameter.equalsIgnoreCase("info")) {
v.sendMessage(ChatColor.GOLD + "CopyPasta Parameters:");
v.sendMessage(ChatColor.AQUA + "/b cp air -- toggle include (default) or exclude air during paste");
v.sendMessage(ChatColor.AQUA + "/b cp 0|90|180|270 -- toggle rotation (0 default)");
return;
}
if (parameter.equalsIgnoreCase("air")) {
this.pasteAir = !this.pasteAir;
v.sendMessage(ChatColor.GOLD + "Paste air: " + this.pasteAir);
return;
}
if (parameter.equalsIgnoreCase("90") || parameter.equalsIgnoreCase("180") || parameter.equalsIgnoreCase("270") || parameter.equalsIgnoreCase("0")) {
this.pivot = Integer.parseInt(parameter);
v.sendMessage(ChatColor.GOLD + "Pivot angle: " + this.pivot);
}
}
@Override
public String getPermissionNode() {
return "voxelsniper.brush.copypasta";
}
}