geforkt von Mirrors/FastAsyncWorldEdit
Update favs
Dieser Commit ist enthalten in:
Ursprung
9927cde616
Commit
f43faae917
24
favs/build.gradle
Normale Datei
24
favs/build.gradle
Normale Datei
@ -0,0 +1,24 @@
|
||||
repositories {
|
||||
maven {url "http://vault.voxelmodpack.com/content/repositories/central/"}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':worldedit-bukkit')
|
||||
compile 'com.martiansoftware:jsap:2.1'
|
||||
}
|
||||
|
||||
processResources {
|
||||
from('src/main/resources') {
|
||||
include 'plugin.yml'
|
||||
expand(
|
||||
name: project.parent.name,
|
||||
version: project.parent.version
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
jar.destinationDir = file '../target'
|
||||
jar.archiveName = "FastAsyncVoxelSniper-${project.name}-${parent.version}.jar"
|
||||
jar.doLast { task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
30
favs/src/main/java/com/boydti/fawe/bukkit/favs/PatternUtil.java
Normale Datei
30
favs/src/main/java/com/boydti/fawe/bukkit/favs/PatternUtil.java
Normale Datei
@ -0,0 +1,30 @@
|
||||
package com.boydti.fawe.bukkit.favs;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PatternUtil {
|
||||
public static Pattern parsePattern(Player player, SnipeData snipeData, String arg) {
|
||||
ParserContext context = new ParserContext();
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
context.setActor(fp.getPlayer());
|
||||
context.setWorld(fp.getWorld());
|
||||
context.setSession(fp.getSession());
|
||||
try {
|
||||
Pattern pattern = WorldEdit.getInstance().getPatternFactory().parseFromInput(arg, context);
|
||||
snipeData.setPattern(pattern, arg);
|
||||
snipeData.sendMessage(ChatColor.GOLD + "Voxel: " + ChatColor.RED + arg);
|
||||
return pattern;
|
||||
} catch (InputParseException e) {
|
||||
fp.sendMessage(BBC.getPrefix() + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
92
favs/src/main/java/com/thevoxelbox/voxelsniper/Brushes.java
Normale Datei
92
favs/src/main/java/com/thevoxelbox/voxelsniper/Brushes.java
Normale Datei
@ -0,0 +1,92 @@
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.thevoxelbox.voxelsniper.brush.IBrush;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Brush registration manager.
|
||||
*/
|
||||
public class Brushes
|
||||
{
|
||||
private Multimap<Class<? extends IBrush>, String> brushes = HashMultimap.create();
|
||||
|
||||
/**
|
||||
* Register a brush for VoxelSniper to be able to use.
|
||||
*
|
||||
* @param clazz Brush implementing IBrush interface.
|
||||
* @param handles Handles under which the brush can be accessed ingame.
|
||||
*/
|
||||
public void registerSniperBrush(Class<? extends IBrush> clazz, String... handles)
|
||||
{
|
||||
Preconditions.checkNotNull(clazz, "Cannot register null as a class.");
|
||||
for (String handle : handles)
|
||||
{
|
||||
brushes.put(clazz, handle.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Brush class via handle Lookup.
|
||||
*
|
||||
* @param handle Case insensitive brush handle
|
||||
* @return Brush class
|
||||
*/
|
||||
public Class<? extends IBrush> getBrushForHandle(String handle)
|
||||
{
|
||||
Preconditions.checkNotNull(handle, "Brushhandle can not be null.");
|
||||
if (!brushes.containsValue(handle.toLowerCase()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Map.Entry<Class<? extends IBrush>, String> entry : brushes.entries())
|
||||
{
|
||||
if (entry.getValue().equalsIgnoreCase(handle))
|
||||
{
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Amount of IBrush classes registered with the system under Sniper visibility.
|
||||
*/
|
||||
public int registeredSniperBrushes()
|
||||
{
|
||||
return brushes.keySet().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Amount of handles registered with the system under Sniper visibility.
|
||||
*/
|
||||
public int registeredSniperBrushHandles()
|
||||
{
|
||||
return brushes.size();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param clazz Brush class
|
||||
* @return All Sniper registered handles for the brush.
|
||||
*/
|
||||
public Set<String> getSniperBrushHandles(Class<? extends IBrush> clazz)
|
||||
{
|
||||
return new HashSet<String>(brushes.get(clazz));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Immutable Multimap copy of all the registered brushes
|
||||
*/
|
||||
public Multimap<Class<?extends IBrush>, String> getRegisteredBrushesMultimap()
|
||||
{
|
||||
return ImmutableMultimap.copyOf(brushes);
|
||||
}
|
||||
}
|
169
favs/src/main/java/com/thevoxelbox/voxelsniper/Message.java
Normale Datei
169
favs/src/main/java/com/thevoxelbox/voxelsniper/Message.java
Normale Datei
@ -0,0 +1,169 @@
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Message
|
||||
{
|
||||
private static final int BRUSH_SIZE_WARNING_THRESHOLD = 20;
|
||||
private final SnipeData snipeData;
|
||||
|
||||
/**
|
||||
* @param snipeData
|
||||
*/
|
||||
public Message(SnipeData snipeData)
|
||||
{
|
||||
this.snipeData = snipeData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a brush message styled message to the player.
|
||||
*
|
||||
* @param brushMessage
|
||||
*/
|
||||
public void brushMessage(String brushMessage)
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.LIGHT_PURPLE + brushMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display Brush Name.
|
||||
*
|
||||
* @param brushName
|
||||
*/
|
||||
public void brushName(String brushName)
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.AQUA + "Brush Type: " + ChatColor.LIGHT_PURPLE + brushName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display Center Parameter.
|
||||
*/
|
||||
public void center()
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.DARK_BLUE + "Brush Center: " + ChatColor.DARK_RED + snipeData.getcCen());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display custom message.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public void custom(String message)
|
||||
{
|
||||
snipeData.sendMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display data value.
|
||||
*/
|
||||
public void data()
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.BLUE + "Data Variable: " + ChatColor.DARK_RED + snipeData.getPropertyId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display voxel height.
|
||||
*/
|
||||
public void height()
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.DARK_AQUA + "Brush Height: " + ChatColor.DARK_RED + snipeData.getVoxelHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display performer.
|
||||
*
|
||||
* @param performerName
|
||||
*/
|
||||
public void performerName(String performerName)
|
||||
{
|
||||
this.snipeData.sendMessage(ChatColor.DARK_PURPLE + "Performer: " + ChatColor.DARK_GREEN + performerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displaye replace material.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void replace()
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.AQUA + "Replace Material: " + ChatColor.RED + snipeData.getReplaceId() + ChatColor.GRAY + " (" + BlockTypes.get(snipeData.getReplaceId()).toString() + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Display replace data value.
|
||||
*/
|
||||
public void replaceData()
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.DARK_GRAY + "Replace Data Variable: " + ChatColor.DARK_RED + snipeData.getReplaceData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display brush size.
|
||||
*/
|
||||
public void size()
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.GREEN + "Brush Size: " + ChatColor.DARK_RED + snipeData.getBrushSize());
|
||||
if (snipeData.getBrushSize() >= BRUSH_SIZE_WARNING_THRESHOLD)
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.RED + "WARNING: Large brush size selected!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display toggle lightning message.
|
||||
*/
|
||||
public void toggleLightning()
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.GOLD + "Lightning mode has been toggled " + ChatColor.DARK_RED + ((snipeData.owner().getSnipeData(snipeData.owner().getCurrentToolId()).isLightningEnabled()) ? "on" : "off"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display toggle printout message.
|
||||
*/
|
||||
public final void togglePrintout()
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.GOLD + "Brush info printout mode has been toggled " + ChatColor.DARK_RED + ((snipeData.owner().getSnipeData(snipeData.owner().getCurrentToolId()).isLightningEnabled()) ? "on" : "off"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display toggle range message.
|
||||
*/
|
||||
public void toggleRange()
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.GOLD + "Distance Restriction toggled " + ChatColor.DARK_RED + ((snipeData.owner().getSnipeData(snipeData.owner().getCurrentToolId()).isRanged()) ? "on" : "off") + ChatColor.GOLD + ". Range is " + ChatColor.LIGHT_PURPLE + (double) snipeData.owner().getSnipeData(snipeData.owner().getCurrentToolId()).getRange());
|
||||
}
|
||||
|
||||
/**
|
||||
* Display voxel type.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void voxel()
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.GOLD + "Voxel: " + ChatColor.RED + snipeData.getVoxelId() + ChatColor.GRAY + " (" + BlockTypes.get(snipeData.getVoxelId()).toString() + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Display voxel list.
|
||||
*/
|
||||
public void voxelList()
|
||||
{
|
||||
if (snipeData.getVoxelList().isEmpty())
|
||||
{
|
||||
snipeData.sendMessage(ChatColor.DARK_GREEN + "No blocks selected!");
|
||||
}
|
||||
else
|
||||
{
|
||||
StringBuilder returnValueBuilder = new StringBuilder();
|
||||
returnValueBuilder.append(ChatColor.DARK_GREEN);
|
||||
returnValueBuilder.append("Block Types Selected: ");
|
||||
returnValueBuilder.append(ChatColor.AQUA);
|
||||
returnValueBuilder.append(snipeData.getVoxelList());
|
||||
snipeData.sendMessage(returnValueBuilder.toString());
|
||||
}
|
||||
}
|
||||
}
|
102
favs/src/main/java/com/thevoxelbox/voxelsniper/PaintingWrapper.java
Normale Datei
102
favs/src/main/java/com/thevoxelbox/voxelsniper/PaintingWrapper.java
Normale Datei
@ -0,0 +1,102 @@
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import org.bukkit.Art;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Painting;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Painting state change handler.
|
||||
*
|
||||
* @author Piotr
|
||||
*/
|
||||
public final class PaintingWrapper
|
||||
{
|
||||
|
||||
private PaintingWrapper()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The paint method used to scroll or set a painting to a specific type.
|
||||
*
|
||||
* @param p
|
||||
* The player executing the method
|
||||
* @param auto
|
||||
* Scroll automatically? If false will use 'choice' to try and set the painting
|
||||
* @param back
|
||||
* Scroll in reverse?
|
||||
* @param choice
|
||||
* Chosen index to set the painting to
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void paint(final Player p, final boolean auto, final boolean back, final int choice)
|
||||
{
|
||||
Location targetLocation = p.getTargetBlock((Set<Material>) null, 4).getLocation();
|
||||
Chunk paintingChunk = p.getTargetBlock((Set<Material>) null, 4).getLocation().getChunk();
|
||||
|
||||
Double bestDistanceMatch = 50D;
|
||||
Painting bestMatch = null;
|
||||
|
||||
for (Entity entity : paintingChunk.getEntities())
|
||||
{
|
||||
if (entity.getType() == EntityType.PAINTING)
|
||||
{
|
||||
Double distance = targetLocation.distanceSquared(entity.getLocation());
|
||||
|
||||
if (distance <= 4 && distance < bestDistanceMatch)
|
||||
{
|
||||
bestDistanceMatch = distance;
|
||||
bestMatch = (Painting) entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestMatch != null)
|
||||
{
|
||||
if (auto)
|
||||
{
|
||||
try
|
||||
{
|
||||
final int i = bestMatch.getArt().getId() + (back ? -1 : 1) + Art.values().length % Art.values().length;
|
||||
Art art = Art.getById(i);
|
||||
|
||||
if (art == null)
|
||||
{
|
||||
p.sendMessage(ChatColor.RED + "This is the final painting, try scrolling to the other direction.");
|
||||
return;
|
||||
}
|
||||
|
||||
bestMatch.setArt(art);
|
||||
p.sendMessage(ChatColor.GREEN + "Painting set to ID: " + (i));
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
p.sendMessage(ChatColor.RED + "Oops. Something went wrong.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
Art art = Art.getById(choice);
|
||||
|
||||
bestMatch.setArt(art);
|
||||
p.sendMessage(ChatColor.GREEN + "Painting set to ID: " + choice);
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
p.sendMessage(ChatColor.RED + "Your input was invalid somewhere.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
303
favs/src/main/java/com/thevoxelbox/voxelsniper/RangeBlockHelper.java
Normale Datei
303
favs/src/main/java/com/thevoxelbox/voxelsniper/RangeBlockHelper.java
Normale Datei
@ -0,0 +1,303 @@
|
||||
/**
|
||||
This file is part of VoxelSniper, licensed under the MIT License (MIT).
|
||||
|
||||
Copyright (c) The VoxelBox <http://thevoxelbox.com>
|
||||
Copyright (c) contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncWorld;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class RangeBlockHelper {
|
||||
private static final int MAXIMUM_WORLD_HEIGHT = 255;
|
||||
private static final double DEFAULT_PLAYER_VIEW_HEIGHT = 1.65D;
|
||||
private static final double DEFAULT_LOCATION_VIEW_HEIGHT = 0.0D;
|
||||
private static final double DEFAULT_STEP = 0.2D;
|
||||
private static final int DEFAULT_RANGE = 250;
|
||||
private Location playerLoc;
|
||||
private double rotX;
|
||||
private double rotY;
|
||||
private double viewHeight;
|
||||
private double rotXSin;
|
||||
private double rotXCos;
|
||||
private double rotYSin;
|
||||
private double rotYCos;
|
||||
private double length;
|
||||
private double hLength;
|
||||
private double step;
|
||||
private double range;
|
||||
private double playerX;
|
||||
private double playerY;
|
||||
private double playerZ;
|
||||
private double xOffset;
|
||||
private double yOffset;
|
||||
private double zOffset;
|
||||
private int lastX;
|
||||
private int lastY;
|
||||
private int lastZ;
|
||||
private int targetX;
|
||||
private int targetY;
|
||||
private int targetZ;
|
||||
private AsyncWorld world;
|
||||
|
||||
public RangeBlockHelper(Location location) {
|
||||
this.init(location, 250.0D, 0.2D, 0.0D);
|
||||
}
|
||||
|
||||
public RangeBlockHelper(Location location, int range, double step) {
|
||||
this.world = (AsyncWorld) location.getWorld();
|
||||
this.init(location, (double)range, step, 0.0D);
|
||||
}
|
||||
|
||||
public RangeBlockHelper(Player player, int range, double step) {
|
||||
if (player != null) {
|
||||
this.world = VoxelSniper.getInstance().getSniperManager().getSniperForPlayer(player).getWorld();
|
||||
}
|
||||
this.init(player.getLocation(), (double)range, step, 1.65D);
|
||||
}
|
||||
|
||||
public RangeBlockHelper(Player player, AsyncWorld world) {
|
||||
if (player != null && (world == null || player.getWorld().getName().equals(world.getName()))) {
|
||||
this.world = VoxelSniper.getInstance().getSniperManager().getSniperForPlayer(player).getWorld();
|
||||
} else {
|
||||
this.world = world;
|
||||
}
|
||||
this.init(player.getLocation(), 250.0D, 0.2D, 1.65D);
|
||||
}
|
||||
|
||||
public RangeBlockHelper(Player player, AsyncWorld world, double range) {
|
||||
if (player != null && (world == null || player.getWorld().getName().equals(world.getName()))) {
|
||||
this.world = VoxelSniper.getInstance().getSniperManager().getSniperForPlayer(player).getWorld();
|
||||
} else {
|
||||
this.world = world;
|
||||
}
|
||||
this.init(player.getLocation(), range, 0.2D, 1.65D);
|
||||
this.fromOffworld();
|
||||
}
|
||||
|
||||
public final void fromOffworld() {
|
||||
if(this.targetY <= 255) {
|
||||
if(this.targetY < 0) {
|
||||
while(this.targetY < 0 && this.length <= this.range) {
|
||||
this.lastX = this.targetX;
|
||||
this.lastY = this.targetY;
|
||||
this.lastZ = this.targetZ;
|
||||
|
||||
while(true) {
|
||||
this.length += this.step;
|
||||
this.hLength = this.length * this.rotYCos;
|
||||
this.yOffset = this.length * this.rotYSin;
|
||||
this.xOffset = this.hLength * this.rotXCos;
|
||||
this.zOffset = this.hLength * this.rotXSin;
|
||||
this.targetX = (int)Math.floor(this.xOffset + this.playerX);
|
||||
this.targetY = (int)Math.floor(this.yOffset + this.playerY);
|
||||
this.targetZ = (int)Math.floor(this.zOffset + this.playerZ);
|
||||
if(this.length > this.range || this.targetX != this.lastX || this.targetY != this.lastY || this.targetZ != this.lastZ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while(this.targetY > 255 && this.length <= this.range) {
|
||||
this.lastX = this.targetX;
|
||||
this.lastY = this.targetY;
|
||||
this.lastZ = this.targetZ;
|
||||
|
||||
while(true) {
|
||||
this.length += this.step;
|
||||
this.hLength = this.length * this.rotYCos;
|
||||
this.yOffset = this.length * this.rotYSin;
|
||||
this.xOffset = this.hLength * this.rotXCos;
|
||||
this.zOffset = this.hLength * this.rotXSin;
|
||||
this.targetX = (int)Math.floor(this.xOffset + this.playerX);
|
||||
this.targetY = (int)Math.floor(this.yOffset + this.playerY);
|
||||
this.targetZ = (int)Math.floor(this.zOffset + this.playerZ);
|
||||
if(this.length > this.range || this.targetX != this.lastX || this.targetY != this.lastY || this.targetZ != this.lastZ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final AsyncBlock getCurBlock() {
|
||||
return this.length <= this.range && this.targetY <= 255 && this.targetY >= 0?this.world.getBlockAt(this.targetX, this.targetY, this.targetZ):null;
|
||||
}
|
||||
|
||||
private boolean isAir(Material m) {
|
||||
switch (m) {
|
||||
case AIR:
|
||||
case CAVE_AIR:
|
||||
case VOID_AIR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public final AsyncBlock getFaceBlock() {
|
||||
while(this.getNextBlock() != null && isAir(this.getCurBlock().getType())) {
|
||||
;
|
||||
}
|
||||
|
||||
if(this.getCurBlock() != null) {
|
||||
return this.getLastBlock();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public final AsyncBlock getLastBlock() {
|
||||
return this.lastY <= 255 && this.lastY >= 0?this.world.getBlockAt(this.lastX, this.lastY, this.lastZ):null;
|
||||
}
|
||||
|
||||
public final AsyncBlock getNextBlock() {
|
||||
this.lastX = this.targetX;
|
||||
this.lastY = this.targetY;
|
||||
this.lastZ = this.targetZ;
|
||||
|
||||
do {
|
||||
this.length += this.step;
|
||||
this.hLength = this.length * this.rotYCos;
|
||||
this.yOffset = this.length * this.rotYSin;
|
||||
this.xOffset = this.hLength * this.rotXCos;
|
||||
this.zOffset = this.hLength * this.rotXSin;
|
||||
this.targetX = (int)Math.floor(this.xOffset + this.playerX);
|
||||
this.targetY = (int)Math.floor(this.yOffset + this.playerY);
|
||||
this.targetZ = (int)Math.floor(this.zOffset + this.playerZ);
|
||||
} while(this.length <= this.range && this.targetX == this.lastX && this.targetY == this.lastY && this.targetZ == this.lastZ);
|
||||
|
||||
return this.length <= this.range && this.targetY <= 255 && this.targetY >= 0?this.world.getBlockAt(this.targetX, this.targetY, this.targetZ):null;
|
||||
}
|
||||
|
||||
public final AsyncBlock getRangeBlock() {
|
||||
this.fromOffworld();
|
||||
return this.length > this.range?null:this.getRange();
|
||||
}
|
||||
|
||||
public final AsyncBlock getTargetBlock() {
|
||||
this.fromOffworld();
|
||||
|
||||
while(this.getNextBlock() != null && isAir(this.getCurBlock().getType())) {
|
||||
;
|
||||
}
|
||||
|
||||
return this.getCurBlock();
|
||||
}
|
||||
|
||||
public final void setCurBlock(int type) {
|
||||
if(this.getCurBlock() != null) {
|
||||
this.world.getBlockAt(this.targetX, this.targetY, this.targetZ).setType(getType(type));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final void setFaceBlock(int type) {
|
||||
while(this.getNextBlock() != null && isAir(this.getCurBlock().getType())) {
|
||||
;
|
||||
}
|
||||
|
||||
if(this.getCurBlock() != null) {
|
||||
this.world.getBlockAt(this.targetX, this.targetY, this.targetZ).setType(getType(type));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Material getType(int id) {
|
||||
return BukkitAdapter.adapt(LegacyMapper.getInstance().getBlockFromLegacy(id).getBlockType());
|
||||
}
|
||||
|
||||
public final void setLastBlock(int type) {
|
||||
if(this.getLastBlock() != null) {
|
||||
this.world.getBlockAt(this.lastX, this.lastY, this.lastZ).setType(getType(type));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final void setTargetBlock(int type) {
|
||||
while(this.getNextBlock() != null && isAir(this.getCurBlock().getType())) {
|
||||
;
|
||||
}
|
||||
|
||||
if(this.getCurBlock() != null) {
|
||||
this.world.getBlockAt(this.targetX, this.targetY, this.targetZ).setType(getType(type));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private AsyncBlock getRange() {
|
||||
this.lastX = this.targetX;
|
||||
this.lastY = this.targetY;
|
||||
this.lastZ = this.targetZ;
|
||||
|
||||
do {
|
||||
this.length += this.step;
|
||||
this.hLength = this.length * this.rotYCos;
|
||||
this.yOffset = this.length * this.rotYSin;
|
||||
this.xOffset = this.hLength * this.rotXCos;
|
||||
this.zOffset = this.hLength * this.rotXSin;
|
||||
this.targetX = (int)Math.floor(this.xOffset + this.playerX);
|
||||
this.targetY = (int)Math.floor(this.yOffset + this.playerY);
|
||||
this.targetZ = (int)Math.floor(this.zOffset + this.playerZ);
|
||||
} while(this.length <= this.range && this.targetX == this.lastX && this.targetY == this.lastY && this.targetZ == this.lastZ);
|
||||
|
||||
AsyncBlock block = world.getBlockAt(this.targetX, this.targetY, this.targetZ);
|
||||
Material type = block.getType();
|
||||
return !isAir(type) ? block : (this.length <= this.range && this.targetY <= 255 && this.targetY >= 0?this.getRange():this.world.getBlockAt(this.lastX, this.lastY, this.lastZ));
|
||||
}
|
||||
|
||||
private void init(Location location, double range, double step, double viewHeight) {
|
||||
this.playerLoc = location;
|
||||
this.viewHeight = viewHeight;
|
||||
this.playerX = this.playerLoc.getX();
|
||||
this.playerY = this.playerLoc.getY() + this.viewHeight;
|
||||
this.playerZ = this.playerLoc.getZ();
|
||||
this.range = range;
|
||||
this.step = step;
|
||||
this.length = 0.0D;
|
||||
this.rotX = (double)((this.playerLoc.getYaw() + 90.0F) % 360.0F);
|
||||
this.rotY = (double)(this.playerLoc.getPitch() * -1.0F);
|
||||
this.rotYCos = Math.cos(Math.toRadians(this.rotY));
|
||||
this.rotYSin = Math.sin(Math.toRadians(this.rotY));
|
||||
this.rotXCos = Math.cos(Math.toRadians(this.rotX));
|
||||
this.rotXSin = Math.sin(Math.toRadians(this.rotX));
|
||||
this.targetX = (int)Math.floor(this.playerLoc.getX());
|
||||
this.targetY = (int)Math.floor(this.playerLoc.getY() + this.viewHeight);
|
||||
this.targetZ = (int)Math.floor(this.playerLoc.getZ());
|
||||
this.lastX = this.targetX;
|
||||
this.lastY = this.targetY;
|
||||
this.lastZ = this.targetZ;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return RangeBlockHelper.class;
|
||||
}
|
||||
}
|
9
favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeAction.java
Normale Datei
9
favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeAction.java
Normale Datei
@ -0,0 +1,9 @@
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public enum SnipeAction
|
||||
{
|
||||
ARROW, GUNPOWDER
|
||||
}
|
328
favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeData.java
Normale Datei
328
favs/src/main/java/com/thevoxelbox/voxelsniper/SnipeData.java
Normale Datei
@ -0,0 +1,328 @@
|
||||
/**
|
||||
This file is part of VoxelSniper, licensed under the MIT License (MIT).
|
||||
|
||||
Copyright (c) The VoxelBox <http://thevoxelbox.com>
|
||||
Copyright (c) contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.util.VoxelList;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @author Piotr
|
||||
*/
|
||||
public class SnipeData {
|
||||
|
||||
public static final int DEFAULT_REPLACE_DATA_VALUE = 0;
|
||||
public static final int DEFAULT_CYLINDER_CENTER = 0;
|
||||
public static final int DEFAULT_VOXEL_HEIGHT = 1;
|
||||
public static final int DEFAULT_BRUSH_SIZE = 3;
|
||||
public static final int DEFAULT_DATA_VALUE = 0;
|
||||
public static final int DEFAULT_REPLACE_ID = BlockTypes.AIR.getInternalId();
|
||||
public static final int DEFAULT_VOXEL_ID = BlockTypes.AIR.getInternalId();
|
||||
|
||||
private final Sniper owner;
|
||||
private Message voxelMessage;
|
||||
/**
|
||||
* Brush size -- set blockPositionY /b #.
|
||||
*/
|
||||
private int brushSize = SnipeData.DEFAULT_BRUSH_SIZE;
|
||||
/**
|
||||
* Voxel Id -- set blockPositionY /v (#,name).
|
||||
*/
|
||||
private int voxelId = SnipeData.DEFAULT_VOXEL_ID;
|
||||
/**
|
||||
* Voxel Replace Id -- set blockPositionY /vr #.
|
||||
*/
|
||||
private int replaceId = SnipeData.DEFAULT_REPLACE_ID;
|
||||
/**
|
||||
* Voxel 'ink' -- set blockPositionY /vi #.
|
||||
*/
|
||||
private int data = SnipeData.DEFAULT_DATA_VALUE;
|
||||
/**
|
||||
* Voxel 'ink' Replace -- set blockPositionY /vir #.
|
||||
*/
|
||||
private int replaceData = SnipeData.DEFAULT_REPLACE_DATA_VALUE;
|
||||
/**
|
||||
* Voxel List of ID's -- set blockPositionY /vl # # # -#.
|
||||
*/
|
||||
private VoxelList voxelList = new VoxelList();
|
||||
/**
|
||||
* Voxel 'heigth' -- set blockPositionY /vh #.
|
||||
*/
|
||||
private int voxelHeight = SnipeData.DEFAULT_VOXEL_HEIGHT;
|
||||
/**
|
||||
* Voxel centroid -- set Cylynder center /vc #.
|
||||
*/
|
||||
private int cCen = SnipeData.DEFAULT_CYLINDER_CENTER;
|
||||
private int range = 0;
|
||||
private boolean ranged = false;
|
||||
private boolean lightning = false;
|
||||
private Extent extent;
|
||||
private Pattern pattern;
|
||||
private String patternInfo;
|
||||
|
||||
/**
|
||||
* @param vs
|
||||
*/
|
||||
public SnipeData(final Sniper vs) {
|
||||
this.owner = vs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extent currently being used to set blocks
|
||||
* @return
|
||||
*/
|
||||
public Extent getExtent() {
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the extent currently being used to set blocks
|
||||
* @param extent
|
||||
*/
|
||||
public void setExtent(Extent extent) {
|
||||
this.extent = extent;
|
||||
}
|
||||
|
||||
public void setPattern(Pattern pattern, String info) {
|
||||
if (pattern != null) {
|
||||
if (info == null) info = "";
|
||||
} else {
|
||||
info = null;
|
||||
}
|
||||
this.pattern = pattern;
|
||||
this.patternInfo = info;
|
||||
}
|
||||
|
||||
public Pattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public String getPatternInfo() {
|
||||
return patternInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the brushSize
|
||||
*/
|
||||
public final int getBrushSize() {
|
||||
return this.brushSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cCen
|
||||
*/
|
||||
public final int getcCen() {
|
||||
return this.cCen;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the data
|
||||
*/
|
||||
public final int getPropertyId() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the replaceData
|
||||
*/
|
||||
public final int getReplaceData() {
|
||||
return this.replaceData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the replaceId
|
||||
*/
|
||||
public final int getReplaceId() {
|
||||
return this.replaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the voxelHeight
|
||||
*/
|
||||
public final int getVoxelHeight() {
|
||||
return this.voxelHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the voxelId
|
||||
*/
|
||||
public final int getVoxelId() {
|
||||
return this.voxelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the voxelList
|
||||
*/
|
||||
public final VoxelList getVoxelList() {
|
||||
return this.voxelList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the voxelMessage
|
||||
*/
|
||||
public final Message getVoxelMessage() {
|
||||
return this.voxelMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return World
|
||||
*/
|
||||
public final World getWorld() {
|
||||
return this.owner.getWorld(); // Changed
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Sniper
|
||||
*/
|
||||
public final Sniper owner() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset to default values.
|
||||
*/
|
||||
public final void reset() {
|
||||
this.voxelId = SnipeData.DEFAULT_VOXEL_ID;
|
||||
this.replaceId = SnipeData.DEFAULT_REPLACE_ID;
|
||||
this.data = SnipeData.DEFAULT_DATA_VALUE;
|
||||
this.brushSize = SnipeData.DEFAULT_BRUSH_SIZE;
|
||||
this.voxelHeight = SnipeData.DEFAULT_VOXEL_HEIGHT;
|
||||
this.cCen = SnipeData.DEFAULT_CYLINDER_CENTER;
|
||||
this.replaceData = SnipeData.DEFAULT_REPLACE_DATA_VALUE;
|
||||
this.voxelList = new VoxelList();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
*/
|
||||
public final void sendMessage(final String message) {
|
||||
this.owner.getPlayer().sendMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param brushSize the brushSize to set
|
||||
*/
|
||||
public final void setBrushSize(final int brushSize) {
|
||||
this.brushSize = brushSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cCen the cCen to set
|
||||
*/
|
||||
public final void setcCen(final int cCen) {
|
||||
this.cCen = cCen;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data the data to set
|
||||
*/
|
||||
public final void setData(final int data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param replaceData the replaceData to set
|
||||
*/
|
||||
public final void setReplaceData(final int replaceData) {
|
||||
this.replaceData = replaceData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param replaceId the replaceId to set
|
||||
*/
|
||||
public final void setReplaceId(final int replaceId) {
|
||||
this.replaceId = replaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param voxelHeight the voxelHeight to set
|
||||
*/
|
||||
public final void setVoxelHeight(final int voxelHeight) {
|
||||
this.voxelHeight = voxelHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param voxelId the voxelId to set
|
||||
*/
|
||||
public final void setVoxelId(final int voxelId) {
|
||||
if (WorldEdit.getInstance().getConfiguration().disallowedBlocks.contains(voxelId)) {
|
||||
if (owner != null) {
|
||||
Player plr = owner.getPlayer();
|
||||
if (plr != null) {
|
||||
plr.sendMessage(ChatColor.RED + "You are not allowed to use '" + voxelId + "'");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.voxelId = voxelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param voxelList the voxelList to set
|
||||
*/
|
||||
public final void setVoxelList(final VoxelList voxelList) {
|
||||
this.voxelList = voxelList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param voxelMessage the voxelMessage to set
|
||||
*/
|
||||
public final void setVoxelMessage(final Message voxelMessage) {
|
||||
this.voxelMessage = voxelMessage;
|
||||
}
|
||||
|
||||
public int getRange() {
|
||||
return range;
|
||||
}
|
||||
|
||||
public void setRange(int range) {
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
public boolean isRanged() {
|
||||
return ranged;
|
||||
}
|
||||
|
||||
public void setRanged(boolean ranged) {
|
||||
this.ranged = ranged;
|
||||
}
|
||||
|
||||
public boolean isLightningEnabled() {
|
||||
return lightning;
|
||||
}
|
||||
|
||||
public void setLightningEnabled(boolean lightning) {
|
||||
this.lightning = lightning;
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return SnipeData.class;
|
||||
}
|
||||
}
|
679
favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java
Normale Datei
679
favs/src/main/java/com/thevoxelbox/voxelsniper/Sniper.java
Normale Datei
@ -0,0 +1,679 @@
|
||||
/**
|
||||
This file is part of VoxelSniper, licensed under the MIT License (MIT).
|
||||
|
||||
Copyright (c) The VoxelBox <http://thevoxelbox.com>
|
||||
Copyright (c) contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncWorld;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.logging.LoggingChangeSet;
|
||||
import com.boydti.fawe.object.*;
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.boydti.fawe.object.extent.ResettableExtent;
|
||||
import com.boydti.fawe.object.extent.SourceMaskExtent;
|
||||
import com.boydti.fawe.object.queue.FaweQueueDelegateExtent;
|
||||
import com.boydti.fawe.util.MaskTraverser;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.boydti.fawe.util.WEManager;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.*;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.extent.MaskingExtent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.session.request.Request;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.brush.IBrush;
|
||||
import com.thevoxelbox.voxelsniper.brush.SnipeBrush;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.Performer;
|
||||
import com.thevoxelbox.voxelsniper.event.SniperMaterialChangedEvent;
|
||||
import com.thevoxelbox.voxelsniper.event.SniperReplaceMaterialChangedEvent;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
public class Sniper {
|
||||
private VoxelSniper plugin;
|
||||
private final UUID player;
|
||||
private boolean enabled = true;
|
||||
// private LinkedList<FaweChangeSet> undoList = new LinkedList<>();
|
||||
private Map<String, SniperTool> tools = new HashMap<>();
|
||||
|
||||
public Sniper(VoxelSniper plugin, Player player) {
|
||||
Preconditions.checkNotNull(plugin);
|
||||
Preconditions.checkNotNull(player);
|
||||
this.plugin = plugin;
|
||||
this.player = player.getUniqueId();
|
||||
SniperTool sniperTool = new SniperTool(this);
|
||||
sniperTool.assignAction(SnipeAction.ARROW, Material.ARROW);
|
||||
sniperTool.assignAction(SnipeAction.GUNPOWDER, Material.GUNPOWDER);
|
||||
tools.put(null, sniperTool);
|
||||
}
|
||||
|
||||
public String getCurrentToolId() {
|
||||
return getToolId((getPlayer().getItemInHand() != null) ? getPlayer().getItemInHand().getType() : null);
|
||||
}
|
||||
|
||||
public String getToolId(Material itemInHand) {
|
||||
if (itemInHand == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, SniperTool> entry : tools.entrySet()) {
|
||||
if (entry.getValue().hasToolAssigned(itemInHand)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Added
|
||||
private AsyncWorld permanentWorld;
|
||||
|
||||
public void storeUndo(Undo undo) {
|
||||
}
|
||||
|
||||
// Added
|
||||
public AsyncWorld getWorld() {
|
||||
AsyncWorld world = permanentWorld;
|
||||
if (world == null) {
|
||||
Player bukkitPlayer = getPlayer();
|
||||
World bukkitWorld = bukkitPlayer.getWorld();
|
||||
world = AsyncWorld.wrap(bukkitWorld);
|
||||
permanentWorld = world;
|
||||
}
|
||||
return world;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return Bukkit.getPlayer(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sniper execution call.
|
||||
*
|
||||
* @param action Action player performed
|
||||
* @param itemInHand Item in hand of player
|
||||
* @param clickedBlock Block that the player targeted/interacted with
|
||||
* @param clickedFace Face of that targeted Block
|
||||
* @return true if command visibly processed, false otherwise.
|
||||
*/
|
||||
public boolean snipe(final Action action, final Material itemInHand, final Block clickedBlock, final BlockFace clickedFace) {
|
||||
switch (action) {
|
||||
case LEFT_CLICK_AIR:
|
||||
case LEFT_CLICK_BLOCK:
|
||||
case RIGHT_CLICK_AIR:
|
||||
case RIGHT_CLICK_BLOCK:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (tools.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String toolId = getToolId(itemInHand);
|
||||
SniperTool sniperTool = tools.get(toolId);
|
||||
if (sniperTool == null) {
|
||||
return false;
|
||||
}
|
||||
if (!sniperTool.hasToolAssigned(itemInHand)) {
|
||||
return false;
|
||||
}
|
||||
if (sniperTool.getCurrentBrush() == null) {
|
||||
getPlayer().sendMessage("No Brush selected.");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Player player = getPlayer();
|
||||
final FawePlayer<Player> fp = FawePlayer.wrap(player);
|
||||
TaskManager.IMP.taskNow(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!fp.runAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
snipeOnCurrentThread(fp, action, itemInHand, clickedBlock, clickedFace, sniperTool, toolId);
|
||||
}
|
||||
}, false, true)) {
|
||||
BBC.WORLDEDIT_COMMAND_LIMIT.send(fp);
|
||||
}
|
||||
}
|
||||
}, Fawe.isMainThread());
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Old method (plus world arg)
|
||||
public synchronized boolean snipeOnCurrentThread(FawePlayer fp, final Action action, final Material itemInHand, Block clickedBlock, final BlockFace clickedFace, SniperTool sniperTool, String toolId) {
|
||||
try {
|
||||
Player bukkitPlayer = getPlayer();
|
||||
World bukkitWorld = bukkitPlayer.getWorld();
|
||||
|
||||
FaweQueue baseQueue = fp.getFaweQueue(false);
|
||||
Region[] mask = WEManager.IMP.getMask(fp);
|
||||
if (mask.length == 0) {
|
||||
BBC.NO_REGION.send(fp);
|
||||
return false;
|
||||
}
|
||||
MaskedFaweQueue maskQueue = new MaskedFaweQueue(baseQueue, mask);
|
||||
com.sk89q.worldedit.world.World worldEditWorld = fp.getWorld();
|
||||
FaweChangeSet changeSet = FaweChangeSet.getDefaultChangeSet(worldEditWorld, fp.getUUID());
|
||||
if (Fawe.imp().getBlocksHubApi() != null) {
|
||||
changeSet = LoggingChangeSet.wrap(fp, changeSet);
|
||||
}
|
||||
FaweQueue changeQueue;
|
||||
if (Settings.IMP.HISTORY.COMBINE_STAGES) {
|
||||
changeQueue = maskQueue;
|
||||
changeSet.addChangeTask(baseQueue);
|
||||
} else {
|
||||
changeQueue = new ChangeSetFaweQueue(changeSet, maskQueue);
|
||||
}
|
||||
LocalSession session = fp.getSession();
|
||||
{ // Set mask etc
|
||||
Mask destMask = session.getMask();
|
||||
if (!Masks.isNull(destMask)) {
|
||||
new MaskTraverser(destMask).reset(changeQueue);
|
||||
changeQueue = new FaweQueueDelegateExtent(changeQueue, new MaskingExtent(changeQueue, destMask));
|
||||
}
|
||||
Mask sourceMask = session.getSourceMask();
|
||||
if (!Masks.isNull(sourceMask)) {
|
||||
new MaskTraverser(sourceMask).reset(changeQueue);
|
||||
changeQueue = new FaweQueueDelegateExtent(changeQueue, new SourceMaskExtent(changeQueue, sourceMask));
|
||||
}
|
||||
ResettableExtent transform = session.getTransform();
|
||||
if (transform != null) {
|
||||
transform.setExtent(changeQueue);
|
||||
changeQueue = new FaweQueueDelegateExtent(changeQueue, transform);
|
||||
}
|
||||
}
|
||||
|
||||
AsyncWorld world = getWorld();
|
||||
world.changeWorld(bukkitWorld, changeQueue);
|
||||
|
||||
AsyncBlock asyncBlock = null;
|
||||
if (clickedBlock != null) {
|
||||
asyncBlock = world.getBlockAt(clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ());
|
||||
}
|
||||
if (!getPlayer().hasPermission(sniperTool.getCurrentBrush().getPermissionNode())) {
|
||||
getPlayer().sendMessage("You are not allowed to use this brush. You're missing the permission node '" + sniperTool.getCurrentBrush().getPermissionNode() + "'");
|
||||
return true;
|
||||
}
|
||||
|
||||
final SnipeData snipeData = sniperTool.getSnipeData();
|
||||
if (getPlayer().isSneaking()) {
|
||||
AsyncBlock targetBlock;
|
||||
SnipeAction snipeAction = sniperTool.getActionAssigned(itemInHand);
|
||||
|
||||
switch (action) {
|
||||
case LEFT_CLICK_BLOCK:
|
||||
case LEFT_CLICK_AIR:
|
||||
if (asyncBlock != null) {
|
||||
targetBlock = asyncBlock;
|
||||
} else {
|
||||
RangeBlockHelper rangeBlockHelper = snipeData.isRanged() ? new RangeBlockHelper(getPlayer(), world, snipeData.getRange()) : new RangeBlockHelper(getPlayer(), world);
|
||||
targetBlock = snipeData.isRanged() ? rangeBlockHelper.getRangeBlock() : rangeBlockHelper.getTargetBlock();
|
||||
}
|
||||
|
||||
switch (snipeAction) {
|
||||
case ARROW:
|
||||
if (targetBlock != null) {
|
||||
int originalVoxel = snipeData.getVoxelId();
|
||||
snipeData.setVoxelId(targetBlock.getTypeId());
|
||||
// SniperMaterialChangedEvent event = new SniperMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((originalVoxel << BlockTypes.BIT_OFFSET) + snipeData.getPropertyId())), BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + snipeData.getPropertyId())));
|
||||
// callEvent(event);
|
||||
snipeData.getVoxelMessage().voxel();
|
||||
return true;
|
||||
} else {
|
||||
int originalVoxel = snipeData.getVoxelId();
|
||||
snipeData.setVoxelId(BlockTypes.AIR.getInternalId());
|
||||
// SniperMaterialChangedEvent event = new SniperMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((originalVoxel << BlockTypes.BIT_OFFSET) + snipeData.getPropertyId())), BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + snipeData.getPropertyId())));
|
||||
// callEvent(event);
|
||||
snipeData.getVoxelMessage().voxel();
|
||||
return true;
|
||||
}
|
||||
case GUNPOWDER:
|
||||
if (targetBlock != null) {
|
||||
int originalData = snipeData.getPropertyId();
|
||||
snipeData.setData(targetBlock.getPropertyId());
|
||||
// SniperMaterialChangedEvent event = new SniperMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + originalData)), BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + snipeData.getPropertyId())));
|
||||
// callEvent(event);
|
||||
snipeData.getVoxelMessage().data();
|
||||
return true;
|
||||
} else {
|
||||
int originalData = snipeData.getPropertyId();
|
||||
snipeData.setData(0);
|
||||
// SniperMaterialChangedEvent event = new SniperMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + originalData)), BukkitAdapter.adapt(BlockState.get(snipeData.getVoxelId() + snipeData.getPropertyId())));
|
||||
// callEvent(event);
|
||||
snipeData.getVoxelMessage().data();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RIGHT_CLICK_AIR:
|
||||
case RIGHT_CLICK_BLOCK:
|
||||
if (asyncBlock != null) {
|
||||
targetBlock = asyncBlock;
|
||||
} else {
|
||||
RangeBlockHelper rangeBlockHelper = snipeData.isRanged() ? new RangeBlockHelper(getPlayer(), world, snipeData.getRange()) : new RangeBlockHelper(getPlayer(), world);
|
||||
targetBlock = snipeData.isRanged() ? rangeBlockHelper.getRangeBlock() : rangeBlockHelper.getTargetBlock();
|
||||
}
|
||||
|
||||
switch (snipeAction) {
|
||||
case ARROW:
|
||||
if (targetBlock != null) {
|
||||
int originalId = snipeData.getReplaceId();
|
||||
snipeData.setReplaceId(targetBlock.getTypeId());
|
||||
// SniperReplaceMaterialChangedEvent event = new SniperReplaceMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((originalId << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData())), BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData())));
|
||||
// callEvent(event);
|
||||
snipeData.getVoxelMessage().replace();
|
||||
return true;
|
||||
} else {
|
||||
int originalId = snipeData.getReplaceId();
|
||||
snipeData.setReplaceId(BlockTypes.AIR.getInternalId());
|
||||
// SniperReplaceMaterialChangedEvent event = new SniperReplaceMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((originalId << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData())), BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData())));
|
||||
// callEvent(event);
|
||||
snipeData.getVoxelMessage().replace();
|
||||
return true;
|
||||
}
|
||||
case GUNPOWDER:
|
||||
if (targetBlock != null) {
|
||||
int originalData = snipeData.getReplaceData();
|
||||
snipeData.setReplaceData(targetBlock.getPropertyId());
|
||||
// SniperReplaceMaterialChangedEvent event = new SniperReplaceMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + originalData)), BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData())));
|
||||
// callEvent(event);
|
||||
snipeData.getVoxelMessage().replaceData();
|
||||
return true;
|
||||
} else {
|
||||
int originalData = snipeData.getReplaceData();
|
||||
snipeData.setReplaceData(BlockTypes.AIR.getInternalId());
|
||||
// SniperReplaceMaterialChangedEvent event = new SniperReplaceMaterialChangedEvent(this, toolId, BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + originalData)), BukkitAdapter.adapt(BlockState.get((snipeData.getReplaceId() << BlockTypes.BIT_OFFSET) + snipeData.getReplaceData())));
|
||||
// callEvent(event);
|
||||
snipeData.getVoxelMessage().replaceData();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
final AsyncBlock targetBlock;
|
||||
final AsyncBlock lastBlock;
|
||||
final SnipeAction snipeAction = sniperTool.getActionAssigned(itemInHand);
|
||||
|
||||
switch (action) {
|
||||
case RIGHT_CLICK_AIR:
|
||||
case RIGHT_CLICK_BLOCK:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (asyncBlock != null) {
|
||||
targetBlock = asyncBlock;
|
||||
lastBlock = asyncBlock.getRelative(clickedFace);
|
||||
if (lastBlock == null || targetBlock == null) {
|
||||
getPlayer().sendMessage(ChatColor.RED + "Snipe target block must be visible.");
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
RangeBlockHelper rangeBlockHelper = snipeData.isRanged() ? new RangeBlockHelper(getPlayer(), world, snipeData.getRange()) : new RangeBlockHelper(getPlayer(), world);
|
||||
targetBlock = snipeData.isRanged() ? rangeBlockHelper.getRangeBlock() : rangeBlockHelper.getTargetBlock();
|
||||
lastBlock = rangeBlockHelper.getLastBlock();
|
||||
|
||||
if (targetBlock == null || lastBlock == null) {
|
||||
getPlayer().sendMessage(ChatColor.RED + "Snipe target block must be visible.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
final IBrush brush = sniperTool.getCurrentBrush();
|
||||
|
||||
try {
|
||||
snipeData.setExtent(world);
|
||||
Request.reset();
|
||||
Request.request().setExtent(world);
|
||||
switch (brush.getClass().getSimpleName()) {
|
||||
case "JockeyBrush":
|
||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
brush.perform(snipeAction, snipeData, targetBlock, lastBlock);
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
if (sniperTool.getCurrentBrush() instanceof PerformBrush) {
|
||||
PerformBrush performerBrush = (PerformBrush) sniperTool.getCurrentBrush();
|
||||
performerBrush.initP(snipeData);
|
||||
}
|
||||
brush.perform(snipeAction, snipeData, targetBlock, lastBlock);
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
snipeData.setExtent(null);
|
||||
Request.reset();
|
||||
}
|
||||
if (Fawe.isMainThread()) {
|
||||
SetQueue.IMP.flush(changeQueue);
|
||||
} else {
|
||||
changeQueue.flush();
|
||||
}
|
||||
if (changeSet != null) {
|
||||
if (Settings.IMP.HISTORY.COMBINE_STAGES) {
|
||||
changeSet.closeAsync();
|
||||
} else {
|
||||
changeSet.close();
|
||||
}
|
||||
session.remember(changeSet.toEditSession(fp));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void callEvent(Event event) {
|
||||
if (Fawe.isMainThread()) {
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
} else {
|
||||
if (event.isAsynchronous()) {
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
} else {
|
||||
try {
|
||||
PluginManager plm = Bukkit.getPluginManager();
|
||||
Class<? extends PluginManager> clazz = plm.getClass();
|
||||
Method methodFireEvent = clazz.getDeclaredMethod("fireEvent", Event.class);
|
||||
methodFireEvent.setAccessible(true);
|
||||
methodFireEvent.invoke(plm, event);
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IBrush setBrush(String toolId, Class<? extends IBrush> brush) {
|
||||
if (!tools.containsKey(toolId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return tools.get(toolId).setCurrentBrush(brush);
|
||||
}
|
||||
|
||||
public IBrush getBrush(String toolId) {
|
||||
if (!tools.containsKey(toolId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return tools.get(toolId).getCurrentBrush();
|
||||
}
|
||||
|
||||
public IBrush previousBrush(String toolId) {
|
||||
if (!tools.containsKey(toolId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return tools.get(toolId).previousBrush();
|
||||
}
|
||||
|
||||
public boolean setTool(String toolId, SnipeAction action, Material itemInHand) {
|
||||
for (Map.Entry<String, SniperTool> entry : tools.entrySet()) {
|
||||
if (entry.getKey() != toolId && entry.getValue().hasToolAssigned(itemInHand)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tools.containsKey(toolId)) {
|
||||
SniperTool tool = new SniperTool(this);
|
||||
tools.put(toolId, tool);
|
||||
}
|
||||
tools.get(toolId).assignAction(action, itemInHand);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void removeTool(String toolId, Material itemInHand) {
|
||||
if (!tools.containsKey(toolId)) {
|
||||
SniperTool tool = new SniperTool(this);
|
||||
tools.put(toolId, tool);
|
||||
}
|
||||
tools.get(toolId).unassignAction(itemInHand);
|
||||
}
|
||||
|
||||
public void removeTool(String toolId) {
|
||||
if (toolId == null) {
|
||||
return;
|
||||
}
|
||||
tools.remove(toolId);
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public void undo() {
|
||||
undo(1);
|
||||
}
|
||||
|
||||
public void undo(int amount) {
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(getPlayer());
|
||||
if (!fp.runAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int count = 0;
|
||||
for (int i = 0; i < amount; i++) {
|
||||
EditSession es = fp.getSession().undo(null, fp.getPlayer());
|
||||
if (es == null) {
|
||||
break;
|
||||
} else {
|
||||
es.flushQueue();
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (count > 0) {
|
||||
BBC.COMMAND_UNDO_SUCCESS.send(fp);
|
||||
} else {
|
||||
BBC.COMMAND_UNDO_ERROR.send(fp);
|
||||
}
|
||||
}
|
||||
}, true, false));
|
||||
}
|
||||
|
||||
public void reset(String toolId) {
|
||||
SniperTool backup = tools.remove(toolId);
|
||||
SniperTool newTool = new SniperTool(this);
|
||||
|
||||
for (Map.Entry<SnipeAction, Material> entry : backup.getActionTools().entrySet()) {
|
||||
newTool.assignAction(entry.getKey(), entry.getValue());
|
||||
}
|
||||
tools.put(toolId, newTool);
|
||||
}
|
||||
|
||||
public SnipeData getSnipeData(String toolId) {
|
||||
return tools.containsKey(toolId) ? tools.get(toolId).getSnipeData() : null;
|
||||
}
|
||||
|
||||
public void displayInfo() {
|
||||
String currentToolId = getCurrentToolId();
|
||||
SniperTool sniperTool = tools.get(currentToolId);
|
||||
IBrush brush = sniperTool.getCurrentBrush();
|
||||
getPlayer().sendMessage("Current Tool: " + ((currentToolId != null) ? currentToolId : "Default Tool"));
|
||||
if (brush == null) {
|
||||
getPlayer().sendMessage("No brush selected.");
|
||||
return;
|
||||
}
|
||||
brush.info(sniperTool.getMessageHelper());
|
||||
if (brush instanceof Performer) {
|
||||
((Performer) brush).showInfo(sniperTool.getMessageHelper());
|
||||
}
|
||||
}
|
||||
|
||||
public SniperTool getSniperTool(String toolId) {
|
||||
return tools.get(toolId);
|
||||
}
|
||||
|
||||
public class SniperTool {
|
||||
private BiMap<SnipeAction, Material> actionTools = HashBiMap.create();
|
||||
private ClassToInstanceMap<IBrush> brushes = MutableClassToInstanceMap.create();
|
||||
private Class<? extends IBrush> currentBrush;
|
||||
private Class<? extends IBrush> previousBrush;
|
||||
private SnipeData snipeData;
|
||||
private Message messageHelper;
|
||||
|
||||
private SniperTool(Sniper owner) {
|
||||
this(SnipeBrush.class, new SnipeData(owner));
|
||||
}
|
||||
|
||||
private SniperTool(Class<? extends IBrush> currentBrush, SnipeData snipeData) {
|
||||
Preconditions.checkNotNull(currentBrush);
|
||||
Preconditions.checkNotNull(snipeData);
|
||||
this.snipeData = snipeData;
|
||||
messageHelper = new Message(snipeData);
|
||||
snipeData.setVoxelMessage(messageHelper);
|
||||
|
||||
IBrush newBrushInstance = instantiateBrush(currentBrush);
|
||||
if (snipeData.owner().getPlayer().hasPermission(newBrushInstance.getPermissionNode())) {
|
||||
brushes.put(currentBrush, newBrushInstance);
|
||||
this.currentBrush = currentBrush;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasToolAssigned(Material material) {
|
||||
return actionTools.containsValue(material);
|
||||
}
|
||||
|
||||
public SnipeAction getActionAssigned(Material itemInHand) {
|
||||
return actionTools.inverse().get(itemInHand);
|
||||
}
|
||||
|
||||
public Material getToolAssigned(SnipeAction action) {
|
||||
return actionTools.get(action);
|
||||
}
|
||||
|
||||
public void assignAction(SnipeAction action, Material itemInHand) {
|
||||
actionTools.forcePut(action, itemInHand);
|
||||
}
|
||||
|
||||
public void unassignAction(Material itemInHand) {
|
||||
actionTools.inverse().remove(itemInHand);
|
||||
}
|
||||
|
||||
public BiMap<SnipeAction, Material> getActionTools() {
|
||||
return ImmutableBiMap.copyOf(actionTools);
|
||||
}
|
||||
|
||||
public SnipeData getSnipeData() {
|
||||
return snipeData;
|
||||
}
|
||||
|
||||
public Message getMessageHelper() {
|
||||
return messageHelper;
|
||||
}
|
||||
|
||||
public IBrush getCurrentBrush() {
|
||||
if (currentBrush == null) {
|
||||
return null;
|
||||
}
|
||||
return brushes.getInstance(currentBrush);
|
||||
}
|
||||
|
||||
public IBrush setCurrentBrush(Class<? extends IBrush> brush) {
|
||||
Preconditions.checkNotNull(brush, "Can't set brush to null.");
|
||||
IBrush brushInstance = brushes.get(brush);
|
||||
if (brushInstance == null) {
|
||||
brushInstance = instantiateBrush(brush);
|
||||
Preconditions.checkNotNull(brushInstance, "Could not instanciate brush class.");
|
||||
if (snipeData.owner().getPlayer().hasPermission(brushInstance.getPermissionNode())) {
|
||||
brushes.put(brush, brushInstance);
|
||||
previousBrush = currentBrush;
|
||||
currentBrush = brush;
|
||||
return brushInstance;
|
||||
}
|
||||
}
|
||||
|
||||
if (snipeData.owner().getPlayer().hasPermission(brushInstance.getPermissionNode())) {
|
||||
previousBrush = currentBrush;
|
||||
currentBrush = brush;
|
||||
return brushInstance;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public IBrush previousBrush() {
|
||||
if (previousBrush == null) {
|
||||
return null;
|
||||
}
|
||||
return setCurrentBrush(previousBrush);
|
||||
}
|
||||
|
||||
private IBrush instantiateBrush(Class<? extends IBrush> brush) {
|
||||
try {
|
||||
return brush.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
return null;
|
||||
} catch (IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return Sniper.class;
|
||||
}
|
||||
}
|
30
favs/src/main/java/com/thevoxelbox/voxelsniper/SniperManager.java
Normale Datei
30
favs/src/main/java/com/thevoxelbox/voxelsniper/SniperManager.java
Normale Datei
@ -0,0 +1,30 @@
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SniperManager
|
||||
{
|
||||
private Map<UUID, Sniper> sniperInstances = Maps.newHashMap();
|
||||
private VoxelSniper plugin;
|
||||
|
||||
public SniperManager(VoxelSniper plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public Sniper getSniperForPlayer(Player player)
|
||||
{
|
||||
if (sniperInstances.get(player.getUniqueId()) == null)
|
||||
{
|
||||
sniperInstances.put(player.getUniqueId(), new Sniper(plugin, player));
|
||||
}
|
||||
return sniperInstances.get(player.getUniqueId());
|
||||
}
|
||||
}
|
70
favs/src/main/java/com/thevoxelbox/voxelsniper/Undo.java
Normale Datei
70
favs/src/main/java/com/thevoxelbox/voxelsniper/Undo.java
Normale Datei
@ -0,0 +1,70 @@
|
||||
/**
|
||||
This file is part of VoxelSniper, licensed under the MIT License (MIT).
|
||||
|
||||
Copyright (c) The VoxelBox <http://thevoxelbox.com>
|
||||
Copyright (c) contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* Holds {@link org.bukkit.block.BlockState}s that can be later on used to reset those block
|
||||
* locations back to the recorded states.
|
||||
*/
|
||||
public class Undo {
|
||||
|
||||
int size;
|
||||
private World world;
|
||||
|
||||
/**
|
||||
* Default constructor of a Undo container.
|
||||
*/
|
||||
public Undo() {}
|
||||
|
||||
/**
|
||||
* Get the number of blocks in the collection.
|
||||
*
|
||||
* @return size of the Undo collection
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Block to the collection.
|
||||
*
|
||||
* @param block Block to be added
|
||||
*/
|
||||
public void put(Block block) {
|
||||
size++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the blockstates of all recorded blocks back to the state when they
|
||||
* were inserted.
|
||||
*/
|
||||
public void undo() {
|
||||
|
||||
}
|
||||
}
|
227
favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniper.java
Normale Datei
227
favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniper.java
Normale Datei
@ -0,0 +1,227 @@
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.bukkit.BukkitCommand;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.util.Jars;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.thevoxelbox.voxelsniper.brush.*;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import com.thevoxelbox.voxelsniper.command.VoxelVoxelCommand;
|
||||
import com.thevoxelbox.voxelsniper.event.SniperBrushChangedEvent;
|
||||
import com.thevoxelbox.voxelsniper.event.SniperMaterialChangedEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Bukkit extension point.
|
||||
*/
|
||||
public class VoxelSniper extends JavaPlugin
|
||||
{
|
||||
private static VoxelSniper instance;
|
||||
private SniperManager sniperManager = new SniperManager(this);
|
||||
private final VoxelSniperListener voxelSniperListener = new VoxelSniperListener(this);
|
||||
private VoxelSniperConfiguration voxelSniperConfiguration;
|
||||
|
||||
/**
|
||||
* Returns {@link com.thevoxelbox.voxelsniper.Brushes} for current instance.
|
||||
*
|
||||
* @return Brush Manager for current instance.
|
||||
*/
|
||||
public Brushes getBrushManager()
|
||||
{
|
||||
return brushManager;
|
||||
}
|
||||
|
||||
private Brushes brushManager = new Brushes();
|
||||
|
||||
/**
|
||||
* @return {@link VoxelSniper}
|
||||
*/
|
||||
public static VoxelSniper getInstance()
|
||||
{
|
||||
return VoxelSniper.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns object for accessing global VoxelSniper options.
|
||||
*
|
||||
* @return {@link VoxelSniperConfiguration} object for accessing global VoxelSniper options.
|
||||
*/
|
||||
public VoxelSniperConfiguration getVoxelSniperConfiguration()
|
||||
{
|
||||
return voxelSniperConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link com.thevoxelbox.voxelsniper.SniperManager} for current instance.
|
||||
*
|
||||
* @return SniperManager
|
||||
*/
|
||||
public SniperManager getSniperManager()
|
||||
{
|
||||
return sniperManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args)
|
||||
{
|
||||
if (sender instanceof Player)
|
||||
{
|
||||
String[] arguments = args;
|
||||
|
||||
if (arguments == null)
|
||||
{
|
||||
arguments = new String[0];
|
||||
}
|
||||
|
||||
return voxelSniperListener.onCommand((Player) sender, arguments, command.getName());
|
||||
}
|
||||
|
||||
getLogger().info("Only Players can execute commands.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
VoxelSniper.instance = this;
|
||||
|
||||
registerBrushes();
|
||||
getLogger().info("Registered " + brushManager.registeredSniperBrushes() + " Sniper Brushes with " + brushManager.registeredSniperBrushHandles() + " handles.");
|
||||
|
||||
saveDefaultConfig();
|
||||
voxelSniperConfiguration = new VoxelSniperConfiguration(getConfig());
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(this.voxelSniperListener, this);
|
||||
getLogger().info("Registered Sniper Listener.");
|
||||
|
||||
try {
|
||||
setupCommand("/p", new FaweCommand("voxelsniper.sniper") {
|
||||
@Override
|
||||
public boolean execute(FawePlayer fp, String... args) {
|
||||
Player player = (Player) fp.parent;
|
||||
return (Bukkit.getPluginManager().getPlugin("VoxelSniper")).onCommand(player, new Command("p") {
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
|
||||
return false;
|
||||
}
|
||||
}, null, args);
|
||||
|
||||
}
|
||||
});
|
||||
setupCommand("/d", new FaweCommand("voxelsniper.sniper") {
|
||||
@Override
|
||||
public boolean execute(FawePlayer fp, String... args) {
|
||||
Player player = (Player) fp.parent;
|
||||
return (Bukkit.getPluginManager().getPlugin("VoxelSniper")).onCommand(player, new Command("d") {
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
|
||||
return false;
|
||||
}
|
||||
}, null, args);
|
||||
|
||||
}
|
||||
});
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all brushes.
|
||||
*/
|
||||
public void registerBrushes()
|
||||
{
|
||||
brushManager.registerSniperBrush(BallBrush.class, "b", "ball");
|
||||
brushManager.registerSniperBrush(BiomeBrush.class, "bio", "biome");
|
||||
brushManager.registerSniperBrush(BlendBallBrush.class, "bb", "blendball");
|
||||
brushManager.registerSniperBrush(BlendDiscBrush.class, "bd", "blenddisc");
|
||||
brushManager.registerSniperBrush(BlendVoxelBrush.class, "bv", "blendvoxel");
|
||||
brushManager.registerSniperBrush(BlendVoxelDiscBrush.class, "bvd", "blendvoxeldisc");
|
||||
brushManager.registerSniperBrush(BlobBrush.class, "blob", "splatblob");
|
||||
brushManager.registerSniperBrush(BlockResetBrush.class, "brb", "blockresetbrush");
|
||||
brushManager.registerSniperBrush(BlockResetSurfaceBrush.class, "brbs", "blockresetbrushsurface");
|
||||
brushManager.registerSniperBrush(CanyonBrush.class, "ca", "canyon");
|
||||
brushManager.registerSniperBrush(CanyonSelectionBrush.class, "cas", "canyonselection");
|
||||
brushManager.registerSniperBrush(CheckerVoxelDiscBrush.class, "cvd", "checkervoxeldisc");
|
||||
brushManager.registerSniperBrush(CleanSnowBrush.class, "cls", "cleansnow");
|
||||
brushManager.registerSniperBrush(CloneStampBrush.class, "cs", "clonestamp");
|
||||
brushManager.registerSniperBrush(CometBrush.class, "com", "comet");
|
||||
brushManager.registerSniperBrush(CopyPastaBrush.class, "cp", "copypasta");
|
||||
brushManager.registerSniperBrush(CylinderBrush.class, "c", "cylinder");
|
||||
brushManager.registerSniperBrush(DiscBrush.class, "d", "disc");
|
||||
brushManager.registerSniperBrush(DiscFaceBrush.class, "df", "discface");
|
||||
brushManager.registerSniperBrush(DomeBrush.class, "dome", "domebrush");
|
||||
brushManager.registerSniperBrush(DrainBrush.class, "drain");
|
||||
brushManager.registerSniperBrush(EllipseBrush.class, "el", "ellipse");
|
||||
brushManager.registerSniperBrush(EllipsoidBrush.class, "elo", "ellipsoid");
|
||||
brushManager.registerSniperBrush(EntityBrush.class, "en", "entity");
|
||||
brushManager.registerSniperBrush(EntityRemovalBrush.class, "er", "entityremoval");
|
||||
brushManager.registerSniperBrush(EraserBrush.class, "erase", "eraser");
|
||||
brushManager.registerSniperBrush(ErodeBrush.class, "e", "erode");
|
||||
brushManager.registerSniperBrush(ExtrudeBrush.class, "ex", "extrude");
|
||||
brushManager.registerSniperBrush(FillDownBrush.class, "fd", "filldown");
|
||||
brushManager.registerSniperBrush(FlatOceanBrush.class, "fo", "flatocean");
|
||||
brushManager.registerSniperBrush(GenerateTreeBrush.class, "gt", "generatetree");
|
||||
brushManager.registerSniperBrush(HeatRayBrush.class, "hr", "heatray");
|
||||
brushManager.registerSniperBrush(JaggedLineBrush.class, "j", "jagged");
|
||||
brushManager.registerSniperBrush(JockeyBrush.class, "jockey");
|
||||
brushManager.registerSniperBrush(LightningBrush.class, "light", "lightning");
|
||||
brushManager.registerSniperBrush(LineBrush.class, "l", "line");
|
||||
brushManager.registerSniperBrush(MoveBrush.class, "mv", "move");
|
||||
brushManager.registerSniperBrush(OceanBrush.class, "o", "ocean");
|
||||
brushManager.registerSniperBrush(OverlayBrush.class, "over", "overlay");
|
||||
brushManager.registerSniperBrush(PaintingBrush.class, "paint", "painting");
|
||||
brushManager.registerSniperBrush(PullBrush.class, "pull");
|
||||
brushManager.registerSniperBrush(PunishBrush.class, "p", "punish");
|
||||
brushManager.registerSniperBrush(RandomErodeBrush.class, "re", "randomerode");
|
||||
brushManager.registerSniperBrush(RegenerateChunkBrush.class, "gc", "generatechunk");
|
||||
brushManager.registerSniperBrush(RingBrush.class, "ri", "ring");
|
||||
brushManager.registerSniperBrush(Rot2DBrush.class, "rot2", "rotation2d");
|
||||
brushManager.registerSniperBrush(Rot2DvertBrush.class, "rot2v", "rotation2dvertical");
|
||||
brushManager.registerSniperBrush(Rot3DBrush.class, "rot3", "rotation3d");
|
||||
brushManager.registerSniperBrush(RulerBrush.class, "r", "ruler");
|
||||
brushManager.registerSniperBrush(ScannerBrush.class, "sc", "scanner");
|
||||
brushManager.registerSniperBrush(SetBrush.class, "set");
|
||||
brushManager.registerSniperBrush(SetRedstoneFlipBrush.class, "setrf", "setredstoneflip");
|
||||
brushManager.registerSniperBrush(ShellBallBrush.class, "shb", "shellball");
|
||||
brushManager.registerSniperBrush(ShellSetBrush.class, "shs", "shellset");
|
||||
brushManager.registerSniperBrush(ShellVoxelBrush.class, "shv", "shellvoxel");
|
||||
brushManager.registerSniperBrush(SignOverwriteBrush.class, "sio", "signoverwriter");
|
||||
brushManager.registerSniperBrush(SnipeBrush.class, "s", "snipe");
|
||||
brushManager.registerSniperBrush(SnowConeBrush.class, "snow", "snowcone");
|
||||
brushManager.registerSniperBrush(SpiralStaircaseBrush.class, "sstair", "spiralstaircase");
|
||||
brushManager.registerSniperBrush(SplatterBallBrush.class, "sb", "splatball");
|
||||
brushManager.registerSniperBrush(SplatterDiscBrush.class, "sd", "splatdisc");
|
||||
brushManager.registerSniperBrush(SplatterOverlayBrush.class, "sover", "splatteroverlay");
|
||||
brushManager.registerSniperBrush(SplatterVoxelBrush.class, "sv", "splattervoxel");
|
||||
brushManager.registerSniperBrush(SplatterDiscBrush.class, "svd", "splatvoxeldisc");
|
||||
brushManager.registerSniperBrush(SplineBrush.class, "sp", "spline");
|
||||
brushManager.registerSniperBrush(StencilBrush.class, "st", "stencil");
|
||||
brushManager.registerSniperBrush(StencilListBrush.class, "sl", "stencillist");
|
||||
brushManager.registerSniperBrush(ThreePointCircleBrush.class, "tpc", "threepointcircle");
|
||||
brushManager.registerSniperBrush(TreeSnipeBrush.class, "t", "tree", "treesnipe");
|
||||
brushManager.registerSniperBrush(TriangleBrush.class, "tri", "triangle");
|
||||
brushManager.registerSniperBrush(UnderlayBrush.class, "under", "underlay");
|
||||
brushManager.registerSniperBrush(VoltMeterBrush.class, "volt", "voltmeter");
|
||||
brushManager.registerSniperBrush(VoxelBrush.class, "v", "voxel");
|
||||
brushManager.registerSniperBrush(VoxelDiscBrush.class, "vd", "voxeldisc");
|
||||
brushManager.registerSniperBrush(VoxelDiscFaceBrush.class, "vdf", "voxeldiscface");
|
||||
brushManager.registerSniperBrush(WarpBrush.class, "w", "warp");
|
||||
}
|
||||
|
||||
public void setupCommand(final String label, final FaweCommand cmd) {
|
||||
this.getCommand(label).setExecutor(new BukkitCommand(cmd));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Configuration storage defining global configurations for VoxelSniper.
|
||||
*/
|
||||
public class VoxelSniperConfiguration
|
||||
{
|
||||
public static final String CONFIG_IDENTIFIER_LITESNIPER_MAX_BRUSH_SIZE = "litesniper-max-brush-size";
|
||||
public static final String CONFIG_IDENTIFIER_UNDO_CACHE_SIZE = "undo-cache-size";
|
||||
public static final String CONFIG_IDENTIFIER_LITESNIPER_RESTRICTED_ITEMS = "litesniper-restricted-items";
|
||||
public static final String CONFIG_IDENTIFIER_MESSAGE_ON_LOGIN_ENABLED = "message-on-login-enabled";
|
||||
public static final int DEFAULT_LITESNIPER_MAX_BRUSH_SIZE = 5;
|
||||
public static final int DEFAULT_UNDO_CACHE_SIZE = 20;
|
||||
public static final boolean DEFAULT_MESSAGE_ON_LOGIN_ENABLED = true;
|
||||
private FileConfiguration configuration;
|
||||
|
||||
/**
|
||||
* @param configuration Configuration that is going to be used.
|
||||
*/
|
||||
public VoxelSniperConfiguration(FileConfiguration configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum amount of snipes stored in the undo cache of snipers.
|
||||
*
|
||||
* @return the maximum amount of snipes stored in the undo cache of snipers
|
||||
*/
|
||||
public int getUndoCacheSize()
|
||||
{
|
||||
return configuration.getInt(CONFIG_IDENTIFIER_UNDO_CACHE_SIZE, DEFAULT_UNDO_CACHE_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum amount of snipes stored in the undo cache of snipers.
|
||||
*
|
||||
* @param size size of undo cache
|
||||
*/
|
||||
public void setUndoCacheSize(int size)
|
||||
{
|
||||
configuration.set(CONFIG_IDENTIFIER_UNDO_CACHE_SIZE, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns maximum size of brushes that LiteSnipers can use.
|
||||
*
|
||||
* @return maximum size
|
||||
*/
|
||||
public int getLiteSniperMaxBrushSize()
|
||||
{
|
||||
return configuration.getInt(CONFIG_IDENTIFIER_LITESNIPER_MAX_BRUSH_SIZE, DEFAULT_LITESNIPER_MAX_BRUSH_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set maximum size of brushes that LiteSnipers can use.
|
||||
*
|
||||
* @param size maximum size
|
||||
*/
|
||||
public void setLiteSniperMaxBrushSize(int size)
|
||||
{
|
||||
configuration.set(CONFIG_IDENTIFIER_LITESNIPER_MAX_BRUSH_SIZE, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns List of restricted Litesniper Items.
|
||||
*
|
||||
* @return List of restricted Litesniper Items
|
||||
*/
|
||||
public List<Integer> getLiteSniperRestrictedItems()
|
||||
{
|
||||
return configuration.getIntegerList(CONFIG_IDENTIFIER_LITESNIPER_RESTRICTED_ITEMS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new list of restricted Litesniper Items.
|
||||
*
|
||||
* @param restrictedItems List of restricted Litesniper Items
|
||||
*/
|
||||
public void setLitesniperRestrictedItems(List<Integer> restrictedItems)
|
||||
{
|
||||
Preconditions.checkNotNull(restrictedItems, "Restricted items must be a list.");
|
||||
configuration.set(CONFIG_IDENTIFIER_LITESNIPER_RESTRICTED_ITEMS, restrictedItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the login message is enabled.
|
||||
*
|
||||
* @return true if message on login is enabled, false otherwise.
|
||||
*/
|
||||
public boolean isMessageOnLoginEnabled()
|
||||
{
|
||||
return configuration.getBoolean(CONFIG_IDENTIFIER_MESSAGE_ON_LOGIN_ENABLED, DEFAULT_MESSAGE_ON_LOGIN_ENABLED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the message on login to be enabled or disabled.
|
||||
*
|
||||
* @param enabled Message on Login enabled
|
||||
*/
|
||||
public void setMessageOnLoginEnabled(boolean enabled)
|
||||
{
|
||||
configuration.set(CONFIG_IDENTIFIER_MESSAGE_ON_LOGIN_ENABLED, enabled);
|
||||
}
|
||||
}
|
138
favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniperListener.java
Normale Datei
138
favs/src/main/java/com/thevoxelbox/voxelsniper/VoxelSniperListener.java
Normale Datei
@ -0,0 +1,138 @@
|
||||
package com.thevoxelbox.voxelsniper;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.api.command.VoxelCommand;
|
||||
import com.thevoxelbox.voxelsniper.command.*;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Voxel
|
||||
*/
|
||||
public class VoxelSniperListener implements Listener
|
||||
{
|
||||
|
||||
private static final String SNIPER_PERMISSION = "voxelsniper.sniper";
|
||||
private final VoxelSniper plugin;
|
||||
private Map<String, VoxelCommand> commands = new HashMap<String, VoxelCommand>();
|
||||
|
||||
/**
|
||||
* @param plugin
|
||||
*/
|
||||
public VoxelSniperListener(final VoxelSniper plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
addCommand(new VoxelBrushCommand(plugin));
|
||||
addCommand(new VoxelBrushToolCommand(plugin));
|
||||
addCommand(new VoxelCenterCommand(plugin));
|
||||
addCommand(new VoxelChunkCommand(plugin));
|
||||
addCommand(new VoxelDefaultCommand(plugin));
|
||||
addCommand(new VoxelGoToCommand(plugin));
|
||||
addCommand(new VoxelHeightCommand(plugin));
|
||||
addCommand(new VoxelInkCommand(plugin));
|
||||
addCommand(new VoxelInkReplaceCommand(plugin));
|
||||
addCommand(new VoxelListCommand(plugin));
|
||||
addCommand(new VoxelPaintCommand(plugin));
|
||||
addCommand(new VoxelPerformerCommand(plugin));
|
||||
addCommand(new VoxelReplaceCommand(plugin));
|
||||
addCommand(new VoxelSniperCommand(plugin));
|
||||
addCommand(new VoxelUndoCommand(plugin));
|
||||
addCommand(new VoxelUndoUserCommand(plugin));
|
||||
addCommand(new VoxelVoxelCommand(plugin));
|
||||
}
|
||||
|
||||
private void addCommand(final VoxelCommand command)
|
||||
{
|
||||
this.commands.put(command.getIdentifier().toLowerCase(), command);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player
|
||||
* @param split
|
||||
* @param command
|
||||
* @return boolean Success.
|
||||
*/
|
||||
public boolean onCommand(final Player player, final String[] split, final String command)
|
||||
{
|
||||
VoxelCommand found = this.commands.get(command.toLowerCase());
|
||||
if (found == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasPermission(found, player))
|
||||
{
|
||||
player.sendMessage(ChatColor.RED + "Insufficient Permissions.");
|
||||
return true;
|
||||
}
|
||||
|
||||
return found.onCommand(player, split);
|
||||
}
|
||||
|
||||
private boolean hasPermission(final VoxelCommand command, final Player player)
|
||||
{
|
||||
if (command == null || player == null)
|
||||
{
|
||||
// Just a usual check for nulls
|
||||
return false;
|
||||
}
|
||||
else if (command.getPermission() == null || command.getPermission().isEmpty())
|
||||
{
|
||||
// This is for commands that do not require a permission node to be executed
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Should utilize Vault for permission checks if available
|
||||
return player.hasPermission(command.getPermission());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param event
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = false)
|
||||
public final void onPlayerInteract(final PlayerInteractEvent event)
|
||||
{
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (!player.hasPermission(SNIPER_PERMISSION))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player);
|
||||
if (sniper.isEnabled() && sniper.snipe(event.getAction(), event.getMaterial(), event.getClickedBlock(), event.getBlockFace()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
catch (final Throwable ignored)
|
||||
{
|
||||
ignored.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param event
|
||||
*/
|
||||
@EventHandler
|
||||
public final void onPlayerJoin(final PlayerJoinEvent event)
|
||||
{
|
||||
Player player = event.getPlayer();
|
||||
Sniper sniper = plugin.getSniperManager().getSniperForPlayer(player);
|
||||
|
||||
if (player.hasPermission(SNIPER_PERMISSION) && plugin.getVoxelSniperConfiguration().isMessageOnLoginEnabled())
|
||||
{
|
||||
sniper.displayInfo();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package com.thevoxelbox.voxelsniper.api.command;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.VoxelSniper;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public abstract class VoxelCommand
|
||||
{
|
||||
|
||||
private final String name;
|
||||
private String description = "";
|
||||
private String permission = "";
|
||||
private String identifier = "";
|
||||
protected final VoxelSniper plugin;
|
||||
|
||||
public VoxelCommand(String name, final VoxelSniper plugin)
|
||||
{
|
||||
this.name = name;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public abstract boolean onCommand(final Player player, final String[] args);
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getPermission()
|
||||
{
|
||||
return this.permission;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setDescription(String description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void setPermission(String permission)
|
||||
{
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
public String getIdentifier()
|
||||
{
|
||||
return this.identifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(String identifier)
|
||||
{
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public boolean isIdentifier(String offered)
|
||||
{
|
||||
return this.identifier.isEmpty() || this.identifier.equalsIgnoreCase(offered);
|
||||
}
|
||||
|
||||
/**
|
||||
* Padds an empty String to the front of the array.
|
||||
*
|
||||
* @param args Array to pad empty string in front of
|
||||
* @return padded array
|
||||
*/
|
||||
protected String[] hackTheArray(String[] args)
|
||||
{
|
||||
String[] returnValue = new String[args.length + 1];
|
||||
returnValue[0] = "";
|
||||
for (int i = 0, argsLength = args.length; i < argsLength; i++)
|
||||
{
|
||||
String arg = args[i];
|
||||
returnValue[i + 1] = arg;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
}
|
146
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BallBrush.java
Normale Datei
146
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BallBrush.java
Normale Datei
@ -0,0 +1,146 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* A brush that creates a solid ball.
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Ball_Brush
|
||||
*
|
||||
* @author Piotr
|
||||
*/
|
||||
public class BallBrush extends PerformBrush
|
||||
{
|
||||
public static final double TRUE_CIRCLE_ON_VALUE = 0.5;
|
||||
public static final int TRUE_CIRCLE_OFF_VALUE = 0;
|
||||
private double trueCircle = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BallBrush()
|
||||
{
|
||||
this.setName("Ball");
|
||||
}
|
||||
|
||||
private void ball(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
|
||||
int blockPositionX = targetBlock.getX();
|
||||
int blockPositionY = targetBlock.getY();
|
||||
int blockPositionZ = targetBlock.getZ();
|
||||
this.current.perform(targetBlock);
|
||||
|
||||
for (int z = 1; z <= brushSize; z++)
|
||||
{
|
||||
final double zSquared = Math.pow(z, 2);
|
||||
|
||||
this.current.perform(this.clampY(blockPositionX + z, blockPositionY, blockPositionZ));
|
||||
this.current.perform(this.clampY(blockPositionX - z, blockPositionY, blockPositionZ));
|
||||
this.current.perform(this.clampY(blockPositionX, blockPositionY + z, blockPositionZ));
|
||||
this.current.perform(this.clampY(blockPositionX, blockPositionY - z, blockPositionZ));
|
||||
this.current.perform(this.clampY(blockPositionX, blockPositionY, blockPositionZ + z));
|
||||
this.current.perform(this.clampY(blockPositionX, blockPositionY, blockPositionZ - z));
|
||||
|
||||
for (int x = 1; x <= brushSize; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
|
||||
if (zSquared + xSquared <= brushSizeSquared)
|
||||
{
|
||||
this.current.perform(this.clampY(blockPositionX + z, blockPositionY, blockPositionZ + x));
|
||||
this.current.perform(this.clampY(blockPositionX + z, blockPositionY, blockPositionZ - x));
|
||||
this.current.perform(this.clampY(blockPositionX - z, blockPositionY, blockPositionZ + x));
|
||||
this.current.perform(this.clampY(blockPositionX - z, blockPositionY, blockPositionZ - x));
|
||||
this.current.perform(this.clampY(blockPositionX + z, blockPositionY + x, blockPositionZ));
|
||||
this.current.perform(this.clampY(blockPositionX + z, blockPositionY - x, blockPositionZ));
|
||||
this.current.perform(this.clampY(blockPositionX - z, blockPositionY + x, blockPositionZ));
|
||||
this.current.perform(this.clampY(blockPositionX - z, blockPositionY - x, blockPositionZ));
|
||||
this.current.perform(this.clampY(blockPositionX, blockPositionY + z, blockPositionZ + x));
|
||||
this.current.perform(this.clampY(blockPositionX, blockPositionY + z, blockPositionZ - x));
|
||||
this.current.perform(this.clampY(blockPositionX, blockPositionY - z, blockPositionZ + x));
|
||||
this.current.perform(this.clampY(blockPositionX, blockPositionY - z, blockPositionZ - x));
|
||||
}
|
||||
|
||||
for (int y = 1; y <= brushSize; y++)
|
||||
{
|
||||
if ((xSquared + Math.pow(y, 2) + zSquared) <= brushSizeSquared)
|
||||
{
|
||||
this.current.perform(this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ + z));
|
||||
this.current.perform(this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ - z));
|
||||
this.current.perform(this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ + z));
|
||||
this.current.perform(this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ - z));
|
||||
this.current.perform(this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ + z));
|
||||
this.current.perform(this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ - z));
|
||||
this.current.perform(this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ + z));
|
||||
this.current.perform(this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ - z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.ball(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.ball(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Ball Brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b b true -- will use a true sphere algorithm instead of the skinnier version with classic sniper nubs. /b b false will switch back. (false is default)");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("true"))
|
||||
{
|
||||
this.trueCircle = TRUE_CIRCLE_ON_VALUE;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode ON.");
|
||||
}
|
||||
else if (parameter.startsWith("false"))
|
||||
{
|
||||
this.trueCircle = TRUE_CIRCLE_OFF_VALUE;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode OFF.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.ball";
|
||||
}
|
||||
}
|
126
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BiomeBrush.java
Normale Datei
126
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BiomeBrush.java
Normale Datei
@ -0,0 +1,126 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class BiomeBrush extends Brush
|
||||
{
|
||||
private Biome selectedBiome = Biome.PLAINS;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BiomeBrush()
|
||||
{
|
||||
this.setName("Biome (/b biome [Biome Name])");
|
||||
}
|
||||
|
||||
private void biome(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize, 2);
|
||||
|
||||
for (int x = -brushSize; x <= brushSize; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
|
||||
for (int z = -brushSize; z <= brushSize; z++)
|
||||
{
|
||||
if ((xSquared + Math.pow(z, 2)) <= brushSizeSquared)
|
||||
{
|
||||
this.getWorld().setBiome(this.getTargetBlock().getX() + x, this.getTargetBlock().getZ() + z, this.selectedBiome);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Block block1 = this.getWorld().getBlockAt(this.getTargetBlock().getX() - brushSize, 0, this.getTargetBlock().getZ() - brushSize);
|
||||
final Block block2 = this.getWorld().getBlockAt(this.getTargetBlock().getX() + brushSize, 0, this.getTargetBlock().getZ() + brushSize);
|
||||
|
||||
final int lowChunkX = (block1.getX() <= block2.getX()) ? block1.getChunk().getX() : block2.getChunk().getX();
|
||||
final int lowChunkZ = (block1.getZ() <= block2.getZ()) ? block1.getChunk().getZ() : block2.getChunk().getZ();
|
||||
final int highChunkX = (block1.getX() >= block2.getX()) ? block1.getChunk().getX() : block2.getChunk().getX();
|
||||
final int highChunkZ = (block1.getZ() >= block2.getZ()) ? block1.getChunk().getZ() : block2.getChunk().getZ();
|
||||
|
||||
for (int x = lowChunkX; x <= highChunkX; x++)
|
||||
{
|
||||
for (int z = lowChunkZ; z <= highChunkZ; z++)
|
||||
{
|
||||
this.getWorld().refreshChunk(x, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.biome(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.biome(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.custom(ChatColor.GOLD + "Currently selected biome type: " + ChatColor.DARK_GREEN + this.selectedBiome.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] args, final SnipeData v)
|
||||
{
|
||||
if (args[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Biome Brush Parameters:");
|
||||
String availableBiomes = "";
|
||||
|
||||
for (final Biome biome : Biome.values())
|
||||
{
|
||||
if (availableBiomes.isEmpty())
|
||||
{
|
||||
availableBiomes = ChatColor.DARK_GREEN + biome.name();
|
||||
continue;
|
||||
}
|
||||
|
||||
availableBiomes += ChatColor.RED + ", " + ChatColor.DARK_GREEN + biome.name();
|
||||
|
||||
}
|
||||
v.sendMessage(ChatColor.DARK_BLUE + "Available biomes: " + availableBiomes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// allows biome names with spaces in their name
|
||||
String biomeName = args[1];
|
||||
for (int i = 2; i < args.length; i++)
|
||||
{
|
||||
biomeName += " " + args[i];
|
||||
}
|
||||
|
||||
for (final Biome biome : Biome.values())
|
||||
{
|
||||
if (biome.name().equalsIgnoreCase(biomeName))
|
||||
{
|
||||
this.selectedBiome = biome;
|
||||
break;
|
||||
}
|
||||
}
|
||||
v.sendMessage(ChatColor.GOLD + "Currently selected biome type: " + ChatColor.DARK_GREEN + this.selectedBiome.name());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.biome";
|
||||
}
|
||||
}
|
162
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendBallBrush.java
Normale Datei
162
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendBallBrush.java
Normale Datei
@ -0,0 +1,162 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes
|
||||
*/
|
||||
public class BlendBallBrush extends BlendBrushBase
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BlendBallBrush()
|
||||
{
|
||||
this.setName("Blend Ball");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected final void blend(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final int brushSizeDoubled = 2 * brushSize;
|
||||
// Array that holds the original materials plus a buffer
|
||||
final int[][][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1];
|
||||
// Array that holds the blended materials
|
||||
final int[][][] newMaterials = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1];
|
||||
|
||||
// Log current materials into oldmats
|
||||
for (int x = 0; x <= 2 * (brushSize + 1); x++)
|
||||
{
|
||||
for (int y = 0; y <= 2 * (brushSize + 1); y++)
|
||||
{
|
||||
for (int z = 0; z <= 2 * (brushSize + 1); z++)
|
||||
{
|
||||
oldMaterials[x][y][z] = this.getBlockIdAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY() - brushSize - 1 + y, this.getTargetBlock().getZ() - brushSize - 1 + z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log current materials into newmats
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int y = 0; y <= brushSizeDoubled; y++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
newMaterials[x][y][z] = oldMaterials[x + 1][y + 1][z + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blend materials
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int y = 0; y <= brushSizeDoubled; y++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
final int[] materialFrequency = new int[BlockTypes.size()]; // Array that tracks frequency of materials neighboring given block
|
||||
int modeMatCount = 0;
|
||||
int modeMatId = 0;
|
||||
boolean tiecheck = true;
|
||||
|
||||
for (int m = -1; m <= 1; m++)
|
||||
{
|
||||
for (int n = -1; n <= 1; n++)
|
||||
{
|
||||
for (int o = -1; o <= 1; o++)
|
||||
{
|
||||
if (!(m == 0 && n == 0 && o == 0))
|
||||
{
|
||||
materialFrequency[oldMaterials[x + 1 + m][y + 1 + n][z + 1 + o]]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find most common neighboring material.
|
||||
for (BlockTypes type : BlockTypes.values)
|
||||
{
|
||||
int i = type.getInternalId();
|
||||
if (materialFrequency[i] > modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER)))
|
||||
{
|
||||
modeMatCount = materialFrequency[i];
|
||||
modeMatId = i;
|
||||
}
|
||||
}
|
||||
// Make sure there'world not a tie for most common
|
||||
for (int i = 0; i < modeMatId; i++)
|
||||
{
|
||||
BlockTypes type = BlockTypes.get(i);
|
||||
if (materialFrequency[i] == modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER)))
|
||||
{
|
||||
tiecheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Record most common neighbor material for this block
|
||||
if (tiecheck)
|
||||
{
|
||||
newMaterials[x][y][z] = modeMatId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Undo undo = new Undo();
|
||||
final double rSquared = Math.pow(brushSize + 1, 2);
|
||||
|
||||
// Make the changes
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x - brushSize - 1, 2);
|
||||
|
||||
for (int y = 0; y <= brushSizeDoubled; y++)
|
||||
{
|
||||
final double ySquared = Math.pow(y - brushSize - 1, 2);
|
||||
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
if (xSquared + ySquared + Math.pow(z - brushSize - 1, 2) <= rSquared)
|
||||
{
|
||||
if (!(this.excludeAir && BlockTypes.get(newMaterials[x][y][z]).getMaterial().isAir()) && !(this.excludeWater && (newMaterials[x][y][z] == BlockTypes.WATER.getInternalId())))
|
||||
{
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, this.getTargetBlock().getZ() - brushSize + z) != newMaterials[x][y][z])
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, this.getTargetBlock().getZ() - brushSize + z));
|
||||
}
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() - brushSize + z, this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, newMaterials[x][y][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Blend Ball Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b bb water -- toggle include or exclude (default: exclude) water");
|
||||
return;
|
||||
}
|
||||
|
||||
super.parameters(par, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.blendball";
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.bekvon.bukkit.residence.commands.material;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* @author Monofraps
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public abstract class BlendBrushBase extends Brush
|
||||
{
|
||||
protected boolean excludeAir = true;
|
||||
protected boolean excludeWater = true;
|
||||
|
||||
/**
|
||||
* @param v
|
||||
*/
|
||||
protected abstract void blend(final SnipeData v);
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.excludeAir = false;
|
||||
this.blend(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.excludeAir = true;
|
||||
this.blend(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.voxel();
|
||||
vm.custom(ChatColor.BLUE + "Water Mode: " + (this.excludeWater ? "exclude" : "include"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; ++i)
|
||||
{
|
||||
if (par[i].equalsIgnoreCase("water"))
|
||||
{
|
||||
this.excludeWater = !this.excludeWater;
|
||||
v.sendMessage(ChatColor.AQUA + "Water Mode: " + (this.excludeWater ? "exclude" : "include"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
protected final boolean isExcludeAir()
|
||||
{
|
||||
return excludeAir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param excludeAir
|
||||
*/
|
||||
protected final void setExcludeAir(boolean excludeAir)
|
||||
{
|
||||
this.excludeAir = excludeAir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
protected final boolean isExcludeWater()
|
||||
{
|
||||
return excludeWater;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param excludeWater
|
||||
*/
|
||||
protected final void setExcludeWater(boolean excludeWater)
|
||||
{
|
||||
this.excludeWater = excludeWater;
|
||||
}
|
||||
}
|
143
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendDiscBrush.java
Normale Datei
143
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlendDiscBrush.java
Normale Datei
@ -0,0 +1,143 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes
|
||||
*/
|
||||
public class BlendDiscBrush extends BlendBrushBase
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BlendDiscBrush()
|
||||
{
|
||||
this.setName("Blend Disc");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected final void blend(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final int brushSizeDoubled = 2 * brushSize;
|
||||
final int[][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer
|
||||
final int[][] newMaterials = new int[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Array that holds the blended materials
|
||||
|
||||
// Log current materials into oldmats
|
||||
for (int x = 0; x <= 2 * (brushSize + 1); x++)
|
||||
{
|
||||
for (int z = 0; z <= 2 * (brushSize + 1); z++)
|
||||
{
|
||||
oldMaterials[x][z] = this.getBlockIdAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize - 1 + z);
|
||||
}
|
||||
}
|
||||
|
||||
// Log current materials into newmats
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
newMaterials[x][z] = oldMaterials[x + 1][z + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Blend materials
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
final int[] materialFrequency = new int[BlockTypes.size()]; // Array that tracks frequency of materials neighboring given block
|
||||
int modeMatCount = 0;
|
||||
int modeMatId = 0;
|
||||
boolean tiecheck = true;
|
||||
|
||||
for (int m = -1; m <= 1; m++)
|
||||
{
|
||||
for (int n = -1; n <= 1; n++)
|
||||
{
|
||||
if (!(m == 0 && n == 0))
|
||||
{
|
||||
materialFrequency[oldMaterials[x + 1 + m][z + 1 + n]]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find most common neighboring material.
|
||||
for (BlockTypes type : BlockTypes.values)
|
||||
{
|
||||
int i = type.getInternalId();
|
||||
if (materialFrequency[i] > modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER)))
|
||||
{
|
||||
modeMatCount = materialFrequency[i];
|
||||
modeMatId = i;
|
||||
}
|
||||
}
|
||||
// Make sure there'world not a tie for most common
|
||||
for (int i = 0; i < modeMatId; i++)
|
||||
{
|
||||
BlockTypes type = BlockTypes.get(i);
|
||||
if (materialFrequency[i] == modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER)))
|
||||
{
|
||||
tiecheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Record most common neighbor material for this block
|
||||
if (tiecheck)
|
||||
{
|
||||
newMaterials[x][z] = modeMatId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Undo undo = new Undo();
|
||||
final double rSquared = Math.pow(brushSize + 1, 2);
|
||||
|
||||
// Make the changes
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x - brushSize - 1, 2);
|
||||
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
if (xSquared + Math.pow(z - brushSize - 1, 2) <= rSquared)
|
||||
{
|
||||
if (!(this.excludeAir && BlockTypes.get(newMaterials[x][z]).getMaterial().isAir()) && !(this.excludeWater && (newMaterials[x][z] == BlockTypes.WATER.getInternalId())))
|
||||
{
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize + z) != newMaterials[x][z])
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize + z));
|
||||
}
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() - brushSize + z, this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), newMaterials[x][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Blend Disc Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b bd water -- toggle include or exclude (default) water");
|
||||
return;
|
||||
}
|
||||
|
||||
super.parameters(par, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.blenddisc";
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes
|
||||
*/
|
||||
public class BlendVoxelBrush extends BlendBrushBase
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BlendVoxelBrush()
|
||||
{
|
||||
this.setName("Blend Voxel");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected final void blend(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final int brushSizeDoubled = 2 * brushSize;
|
||||
// Array that holds the original materials plus a buffer
|
||||
final int[][][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1];
|
||||
// Array that holds the blended materials
|
||||
final int[][][] newMaterials = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1];
|
||||
|
||||
// Log current materials into oldmats
|
||||
for (int x = 0; x <= 2 * (brushSize + 1); x++)
|
||||
{
|
||||
for (int y = 0; y <= 2 * (brushSize + 1); y++)
|
||||
{
|
||||
for (int z = 0; z <= 2 * (brushSize + 1); z++)
|
||||
{
|
||||
oldMaterials[x][y][z] = this.getBlockIdAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY() - brushSize - 1 + y, this.getTargetBlock().getZ() - brushSize - 1 + z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log current materials into newmats
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int y = 0; y <= brushSizeDoubled; y++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
newMaterials[x][y][z] = oldMaterials[x + 1][y + 1][z + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blend materials
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int y = 0; y <= brushSizeDoubled; y++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
final int[] materialFrequency = new int[BlockTypes.size()]; // Array that tracks frequency of materials neighboring given block
|
||||
int modeMatCount = 0;
|
||||
int modeMatId = 0;
|
||||
boolean tiecheck = true;
|
||||
|
||||
for (int m = -1; m <= 1; m++)
|
||||
{
|
||||
for (int n = -1; n <= 1; n++)
|
||||
{
|
||||
for (int o = -1; o <= 1; o++)
|
||||
{
|
||||
if (!(m == 0 && n == 0 && o == 0))
|
||||
{
|
||||
materialFrequency[oldMaterials[x + 1 + m][y + 1 + n][z + 1 + o]]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find most common neighboring material.
|
||||
for (BlockTypes type : BlockTypes.values)
|
||||
{
|
||||
int i = type.getInternalId();
|
||||
if (materialFrequency[i] > modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER)))
|
||||
{
|
||||
modeMatCount = materialFrequency[i];
|
||||
modeMatId = i;
|
||||
}
|
||||
}
|
||||
// Make sure there'world not a tie for most common
|
||||
for (int i = 0; i < modeMatId; i++)
|
||||
{
|
||||
BlockTypes type = BlockTypes.get(i);
|
||||
if (materialFrequency[i] == modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER)))
|
||||
{
|
||||
tiecheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Record most common neighbor material for this block
|
||||
if (tiecheck)
|
||||
{
|
||||
newMaterials[x][y][z] = modeMatId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Undo undo = new Undo();
|
||||
|
||||
// Make the changes
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
for (int y = 0; y <= brushSizeDoubled; y++)
|
||||
{
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
if (!(this.excludeAir && BlockTypes.get(newMaterials[x][y][z]).getMaterial().isAir()) && !(this.excludeWater && (newMaterials[x][y][z] == BlockTypes.WATER.getInternalId())))
|
||||
{
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, this.getTargetBlock().getZ() - brushSize + z) != newMaterials[x][y][z])
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, this.getTargetBlock().getZ() - brushSize + z));
|
||||
}
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() - brushSize + z, this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + y, newMaterials[x][y][z]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Blend Voxel Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b bv water -- toggle include or exclude (default) water");
|
||||
return;
|
||||
}
|
||||
|
||||
super.parameters(par, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.blendvoxel";
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Blend_Brushes
|
||||
*/
|
||||
public class BlendVoxelDiscBrush extends BlendBrushBase
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BlendVoxelDiscBrush()
|
||||
{
|
||||
this.setName("Blend Voxel Disc");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected final void blend(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final int brushSizeDoubled = 2 * brushSize;
|
||||
final int[][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer
|
||||
final int[][] newMaterials = new int[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Array that holds the blended materials
|
||||
|
||||
// Log current materials into oldmats
|
||||
for (int x = 0; x <= 2 * (brushSize + 1); x++)
|
||||
{
|
||||
for (int z = 0; z <= 2 * (brushSize + 1); z++)
|
||||
{
|
||||
oldMaterials[x][z] = this.getBlockIdAt(this.getTargetBlock().getX() - brushSize - 1 + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize - 1 + z);
|
||||
}
|
||||
}
|
||||
|
||||
// Log current materials into newmats
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
newMaterials[x][z] = oldMaterials[x + 1][z + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Blend materials
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
final int[] materialFrequency = new int[BlockTypes.size()]; // Array that tracks frequency of materials neighboring given block
|
||||
int modeMatCount = 0;
|
||||
int modeMatId = 0;
|
||||
boolean tiecheck = true;
|
||||
|
||||
for (int m = -1; m <= 1; m++)
|
||||
{
|
||||
for (int n = -1; n <= 1; n++)
|
||||
{
|
||||
if (!(m == 0 && n == 0))
|
||||
{
|
||||
materialFrequency[oldMaterials[x + 1 + m][z + 1 + n]]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find most common neighboring material.
|
||||
for (BlockTypes type : BlockTypes.values)
|
||||
{
|
||||
int i = type.getInternalId();
|
||||
if (materialFrequency[i] > modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER)))
|
||||
{
|
||||
modeMatCount = materialFrequency[i];
|
||||
modeMatId = i;
|
||||
}
|
||||
}
|
||||
// Make sure there'world not a tie for most common
|
||||
for (int i = 0; i < modeMatId; i++)
|
||||
{
|
||||
BlockTypes type = BlockTypes.get(i);
|
||||
if (materialFrequency[i] == modeMatCount && !(this.excludeAir && type.getMaterial().isAir()) && !(this.excludeWater && (type == BlockTypes.WATER)))
|
||||
{
|
||||
tiecheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Record most common neighbor material for this block
|
||||
if (tiecheck)
|
||||
{
|
||||
newMaterials[x][z] = modeMatId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Undo undo = new Undo();
|
||||
|
||||
// Make the changes
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
if (!(this.excludeAir && BlockTypes.get(newMaterials[x][z]).getMaterial().isAir()) && !(this.excludeWater && (newMaterials[x][z] == BlockTypes.WATER.getInternalId())))
|
||||
{
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize + z) != newMaterials[x][z])
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - brushSize + z));
|
||||
}
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() - brushSize + z, this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY(), newMaterials[x][z]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Blend Voxel Disc Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b bvd water -- toggle include or exclude (default) water");
|
||||
return;
|
||||
}
|
||||
|
||||
super.parameters(par, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.blendvoxeldisc";
|
||||
}
|
||||
}
|
313
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlobBrush.java
Normale Datei
313
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/BlobBrush.java
Normale Datei
@ -0,0 +1,313 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Blob_Brush
|
||||
*
|
||||
* @author Giltwist
|
||||
*/
|
||||
public class BlobBrush extends PerformBrush
|
||||
{
|
||||
private static final int GROW_PERCENT_DEFAULT = 1000;
|
||||
private static final int GROW_PERCENT_MIN = 1;
|
||||
private static final int GROW_PERCENT_MAX = 9999;
|
||||
|
||||
private Random randomGenerator = new Random();
|
||||
private int growPercent = GROW_PERCENT_DEFAULT; // chance block on recursion pass is made active
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BlobBrush()
|
||||
{
|
||||
this.setName("Blob");
|
||||
}
|
||||
|
||||
private void checkValidGrowPercent(final SnipeData v)
|
||||
{
|
||||
if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX)
|
||||
{
|
||||
this.growPercent = GROW_PERCENT_DEFAULT;
|
||||
v.sendMessage(ChatColor.BLUE + "Growth percent set to: 10%");
|
||||
}
|
||||
}
|
||||
|
||||
private void digBlob(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final int brushSizeDoubled = 2 * brushSize;
|
||||
final int[][][] splat = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1];
|
||||
final int[][][] tempSplat = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1];
|
||||
|
||||
this.checkValidGrowPercent(v);
|
||||
|
||||
// Seed the array
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
for (int y = brushSizeDoubled; y >= 0; y--)
|
||||
{
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
if ((x == 0 || y == 0 | z == 0 || x == brushSizeDoubled || y == brushSizeDoubled || z == brushSizeDoubled) && this.randomGenerator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent)
|
||||
{
|
||||
splat[x][y][z] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
splat[x][y][z] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Grow the seed
|
||||
for (int r = 0; r < brushSize; r++)
|
||||
{
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
for (int y = brushSizeDoubled; y >= 0; y--)
|
||||
{
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
tempSplat[x][y][z] = splat[x][y][z];
|
||||
double growCheck = 0;
|
||||
if (splat[x][y][z] == 1)
|
||||
{
|
||||
if (x != 0 && splat[x - 1][y][z] == 0)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
if (y != 0 && splat[x][y - 1][z] == 0)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
if (z != 0 && splat[x][y][z - 1] == 0)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
if (x != 2 * brushSize && splat[x + 1][y][z] == 0)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
if (y != 2 * brushSize && splat[x][y + 1][z] == 0)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
if (z != 2 * brushSize && splat[x][y][z + 1] == 0)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
}
|
||||
|
||||
if (growCheck >= 1 && this.randomGenerator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent)
|
||||
{
|
||||
tempSplat[x][y][z] = 0; // prevent bleed into splat
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// shouldn't this just be splat = tempsplat;? -Gavjenks
|
||||
// integrate tempsplat back into splat at end of iteration
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
for (int y = brushSizeDoubled; y >= 0; y--)
|
||||
{
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
splat[x][y][z] = tempSplat[x][y][z];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final double rSquared = Math.pow(brushSize + 1, 2);
|
||||
|
||||
// Make the changes
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x - brushSize - 1, 2);
|
||||
|
||||
for (int y = brushSizeDoubled; y >= 0; y--)
|
||||
{
|
||||
final double ySquared = Math.pow(y - brushSize - 1, 2);
|
||||
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
if (splat[x][y][z] == 1 && xSquared + ySquared + Math.pow(z - brushSize - 1, 2) <= rSquared)
|
||||
{
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + z, this.getTargetBlock().getZ() - brushSize + y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void growBlob(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final int brushSizeDoubled = 2 * brushSize;
|
||||
final int[][][] splat = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1];
|
||||
final int[][][] tempSplat = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1];
|
||||
|
||||
this.checkValidGrowPercent(v);
|
||||
|
||||
// Seed the array
|
||||
splat[brushSize][brushSize][brushSize] = 1;
|
||||
|
||||
// Grow the seed
|
||||
for (int r = 0; r < brushSize; r++)
|
||||
{
|
||||
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
for (int y = brushSizeDoubled; y >= 0; y--)
|
||||
{
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
tempSplat[x][y][z] = splat[x][y][z];
|
||||
int growCheck = 0;
|
||||
if (splat[x][y][z] == 0)
|
||||
{
|
||||
if (x != 0 && splat[x - 1][y][z] == 1)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
if (y != 0 && splat[x][y - 1][z] == 1)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
if (z != 0 && splat[x][y][z - 1] == 1)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
if (x != 2 * brushSize && splat[x + 1][y][z] == 1)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
if (y != 2 * brushSize && splat[x][y + 1][z] == 1)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
if (z != 2 * brushSize && splat[x][y][z + 1] == 1)
|
||||
{
|
||||
growCheck++;
|
||||
}
|
||||
}
|
||||
|
||||
if (growCheck >= 1 && this.randomGenerator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent)
|
||||
{
|
||||
// prevent bleed into splat
|
||||
tempSplat[x][y][z] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// integrate tempsplat back into splat at end of iteration
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
for (int y = brushSizeDoubled; y >= 0; y--)
|
||||
{
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
splat[x][y][z] = tempSplat[x][y][z];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final double rSquared = Math.pow(brushSize + 1, 2);
|
||||
|
||||
// Make the changes
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x - brushSize - 1, 2);
|
||||
|
||||
for (int y = brushSizeDoubled; y >= 0; y--)
|
||||
{
|
||||
final double ySquared = Math.pow(y - brushSize - 1, 2);
|
||||
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
if (splat[x][y][z] == 1 && xSquared + ySquared + Math.pow(z - brushSize - 1, 2) <= rSquared)
|
||||
{
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() - brushSize + x, this.getTargetBlock().getY() - brushSize + z, this.getTargetBlock().getZ() - brushSize + y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.growBlob(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.digBlob(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
this.checkValidGrowPercent(null);
|
||||
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Blob brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b blob g[int] -- set a growth percentage (" + GROW_PERCENT_MIN + "-" + GROW_PERCENT_MAX + "). Default is " + GROW_PERCENT_DEFAULT);
|
||||
return;
|
||||
}
|
||||
if (parameter.startsWith("g"))
|
||||
{
|
||||
final int temp = Integer.parseInt(parameter.replace("g", ""));
|
||||
if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + (float) temp / 100 + "%");
|
||||
this.growPercent = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Growth percent must be an integer " + GROW_PERCENT_MIN + "-" + GROW_PERCENT_MAX + "!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.blob";
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
public class BlockResetBrush extends Brush
|
||||
{
|
||||
private static final ArrayList<Material> DENIED_UPDATES = new ArrayList<Material>();
|
||||
|
||||
static
|
||||
{
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.SIGN);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_SIGN_POST);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.WALL_SIGN);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.CHEST);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.FURNACE);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_BURNING_FURNACE);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_REDSTONE_TORCH_OFF);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_REDSTONE_TORCH_ON);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.REDSTONE_WIRE);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_DIODE_BLOCK_OFF);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_DIODE_BLOCK_ON);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_WOODEN_DOOR);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_WOOD_DOOR);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.IRON_DOOR);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_IRON_DOOR_BLOCK);
|
||||
BlockResetBrush.DENIED_UPDATES.add(Material.LEGACY_FENCE_GATE);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BlockResetBrush()
|
||||
{
|
||||
this.setName("Block Reset Brush");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void applyBrush(final SnipeData v)
|
||||
{
|
||||
for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++)
|
||||
{
|
||||
for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++)
|
||||
{
|
||||
for (int y = -v.getBrushSize(); y <= v.getBrushSize(); y++)
|
||||
{
|
||||
final Block block = this.getWorld().getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z);
|
||||
if (BlockResetBrush.DENIED_UPDATES.contains(block.getType()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
block.setBlockData(block.getType().createBlockData(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
applyBrush(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
applyBrush(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.blockreset";
|
||||
}
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncWorld;
|
||||
import com.sk89q.worldedit.blocks.BlockMaterial;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* This brush only looks for solid blocks, and then changes those plus any air blocks touching them. If it works, this brush should be faster than the original
|
||||
* blockPositionY an amount proportional to the volume of a snipe selection area / the number of blocks touching air in the selection. This is because every solid block
|
||||
* surrounded blockPositionY others should take equally long to check and not change as it would take MC to change them and then check and find no lighting to update. For
|
||||
* air blocks surrounded blockPositionY other air blocks, this brush saves about 80-100 checks blockPositionY not updating them or their lighting. And for air blocks touching solids,
|
||||
* this brush is slower, because it replaces the air once per solid block it is touching. I assume on average this is about 2 blocks. So every air block
|
||||
* touching a solid negates one air block floating in air. Thus, for selections that have more air blocks surrounded blockPositionY air than air blocks touching solids,
|
||||
* this brush will be faster, which is almost always the case, especially for undeveloped terrain and for larger brush sizes (unlike the original brush, this
|
||||
* should only slow down blockPositionY the square of the brush size, not the cube of the brush size). For typical terrain, blockPositionY my calculations, overall speed increase is
|
||||
* about a factor of 5-6 for a size 20 brush. For a complicated city or ship, etc., this may be only a factor of about 2. In a hypothetical worst case scenario
|
||||
* of a 3d checkerboard of stone and air every other block, this brush should only be about 1.5x slower than the original brush. Savings increase for larger
|
||||
* brushes.
|
||||
*
|
||||
* @author GavJenks
|
||||
*/
|
||||
public class BlockResetSurfaceBrush extends Brush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BlockResetSurfaceBrush()
|
||||
{
|
||||
this.setName("Block Reset Brush Surface Only");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void applyBrush(final SnipeData v)
|
||||
{
|
||||
final AsyncWorld world = this.getWorld();
|
||||
|
||||
for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++)
|
||||
{
|
||||
for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++)
|
||||
{
|
||||
for (int y = -v.getBrushSize(); y <= v.getBrushSize(); y++)
|
||||
{
|
||||
|
||||
AsyncBlock block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z);
|
||||
|
||||
|
||||
Material type = block.getType();
|
||||
BlockMaterial mat = BukkitAdapter.adapt(type).getMaterial();
|
||||
if (!mat.isSolid() || !mat.isFullCube() || mat.hasContainer())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean airFound = false;
|
||||
|
||||
if (world.getBlockAt(this.getTargetBlock().getX() + x + 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z).isEmpty())
|
||||
{
|
||||
block = world.getBlockAt(this.getTargetBlock().getX() + x + 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z);
|
||||
final int oldData = block.getPropertyId();
|
||||
resetBlock(block, oldData);
|
||||
airFound = true;
|
||||
}
|
||||
|
||||
if (world.getBlockAt(this.getTargetBlock().getX() + x - 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z).isEmpty())
|
||||
{
|
||||
block = world.getBlockAt(this.getTargetBlock().getX() + x - 1, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z);
|
||||
final int oldData = block.getPropertyId();
|
||||
resetBlock(block, oldData);
|
||||
airFound = true;
|
||||
}
|
||||
|
||||
if (world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y + 1, this.getTargetBlock().getZ() + z).isEmpty())
|
||||
{
|
||||
block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y + 1, this.getTargetBlock().getZ() + z);
|
||||
final int oldData = block.getPropertyId();
|
||||
resetBlock(block, oldData);
|
||||
airFound = true;
|
||||
}
|
||||
|
||||
if (world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y - 1, this.getTargetBlock().getZ() + z).isEmpty())
|
||||
{
|
||||
block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y - 1, this.getTargetBlock().getZ() + z);
|
||||
final int oldData = block.getPropertyId();
|
||||
resetBlock(block, oldData);
|
||||
airFound = true;
|
||||
}
|
||||
|
||||
if (world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z + 1).isEmpty())
|
||||
{
|
||||
block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z + 1);
|
||||
final int oldData = block.getPropertyId();
|
||||
resetBlock(block, oldData);
|
||||
airFound = true;
|
||||
}
|
||||
|
||||
if (world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z - 1).isEmpty())
|
||||
{
|
||||
block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z - 1);
|
||||
final int oldData = block.getPropertyId();
|
||||
resetBlock(block, oldData);
|
||||
airFound = true;
|
||||
}
|
||||
|
||||
if (airFound)
|
||||
{
|
||||
block = world.getBlockAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z);
|
||||
final int oldData = block.getPropertyId();
|
||||
resetBlock(block, oldData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void resetBlock(AsyncBlock block, final int oldData)
|
||||
{
|
||||
block.setTypeIdAndPropertyId(block.getTypeId(), ((block.getPropertyId() + 1) & 0xf), true);
|
||||
block.setTypeIdAndPropertyId(block.getTypeId(), oldData, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
applyBrush(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
applyBrush(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.blockresetsurface";
|
||||
}
|
||||
}
|
311
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Brush.java
Normale Datei
311
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Brush.java
Normale Datei
@ -0,0 +1,311 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncWorld;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.RangeBlockHelper;
|
||||
import com.thevoxelbox.voxelsniper.SnipeAction;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import com.thevoxelbox.voxelsniper.util.BlockWrapper;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
/**
|
||||
* Abstract implementation of the {@link IBrush} interface.
|
||||
*/
|
||||
public abstract class Brush implements IBrush
|
||||
{
|
||||
protected static final int CHUNK_SIZE = 16;
|
||||
/**
|
||||
* Targeted Block.
|
||||
*/
|
||||
private AsyncBlock targetBlock;
|
||||
/**
|
||||
* Last Block before targeted Block.
|
||||
*/
|
||||
private AsyncBlock lastBlock;
|
||||
/**
|
||||
* Brush name.
|
||||
*/
|
||||
private String name = "Undefined";
|
||||
|
||||
/**
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return {@link Block}
|
||||
*/
|
||||
public final AsyncBlock clampY(final int x, final int y, final int z)
|
||||
{
|
||||
int clampedY = y;
|
||||
if (clampedY < 0)
|
||||
{
|
||||
clampedY = 0;
|
||||
}
|
||||
else if (clampedY > this.getWorld().getMaxHeight())
|
||||
{
|
||||
clampedY = this.getWorld().getMaxHeight();
|
||||
}
|
||||
|
||||
return this.getWorld().getBlockAt(x, clampedY, z);
|
||||
}
|
||||
|
||||
private boolean preparePerform(final SnipeData v, final AsyncBlock clickedBlock, final BlockFace clickedFace)
|
||||
{
|
||||
if (this.getTarget(v, clickedBlock, clickedFace))
|
||||
{
|
||||
if (this instanceof PerformBrush)
|
||||
{
|
||||
((PerformBrush) this).initP(v);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean perform(SnipeAction action, SnipeData data, AsyncBlock targetBlock, AsyncBlock lastBlock)
|
||||
{
|
||||
this.setTargetBlock(targetBlock);
|
||||
this.setLastBlock(lastBlock);
|
||||
switch (action)
|
||||
{
|
||||
case ARROW:
|
||||
this.arrow(data);
|
||||
return true;
|
||||
case GUNPOWDER:
|
||||
this.powder(data);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The arrow action. Executed when a player RightClicks with an Arrow
|
||||
*
|
||||
* @param v Sniper caller
|
||||
*/
|
||||
protected void arrow(final SnipeData v)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* The powder action. Executed when a player RightClicks with Gunpowder
|
||||
*
|
||||
* @param v Sniper caller
|
||||
*/
|
||||
protected void powder(final SnipeData v)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void info(Message vm);
|
||||
|
||||
@Override
|
||||
public void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "This brush does not accept additional parameters.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridable getTarget method.
|
||||
*
|
||||
* @param v
|
||||
* @param clickedBlock
|
||||
* @param clickedFace
|
||||
* @return boolean
|
||||
*/
|
||||
protected final boolean getTarget(final SnipeData v, final AsyncBlock clickedBlock, final BlockFace clickedFace)
|
||||
{
|
||||
if (clickedBlock != null)
|
||||
{
|
||||
this.setTargetBlock(clickedBlock);
|
||||
this.setLastBlock(clickedBlock.getRelative(clickedFace));
|
||||
if (this.getLastBlock() == null)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Snipe target block must be visible.");
|
||||
return false;
|
||||
}
|
||||
if (v.owner().getSnipeData(v.owner().getCurrentToolId()).isLightningEnabled())
|
||||
{
|
||||
this.getWorld().strikeLightning(this.getTargetBlock().getLocation());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RangeBlockHelper rangeBlockHelper;
|
||||
if (v.owner().getSnipeData(v.owner().getCurrentToolId()).isRanged())
|
||||
{
|
||||
rangeBlockHelper = new RangeBlockHelper(v.owner().getPlayer(), v.owner().getWorld(), (double) v.owner().getSnipeData(v.owner().getCurrentToolId()).getRange());
|
||||
this.setTargetBlock(rangeBlockHelper.getRangeBlock());
|
||||
}
|
||||
else
|
||||
{
|
||||
rangeBlockHelper = new RangeBlockHelper(v.owner().getPlayer(), v.owner().getWorld());
|
||||
this.setTargetBlock(rangeBlockHelper.getTargetBlock());
|
||||
}
|
||||
if (this.getTargetBlock() != null)
|
||||
{
|
||||
this.setLastBlock(rangeBlockHelper.getLastBlock());
|
||||
if (this.getLastBlock() == null)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Snipe target block must be visible.");
|
||||
return false;
|
||||
}
|
||||
if (v.owner().getSnipeData(v.owner().getCurrentToolId()).isLightningEnabled())
|
||||
{
|
||||
this.getWorld().strikeLightning(this.getTargetBlock().getLocation());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Snipe target block must be visible.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setName(final String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBrushCategory()
|
||||
{
|
||||
return "General";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the targetBlock
|
||||
*/
|
||||
protected final AsyncBlock getTargetBlock()
|
||||
{
|
||||
return this.targetBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param targetBlock the targetBlock to set
|
||||
*/
|
||||
protected final void setTargetBlock(final AsyncBlock targetBlock)
|
||||
{
|
||||
this.targetBlock = targetBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the world
|
||||
*/
|
||||
protected final AsyncWorld getWorld()
|
||||
{
|
||||
return targetBlock.getWorld();
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up Type ID of Block at given coordinates in the world of the targeted Block.
|
||||
*
|
||||
* @param x X coordinate
|
||||
* @param y Y coordinate
|
||||
* @param z Z coordinate
|
||||
* @return Type ID of Block at given coordinates in the world of the targeted Block.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected int getBlockIdAt(int x, int y, int z)
|
||||
{
|
||||
return getWorld().getBlockAt(x, y, z).getTypeId();
|
||||
}
|
||||
|
||||
protected Block getBlockAt(int x, int y, int z)
|
||||
{
|
||||
return getWorld().getBlockAt(x, y, z);
|
||||
}
|
||||
|
||||
protected Material getBlockType(int x, int y, int z)
|
||||
{
|
||||
return getWorld().getBlockAt(x, y, z).getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up Block Data Value of Block at given coordinates in the world of the targeted Block.
|
||||
*
|
||||
* @param x X coordinate
|
||||
* @param y Y coordinate
|
||||
* @param z Z coordinate
|
||||
* @return Block Data Value of Block at given coordinates in the world of the targeted Block.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected int getBlockDataAt(int x, int y, int z)
|
||||
{
|
||||
return this.getWorld().getBlockAt(x, y, z).getPropertyId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Block before target Block.
|
||||
*/
|
||||
protected final AsyncBlock getLastBlock()
|
||||
{
|
||||
return this.lastBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastBlock Last Block before target Block.
|
||||
*/
|
||||
protected final void setLastBlock(AsyncBlock lastBlock)
|
||||
{
|
||||
this.lastBlock = lastBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set block data with supplied data over BlockWrapper.
|
||||
*
|
||||
* @param blockWrapper Block data wrapper
|
||||
*/
|
||||
@Deprecated
|
||||
protected final void setBlock(BlockWrapper blockWrapper)
|
||||
{
|
||||
this.getWorld().getBlockAt(blockWrapper.getX(), blockWrapper.getY(), blockWrapper.getZ()).setTypeId(blockWrapper.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Id of the block at the passed coordinate.
|
||||
*
|
||||
* @param z Z coordinate
|
||||
* @param x X coordinate
|
||||
* @param y Y coordinate
|
||||
* @param id The id the block will be set to
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected final void setBlockIdAt(int z, int x, int y, int id)
|
||||
{
|
||||
this.getWorld().getBlockAt(x, y, z).setTypeId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the id and data value of the block at the passed coordinate.
|
||||
*
|
||||
* @param x X coordinate
|
||||
* @param y Y coordinate
|
||||
* @param z Z coordinate
|
||||
* @param id The id the block will be set to
|
||||
* @param data The data value the block will be set to
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected final void setBlockIdAndDataAt(int x, int y, int z, int id, int data)
|
||||
{
|
||||
this.getWorld().getBlockAt(x, y, z).setTypeIdAndPropertyId(id, data, true);
|
||||
}
|
||||
}
|
146
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CanyonBrush.java
Normale Datei
146
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CanyonBrush.java
Normale Datei
@ -0,0 +1,146 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncChunk;
|
||||
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;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_CANYONATOR
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class CanyonBrush extends Brush
|
||||
{
|
||||
private static final int SHIFT_LEVEL_MIN = 10;
|
||||
private static final int SHIFT_LEVEL_MAX = 60;
|
||||
private int yLevel = 10;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public CanyonBrush()
|
||||
{
|
||||
this.setName("Canyon");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param chunk
|
||||
* @param undo
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected final void canyon(final AsyncChunk chunk, final Undo undo)
|
||||
{
|
||||
for (int x = 0; x < CHUNK_SIZE; x++)
|
||||
{
|
||||
for (int z = 0; z < CHUNK_SIZE; z++)
|
||||
{
|
||||
int currentYLevel = this.yLevel;
|
||||
|
||||
for (int y = 63; y < this.getWorld().getMaxHeight(); y++)
|
||||
{
|
||||
final AsyncBlock block = chunk.getBlock(x, y, z);
|
||||
final AsyncBlock currentYLevelBlock = chunk.getBlock(x, currentYLevel, z);
|
||||
|
||||
undo.put(block);
|
||||
undo.put(currentYLevelBlock);
|
||||
|
||||
currentYLevelBlock.setTypeId(block.getTypeId());
|
||||
block.setType(Material.AIR);
|
||||
|
||||
currentYLevel++;
|
||||
}
|
||||
|
||||
final AsyncBlock block = chunk.getBlock(x, 0, z);
|
||||
undo.put(block);
|
||||
block.setTypeId(BlockTypes.BEDROCK.getInternalId());
|
||||
|
||||
for (int y = 1; y < SHIFT_LEVEL_MIN; y++)
|
||||
{
|
||||
final Block currentBlock = chunk.getBlock(x, y, z);
|
||||
undo.put(currentBlock);
|
||||
currentBlock.setType(Material.STONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void arrow(final SnipeData v)
|
||||
{
|
||||
final Undo undo = new Undo();
|
||||
|
||||
canyon(getTargetBlock().getChunk(), undo);
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void powder(final SnipeData v)
|
||||
{
|
||||
final Undo undo = new Undo();
|
||||
|
||||
Chunk targetChunk = getTargetBlock().getChunk();
|
||||
for (int x = targetChunk.getX() - 1; x <= targetChunk.getX() + 1; x++)
|
||||
{
|
||||
for (int z = targetChunk.getX() - 1; z <= targetChunk.getX() + 1; z++)
|
||||
{
|
||||
canyon(getWorld().getChunkAt(x, z), undo);
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.GREEN + "Shift Level set to " + this.yLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GREEN + "y[number] to set the Level to which the land will be shifted down");
|
||||
}
|
||||
if (par[1].startsWith("y"))
|
||||
{
|
||||
int _i = Integer.parseInt(par[1].replace("y", ""));
|
||||
if (_i < SHIFT_LEVEL_MIN)
|
||||
{
|
||||
_i = SHIFT_LEVEL_MIN;
|
||||
}
|
||||
else if (_i > SHIFT_LEVEL_MAX)
|
||||
{
|
||||
_i = SHIFT_LEVEL_MAX;
|
||||
}
|
||||
this.yLevel = _i;
|
||||
v.sendMessage(ChatColor.GREEN + "Shift Level set to " + this.yLevel);
|
||||
}
|
||||
}
|
||||
|
||||
protected final int getYLevel()
|
||||
{
|
||||
return yLevel;
|
||||
}
|
||||
|
||||
protected final void setYLevel(int yLevel)
|
||||
{
|
||||
this.yLevel = yLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.canyon";
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Canyon_Selection_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class CanyonSelectionBrush extends CanyonBrush
|
||||
{
|
||||
private boolean first = true;
|
||||
private int fx;
|
||||
private int fz;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public CanyonSelectionBrush()
|
||||
{
|
||||
this.setName("Canyon Selection");
|
||||
}
|
||||
|
||||
private void execute(final SnipeData v)
|
||||
{
|
||||
final Chunk chunk = getTargetBlock().getChunk();
|
||||
|
||||
if (this.first)
|
||||
{
|
||||
this.fx = chunk.getX();
|
||||
this.fz = chunk.getZ();
|
||||
|
||||
v.sendMessage(ChatColor.YELLOW + "First point selected!");
|
||||
this.first = !this.first;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.YELLOW + "Second point selected!");
|
||||
selection(Math.min(fx, chunk.getX()), Math.min(fz, chunk.getZ()), Math.max(fx, chunk.getX()), Math.max(fz, chunk.getZ()), v);
|
||||
|
||||
this.first = !this.first;
|
||||
}
|
||||
}
|
||||
|
||||
private void selection(final int lowX, final int lowZ, final int highX, final int highZ, final SnipeData v)
|
||||
{
|
||||
final Undo undo = new Undo();
|
||||
|
||||
for (int x = lowX; x <= highX; x++)
|
||||
{
|
||||
for (int z = lowZ; z <= highZ; z++)
|
||||
{
|
||||
canyon(getWorld().getChunkAt(x, z), undo);
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
execute(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
execute(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.GREEN + "Shift Level set to " + this.getYLevel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.canyonselection";
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
public class CheckerVoxelDiscBrush extends PerformBrush
|
||||
{
|
||||
private boolean useWorldCoordinates = true;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public CheckerVoxelDiscBrush()
|
||||
{
|
||||
this.setName("Checker Voxel Disc");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v
|
||||
* @param target
|
||||
*/
|
||||
private void applyBrush(final SnipeData v, final Block target)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--)
|
||||
{
|
||||
final int sum = this.useWorldCoordinates ? target.getX() + x + target.getZ() + y : x + y;
|
||||
if (sum % 2 != 0)
|
||||
{
|
||||
this.current.perform(this.clampY(target.getX() + x, target.getY(), target.getZ() + y));
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.applyBrush(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.applyBrush(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int x = 1; x < par.length; x++)
|
||||
{
|
||||
final String parameter = par[x].toLowerCase();
|
||||
|
||||
if (parameter.equals("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + this.getName() + " Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "true -- Enables using World Coordinates.");
|
||||
v.sendMessage(ChatColor.AQUA + "false -- Disables using World Coordinates.");
|
||||
return;
|
||||
}
|
||||
if (parameter.startsWith("true"))
|
||||
{
|
||||
this.useWorldCoordinates = true;
|
||||
v.sendMessage(ChatColor.AQUA + "Enabled using World Coordinates.");
|
||||
}
|
||||
else if (parameter.startsWith("false"))
|
||||
{
|
||||
this.useWorldCoordinates = false;
|
||||
v.sendMessage(ChatColor.AQUA + "Disabled using World Coordinates.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.checkervoxeldisc";
|
||||
}
|
||||
}
|
113
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CleanSnowBrush.java
Normale Datei
113
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CleanSnowBrush.java
Normale Datei
@ -0,0 +1,113 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Clean_Snow_Brush
|
||||
*
|
||||
* @author psanker
|
||||
*/
|
||||
public class CleanSnowBrush extends Brush
|
||||
{
|
||||
private double trueCircle = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public CleanSnowBrush()
|
||||
{
|
||||
this.setName("Clean Snow");
|
||||
}
|
||||
|
||||
private void cleanSnow(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
final Undo undo = new Undo();
|
||||
|
||||
for (int y = (brushSize + 1) * 2; y >= 0; y--)
|
||||
{
|
||||
final double ySquared = Math.pow(y - brushSize, 2);
|
||||
|
||||
for (int x = (brushSize + 1) * 2; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x - brushSize, 2);
|
||||
|
||||
for (int z = (brushSize + 1) * 2; z >= 0; z--)
|
||||
{
|
||||
if ((xSquared + Math.pow(z - brushSize, 2) + ySquared) <= brushSizeSquared)
|
||||
{
|
||||
if ((this.clampY(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize, this.getTargetBlock().getZ() + y - brushSize).getType() == Material.SNOW) && ((this.clampY(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize - 1, this.getTargetBlock().getZ() + y - brushSize).getType() == Material.SNOW) || (this.clampY(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize - 1, this.getTargetBlock().getZ() + y - brushSize).isEmpty())))
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + z, this.getTargetBlock().getZ() + y));
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() + y - brushSize, this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize, 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.cleanSnow(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.cleanSnow(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Clean Snow Brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b cls true -- will use a true sphere algorithm instead of the skinnier version with classic sniper nubs. /b cls false will switch back. (false is default)");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("true"))
|
||||
{
|
||||
this.trueCircle = 0.5;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode ON.");
|
||||
}
|
||||
else if (parameter.startsWith("false"))
|
||||
{
|
||||
this.trueCircle = 0;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode OFF.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.cleansnow";
|
||||
}
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
/**
|
||||
* The CloneStamp class is used to create a collection of blocks in a cylinder shape according to the selection the player has set.
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Clone_and_CopyPasta_Brushes
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class CloneStampBrush extends StampBrush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public CloneStampBrush()
|
||||
{
|
||||
this.setName("Clone");
|
||||
}
|
||||
|
||||
/**
|
||||
* The clone method is used to grab a snapshot of the selected area dictated blockPositionY targetBlock.x y z v.brushSize v.voxelHeight and v.cCen.
|
||||
* <p/>
|
||||
* x y z -- initial center of the selection v.brushSize -- the radius of the cylinder v.voxelHeight -- the heigth of the cylinder c.cCen -- the offset on
|
||||
* the Y axis of the selection ( bottom of the cylinder ) as blockPositionY: Bottom_Y = targetBlock.y + v.cCen;
|
||||
*
|
||||
* @param v
|
||||
* the caller
|
||||
*/
|
||||
private void clone(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
this.clone.clear();
|
||||
this.fall.clear();
|
||||
this.drop.clear();
|
||||
this.solid.clear();
|
||||
this.sorted = false;
|
||||
|
||||
int yStartingPoint = this.getTargetBlock().getY() + v.getcCen();
|
||||
int yEndPoint = this.getTargetBlock().getY() + v.getVoxelHeight() + v.getcCen();
|
||||
|
||||
if (yStartingPoint < 0)
|
||||
{
|
||||
yStartingPoint = 0;
|
||||
v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world start position.");
|
||||
}
|
||||
else if (yStartingPoint > this.getWorld().getMaxHeight() - 1)
|
||||
{
|
||||
yStartingPoint = this.getWorld().getMaxHeight() - 1;
|
||||
v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world start position.");
|
||||
}
|
||||
|
||||
if (yEndPoint < 0)
|
||||
{
|
||||
yEndPoint = 0;
|
||||
v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world end position.");
|
||||
}
|
||||
else if (yEndPoint > this.getWorld().getMaxHeight() - 1)
|
||||
{
|
||||
yEndPoint = this.getWorld().getMaxHeight() - 1;
|
||||
v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world end position.");
|
||||
}
|
||||
|
||||
final double bSquared = Math.pow(brushSize, 2);
|
||||
|
||||
for (int z = yStartingPoint; z < yEndPoint; z++)
|
||||
{
|
||||
this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX(), z, this.getTargetBlock().getZ()), 0, z - yStartingPoint, 0));
|
||||
for (int y = 1; y <= brushSize; y++)
|
||||
{
|
||||
this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX(), z, this.getTargetBlock().getZ() + y), 0, z - yStartingPoint, y));
|
||||
this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX(), z, this.getTargetBlock().getZ() - y), 0, z - yStartingPoint, -y));
|
||||
this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() + y, z, this.getTargetBlock().getZ()), y, z - yStartingPoint, 0));
|
||||
this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() - y, z, this.getTargetBlock().getZ()), -y, z - yStartingPoint, 0));
|
||||
}
|
||||
for (int x = 1; x <= brushSize; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
for (int y = 1; y <= brushSize; y++)
|
||||
{
|
||||
if ((xSquared + Math.pow(y, 2)) <= bSquared)
|
||||
{
|
||||
this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() + x, z, this.getTargetBlock().getZ() + y), x, z - yStartingPoint, y));
|
||||
this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() + x, z, this.getTargetBlock().getZ() - y), x, z - yStartingPoint, -y));
|
||||
this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() - x, z, this.getTargetBlock().getZ() + y), -x, z - yStartingPoint, y));
|
||||
this.clone.add(new BlockWrapper(this.clampY(this.getTargetBlock().getX() - x, z, this.getTargetBlock().getZ() - y), -x, z - yStartingPoint, -y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.sendMessage(ChatColor.GREEN + String.valueOf(this.clone.size()) + ChatColor.AQUA + " blocks copied sucessfully.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.clone(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.height();
|
||||
vm.center();
|
||||
switch (this.stamp)
|
||||
{
|
||||
case DEFAULT:
|
||||
vm.brushMessage("Default Stamp");
|
||||
break;
|
||||
|
||||
case NO_AIR:
|
||||
vm.brushMessage("No-Air Stamp");
|
||||
break;
|
||||
|
||||
case FILL:
|
||||
vm.brushMessage("Fill Stamp");
|
||||
break;
|
||||
|
||||
default:
|
||||
vm.custom(ChatColor.DARK_RED + "Error while stamping! Report");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v)
|
||||
{
|
||||
final String parameter = par[1];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Clone / Stamp Cylinder brush parameters");
|
||||
v.sendMessage(ChatColor.GREEN + "cs f -- Activates Fill mode");
|
||||
v.sendMessage(ChatColor.GREEN + "cs a -- Activates No-Air mode");
|
||||
v.sendMessage(ChatColor.GREEN + "cs d -- Activates Default mode");
|
||||
}
|
||||
if (parameter.equalsIgnoreCase("a"))
|
||||
{
|
||||
this.setStamp(StampType.NO_AIR);
|
||||
this.reSort();
|
||||
v.sendMessage(ChatColor.AQUA + "No-Air stamp brush");
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("f"))
|
||||
{
|
||||
this.setStamp(StampType.FILL);
|
||||
this.reSort();
|
||||
v.sendMessage(ChatColor.AQUA + "Fill stamp brush");
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("d"))
|
||||
{
|
||||
this.setStamp(StampType.DEFAULT);
|
||||
this.reSort();
|
||||
v.sendMessage(ChatColor.AQUA + "Default stamp brush");
|
||||
}
|
||||
else if (parameter.startsWith("c"))
|
||||
{
|
||||
v.setcCen(Integer.parseInt(parameter.replace("c", "")));
|
||||
v.sendMessage(ChatColor.BLUE + "Center set to " + v.getcCen());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.clonestamp";
|
||||
}
|
||||
}
|
108
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CometBrush.java
Normale Datei
108
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CometBrush.java
Normale Datei
@ -0,0 +1,108 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.LargeFireball;
|
||||
import org.bukkit.entity.SmallFireball;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
|
||||
/**
|
||||
* @author Gavjenks Heavily revamped from ruler brush blockPositionY
|
||||
* @author Giltwist
|
||||
* @author Monofraps (Merged Meteor brush)
|
||||
*/
|
||||
public class CometBrush extends Brush
|
||||
{
|
||||
private boolean useBigBalls = false;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public CometBrush()
|
||||
{
|
||||
this.setName("Comet");
|
||||
}
|
||||
|
||||
private void doFireball(final SnipeData v)
|
||||
{
|
||||
final Vector targetCoords = new Vector(this.getTargetBlock().getX() + .5 * this.getTargetBlock().getX() / Math.abs(this.getTargetBlock().getX()), this.getTargetBlock().getY() + .5, this.getTargetBlock().getZ() + .5 * this.getTargetBlock().getZ() / Math.abs(this.getTargetBlock().getZ()));
|
||||
final Location playerLocation = v.owner().getPlayer().getEyeLocation();
|
||||
final Vector slope = targetCoords.subtract(playerLocation.toVector());
|
||||
|
||||
if (useBigBalls)
|
||||
{
|
||||
v.owner().getPlayer().launchProjectile(LargeFireball.class).setVelocity(slope.normalize());
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().getPlayer().launchProjectile(SmallFireball.class).setVelocity(slope.normalize());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 0; i < par.length; ++i)
|
||||
{
|
||||
String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage("Parameters:");
|
||||
v.sendMessage("balls [big|small] -- Sets your ball size.");
|
||||
}
|
||||
if (parameter.equalsIgnoreCase("balls"))
|
||||
{
|
||||
if (i + 1 >= par.length)
|
||||
{
|
||||
v.sendMessage("The balls parameter expects a ball size after it.");
|
||||
}
|
||||
|
||||
String newBallSize = par[++i];
|
||||
if (newBallSize.equalsIgnoreCase("big"))
|
||||
{
|
||||
useBigBalls = true;
|
||||
v.sendMessage("Your balls are " + ChatColor.DARK_RED + ("BIG"));
|
||||
}
|
||||
else if (newBallSize.equalsIgnoreCase("small"))
|
||||
{
|
||||
useBigBalls = false;
|
||||
v.sendMessage("Your balls are " + ChatColor.DARK_RED + ("small"));
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage("Unknown ball size.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.doFireball(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.doFireball(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.voxel();
|
||||
vm.custom("Your balls are " + ChatColor.DARK_RED + (useBigBalls ? "BIG" : "small"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.comet";
|
||||
}
|
||||
}
|
222
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CopyPastaBrush.java
Normale Datei
222
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CopyPastaBrush.java
Normale Datei
@ -0,0 +1,222 @@
|
||||
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;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#CopyPasta_Brush
|
||||
*
|
||||
* @author giltwist
|
||||
*/
|
||||
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");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
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 com.thevoxelbox.voxelsniper.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 com.thevoxelbox.voxelsniper.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 com.thevoxelbox.voxelsniper.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";
|
||||
}
|
||||
}
|
146
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CylinderBrush.java
Normale Datei
146
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/CylinderBrush.java
Normale Datei
@ -0,0 +1,146 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* @author Kavutop
|
||||
*/
|
||||
public class CylinderBrush extends PerformBrush
|
||||
{
|
||||
private double trueCircle = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public CylinderBrush()
|
||||
{
|
||||
this.setName("Cylinder");
|
||||
}
|
||||
|
||||
private void cylinder(final SnipeData v, Block targetBlock)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
int yStartingPoint = targetBlock.getY() + v.getcCen();
|
||||
int yEndPoint = targetBlock.getY() + v.getVoxelHeight() + v.getcCen();
|
||||
|
||||
if (yEndPoint < yStartingPoint)
|
||||
{
|
||||
yEndPoint = yStartingPoint;
|
||||
}
|
||||
if (yStartingPoint < 0)
|
||||
{
|
||||
yStartingPoint = 0;
|
||||
v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world start position.");
|
||||
}
|
||||
else if (yStartingPoint > this.getWorld().getMaxHeight() - 1)
|
||||
{
|
||||
yStartingPoint = this.getWorld().getMaxHeight() - 1;
|
||||
v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world start position.");
|
||||
}
|
||||
if (yEndPoint < 0)
|
||||
{
|
||||
yEndPoint = 0;
|
||||
v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world end position.");
|
||||
}
|
||||
else if (yEndPoint > this.getWorld().getMaxHeight() - 1)
|
||||
{
|
||||
yEndPoint = this.getWorld().getMaxHeight() - 1;
|
||||
v.sendMessage(ChatColor.DARK_PURPLE + "Warning: off-world end position.");
|
||||
}
|
||||
|
||||
final double bSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
|
||||
for (int y = yEndPoint; y >= yStartingPoint; y--)
|
||||
{
|
||||
for (int x = brushSize; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
|
||||
for (int z = brushSize; z >= 0; z--)
|
||||
{
|
||||
if ((xSquared + Math.pow(z, 2)) <= bSquared)
|
||||
{
|
||||
this.current.perform(this.clampY(targetBlock.getX() + x, y, targetBlock.getZ() + z));
|
||||
this.current.perform(this.clampY(targetBlock.getX() + x, y, targetBlock.getZ() - z));
|
||||
this.current.perform(this.clampY(targetBlock.getX() - x, y, targetBlock.getZ() + z));
|
||||
this.current.perform(this.clampY(targetBlock.getX() - x, y, targetBlock.getZ() - z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.cylinder(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.cylinder(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.height();
|
||||
vm.center();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Cylinder Brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b c h[number] -- set the cylinder v.voxelHeight. Default is 1.");
|
||||
v.sendMessage(ChatColor.DARK_AQUA + "/b c true -- will use a true circle algorithm instead of the skinnier version with classic sniper nubs. /b b false will switch back. (false is default)");
|
||||
v.sendMessage(ChatColor.DARK_BLUE + "/b c c[number] -- set the origin of the cylinder compared to the target block. Positive numbers will move the cylinder upward, negative will move it downward.");
|
||||
return;
|
||||
}
|
||||
if (parameter.startsWith("true"))
|
||||
{
|
||||
this.trueCircle = 0.5;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode ON.");
|
||||
}
|
||||
else if (parameter.startsWith("false"))
|
||||
{
|
||||
this.trueCircle = 0;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode OFF.");
|
||||
}
|
||||
else if (parameter.startsWith("h"))
|
||||
{
|
||||
v.setVoxelHeight((int) Double.parseDouble(parameter.replace("h", "")));
|
||||
v.sendMessage(ChatColor.AQUA + "Cylinder v.voxelHeight set to: " + v.getVoxelHeight());
|
||||
}
|
||||
else if (parameter.startsWith("c"))
|
||||
{
|
||||
v.setcCen((int) Double.parseDouble(parameter.replace("c", "")));
|
||||
v.sendMessage(ChatColor.AQUA + "Cylinder origin set to: " + v.getcCen());
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.cylinder";
|
||||
}
|
||||
}
|
108
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscBrush.java
Normale Datei
108
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscBrush.java
Normale Datei
@ -0,0 +1,108 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Disc_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class DiscBrush extends PerformBrush
|
||||
{
|
||||
private double trueCircle = 0;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
public DiscBrush()
|
||||
{
|
||||
this.setName("Disc");
|
||||
}
|
||||
|
||||
/**
|
||||
* Disc executor.
|
||||
*
|
||||
* @param v
|
||||
*/
|
||||
private void disc(final SnipeData v, final Block targetBlock)
|
||||
{
|
||||
final double radiusSquared = (v.getBrushSize() + this.trueCircle) * (v.getBrushSize() + this.trueCircle);
|
||||
final Vector centerPoint = targetBlock.getLocation().toVector();
|
||||
final Vector currentPoint = centerPoint.clone();
|
||||
|
||||
for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++)
|
||||
{
|
||||
currentPoint.setX(centerPoint.getX() + x);
|
||||
for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++)
|
||||
{
|
||||
currentPoint.setZ(centerPoint.getZ() + z);
|
||||
if (centerPoint.distanceSquared(currentPoint) <= radiusSquared)
|
||||
{
|
||||
this.current.perform(this.clampY(currentPoint.getBlockX(), currentPoint.getBlockY(), currentPoint.getBlockZ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.disc(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.disc(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i].toLowerCase();
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Disc Brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b d true|false" + " -- toggles useing the true circle algorithm instead of the skinnier version with classic sniper nubs. (false is default)");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("true"))
|
||||
{
|
||||
this.trueCircle = 0.5;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode ON.");
|
||||
}
|
||||
else if (parameter.startsWith("false"))
|
||||
{
|
||||
this.trueCircle = 0;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode OFF.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.disc";
|
||||
}
|
||||
}
|
181
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscFaceBrush.java
Normale Datei
181
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DiscFaceBrush.java
Normale Datei
@ -0,0 +1,181 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Disc_Face_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class DiscFaceBrush extends PerformBrush
|
||||
{
|
||||
private double trueCircle = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public DiscFaceBrush()
|
||||
{
|
||||
this.setName("Disc Face");
|
||||
}
|
||||
|
||||
private void discUD(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
|
||||
for (int x = brushSize; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
|
||||
for (int z = brushSize; z >= 0; z--)
|
||||
{
|
||||
if ((xSquared + Math.pow(z, 2)) <= brushSizeSquared)
|
||||
{
|
||||
current.perform(targetBlock.getRelative(x, 0, z));
|
||||
current.perform(targetBlock.getRelative(x, 0, -z));
|
||||
current.perform(targetBlock.getRelative(-x, 0, z));
|
||||
current.perform(targetBlock.getRelative(-x, 0, -z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void discNS(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
|
||||
for (int x = brushSize; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
for (int y = brushSize; y >= 0; y--)
|
||||
{
|
||||
if ((xSquared + Math.pow(y, 2)) <= brushSizeSquared)
|
||||
{
|
||||
current.perform(targetBlock.getRelative(x, y, 0));
|
||||
current.perform(targetBlock.getRelative(x, -y, 0));
|
||||
current.perform(targetBlock.getRelative(-x, y, 0));
|
||||
current.perform(targetBlock.getRelative(-x, -y, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void discEW(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
|
||||
for (int x = brushSize; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
for (int y = brushSize; y >= 0; y--)
|
||||
{
|
||||
if ((xSquared + Math.pow(y, 2)) <= brushSizeSquared)
|
||||
{
|
||||
current.perform(targetBlock.getRelative(0, x, y));
|
||||
current.perform(targetBlock.getRelative(0, x, -y));
|
||||
current.perform(targetBlock.getRelative(0, -x, y));
|
||||
current.perform(targetBlock.getRelative(0, -x, -y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void pre(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
BlockFace blockFace = getTargetBlock().getFace(this.getLastBlock());
|
||||
if (blockFace == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (blockFace)
|
||||
{
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
this.discNS(v, targetBlock);
|
||||
break;
|
||||
|
||||
case EAST:
|
||||
case WEST:
|
||||
this.discEW(v, targetBlock);
|
||||
break;
|
||||
|
||||
case UP:
|
||||
case DOWN:
|
||||
this.discUD(v, targetBlock);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.pre(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.pre(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Disc Face brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b df true -- will use a true circle algorithm instead of the skinnier version with classic sniper nubs. /b b false will switch back. (false is default)");
|
||||
return;
|
||||
}
|
||||
if (parameter.startsWith("true"))
|
||||
{
|
||||
this.trueCircle = 0.5;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode ON.");
|
||||
}
|
||||
else if (parameter.startsWith("false"))
|
||||
{
|
||||
this.trueCircle = 0;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode OFF.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.discface";
|
||||
}
|
||||
}
|
119
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DomeBrush.java
Normale Datei
119
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DomeBrush.java
Normale Datei
@ -0,0 +1,119 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Dome_Brush
|
||||
*
|
||||
* @author Gavjenks
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
public class DomeBrush extends Brush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public DomeBrush()
|
||||
{
|
||||
this.setName("Dome");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.voxel();
|
||||
vm.height();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v
|
||||
* @param targetBlock
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void generateDome(final SnipeData v, final Block targetBlock)
|
||||
{
|
||||
|
||||
if (v.getVoxelHeight() == 0)
|
||||
{
|
||||
v.sendMessage("VoxelHeight must not be 0.");
|
||||
return;
|
||||
}
|
||||
|
||||
final int absoluteHeight = Math.abs(v.getVoxelHeight());
|
||||
final boolean negative = v.getVoxelHeight() < 0;
|
||||
|
||||
final Set<Vector> changeablePositions = new HashSet<Vector>();
|
||||
|
||||
final Undo undo = new Undo();
|
||||
|
||||
final int brushSizeTimesVoxelHeight = v.getBrushSize() * absoluteHeight;
|
||||
final double stepScale = ((v.getBrushSize() * v.getBrushSize()) + brushSizeTimesVoxelHeight + brushSizeTimesVoxelHeight) / 5;
|
||||
|
||||
final double stepSize = 1 / stepScale;
|
||||
|
||||
for (double u = 0; u <= Math.PI / 2; u += stepSize)
|
||||
{
|
||||
final double y = absoluteHeight * Math.sin(u);
|
||||
for (double stepV = -Math.PI; stepV <= -(Math.PI / 2); stepV += stepSize)
|
||||
{
|
||||
final double x = v.getBrushSize() * Math.cos(u) * Math.cos(stepV);
|
||||
final double z = v.getBrushSize() * Math.cos(u) * Math.sin(stepV);
|
||||
|
||||
final double targetBlockX = targetBlock.getX() + 0.5;
|
||||
final double targetBlockZ = targetBlock.getZ() + 0.5;
|
||||
final int targetY = NumberConversions.floor(targetBlock.getY() + (negative ? -y : y));
|
||||
final int currentBlockXAdd = NumberConversions.floor(targetBlockX + x);
|
||||
final int currentBlockZAdd = NumberConversions.floor(targetBlockZ + z);
|
||||
final int currentBlockXSubtract = NumberConversions.floor(targetBlockX - x);
|
||||
final int currentBlockZSubtract = NumberConversions.floor(targetBlockZ - z);
|
||||
changeablePositions.add(new Vector(currentBlockXAdd, targetY, currentBlockZAdd));
|
||||
changeablePositions.add(new Vector(currentBlockXSubtract, targetY, currentBlockZAdd));
|
||||
changeablePositions.add(new Vector(currentBlockXAdd, targetY, currentBlockZSubtract));
|
||||
changeablePositions.add(new Vector(currentBlockXSubtract, targetY, currentBlockZSubtract));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (final Vector vector : changeablePositions)
|
||||
{
|
||||
final AsyncBlock currentTargetBlock = (AsyncBlock) vector.toLocation(this.getTargetBlock().getWorld()).getBlock();
|
||||
if (currentTargetBlock.getTypeId() != v.getVoxelId() || currentTargetBlock.getPropertyId() != v.getPropertyId())
|
||||
{
|
||||
undo.put(currentTargetBlock);
|
||||
currentTargetBlock.setTypeIdAndPropertyId(v.getVoxelId(), v.getPropertyId(), true);
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.generateDome(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.generateDome(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.dome";
|
||||
}
|
||||
}
|
173
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DrainBrush.java
Normale Datei
173
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/DrainBrush.java
Normale Datei
@ -0,0 +1,173 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
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;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Drain_Brush
|
||||
*
|
||||
* @author Gavjenks
|
||||
* @author psanker
|
||||
*/
|
||||
public class DrainBrush extends Brush
|
||||
{
|
||||
private double trueCircle = 0;
|
||||
private boolean disc = false;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public DrainBrush()
|
||||
{
|
||||
this.setName("Drain");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void drain(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
final Undo undo = new Undo();
|
||||
|
||||
if (this.disc)
|
||||
{
|
||||
for (int x = brushSize; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
|
||||
for (int y = brushSize; y >= 0; y--)
|
||||
{
|
||||
if ((xSquared + Math.pow(y, 2)) <= brushSizeSquared)
|
||||
{
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y) == BlockTypes.WATER.getInternalId() || this.getBlockIdAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y) == BlockTypes.LAVA.getInternalId())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y));
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() + y, this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), BlockTypes.AIR.getInternalId());
|
||||
}
|
||||
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y) == BlockTypes.WATER.getInternalId() || this.getBlockIdAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y) == BlockTypes.LAVA.getInternalId())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y));
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() - y, this.getTargetBlock().getX() + x, this.getTargetBlock().getY(), BlockTypes.AIR.getInternalId());
|
||||
}
|
||||
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y) == BlockTypes.WATER.getInternalId() || this.getBlockIdAt(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y) == BlockTypes.LAVA.getInternalId())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() + y));
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() + y, this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), BlockTypes.AIR.getInternalId());
|
||||
}
|
||||
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y) == BlockTypes.WATER.getInternalId() || this.getBlockIdAt(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y) == BlockTypes.LAVA.getInternalId())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), this.getTargetBlock().getZ() - y));
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() - y, this.getTargetBlock().getX() - x, this.getTargetBlock().getY(), BlockTypes.AIR.getInternalId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = (brushSize + 1) * 2; y >= 0; y--)
|
||||
{
|
||||
final double ySquared = Math.pow(y - brushSize, 2);
|
||||
|
||||
for (int x = (brushSize + 1) * 2; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x - brushSize, 2);
|
||||
|
||||
for (int z = (brushSize + 1) * 2; z >= 0; z--)
|
||||
{
|
||||
if ((xSquared + Math.pow(z - brushSize, 2) + ySquared) <= brushSizeSquared)
|
||||
{
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize, this.getTargetBlock().getZ() + y - brushSize) == BlockTypes.WATER.getInternalId() || this.getBlockIdAt(this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize, this.getTargetBlock().getZ() + y - brushSize) == BlockTypes.LAVA.getInternalId())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + z, this.getTargetBlock().getZ() + y));
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() + y - brushSize, this.getTargetBlock().getX() + x - brushSize, this.getTargetBlock().getY() + z - brushSize, BlockTypes.AIR.getInternalId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.drain(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.drain(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
|
||||
vm.custom(ChatColor.AQUA + ((this.trueCircle == 0.5) ? "True circle mode ON" : "True circle mode OFF"));
|
||||
vm.custom(ChatColor.AQUA + ((this.disc) ? "Disc drain mode ON" : "Disc drain mode OFF"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Drain Brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b drain true -- will use a true sphere algorithm instead of the skinnier version with classic sniper nubs. /b drain false will switch back. (false is default)");
|
||||
v.sendMessage(ChatColor.AQUA + "/b drain d -- toggles disc drain mode, as opposed to a ball drain mode");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("true"))
|
||||
{
|
||||
this.trueCircle = 0.5;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode ON.");
|
||||
}
|
||||
else if (parameter.startsWith("false"))
|
||||
{
|
||||
this.trueCircle = 0;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode OFF.");
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("d"))
|
||||
{
|
||||
if (this.disc)
|
||||
{
|
||||
this.disc = false;
|
||||
v.sendMessage(ChatColor.AQUA + "Disc drain mode OFF");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.disc = true;
|
||||
v.sendMessage(ChatColor.AQUA + "Disc drain mode ON");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.drain";
|
||||
}
|
||||
}
|
304
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipseBrush.java
Normale Datei
304
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipseBrush.java
Normale Datei
@ -0,0 +1,304 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Ellipse_Brush
|
||||
*
|
||||
* @author psanker
|
||||
*/
|
||||
public class EllipseBrush extends PerformBrush
|
||||
{
|
||||
private static final double TWO_PI = (2 * Math.PI);
|
||||
private static final int SCL_MIN = 1;
|
||||
private static final int SCL_MAX = 9999;
|
||||
private static final int SCL_DEFAULT = 10;
|
||||
private static final int STEPS_MIN = 1;
|
||||
private static final int STEPS_MAX = 2000;
|
||||
private static final int STEPS_DEFAULT = 200;
|
||||
private int xscl;
|
||||
private int yscl;
|
||||
private int steps;
|
||||
private double stepSize;
|
||||
private boolean fill;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public EllipseBrush()
|
||||
{
|
||||
this.setName("Ellipse");
|
||||
}
|
||||
|
||||
private void ellipse(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (double steps = 0; (steps <= TWO_PI); steps += stepSize)
|
||||
{
|
||||
final int x = (int) Math.round(this.xscl * Math.cos(steps));
|
||||
final int y = (int) Math.round(this.yscl * Math.sin(steps));
|
||||
|
||||
switch (getTargetBlock().getFace(this.getLastBlock()))
|
||||
{
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
current.perform(targetBlock.getRelative(0, x, y));
|
||||
break;
|
||||
case EAST:
|
||||
case WEST:
|
||||
current.perform(targetBlock.getRelative(x, y, 0));
|
||||
break;
|
||||
case UP:
|
||||
case DOWN:
|
||||
current.perform(targetBlock.getRelative(x, 0, y));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (steps >= TWO_PI)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid target.");
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void ellipsefill(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
int ix = this.xscl;
|
||||
int iy = this.yscl;
|
||||
|
||||
current.perform(targetBlock);
|
||||
|
||||
try
|
||||
{
|
||||
if (ix >= iy)
|
||||
{ // Need this unless you want weird holes
|
||||
for (iy = this.yscl; iy > 0; iy--)
|
||||
{
|
||||
for (double steps = 0; (steps <= TWO_PI); steps += stepSize)
|
||||
{
|
||||
final int x = (int) Math.round(ix * Math.cos(steps));
|
||||
final int y = (int) Math.round(iy * Math.sin(steps));
|
||||
|
||||
switch (getTargetBlock().getFace(this.getLastBlock()))
|
||||
{
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
current.perform(targetBlock.getRelative(0, x, y));
|
||||
break;
|
||||
case EAST:
|
||||
case WEST:
|
||||
current.perform(targetBlock.getRelative(x, y, 0));
|
||||
break;
|
||||
case UP:
|
||||
case DOWN:
|
||||
current.perform(targetBlock.getRelative(x, 0, y));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (steps >= TWO_PI)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
ix--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ix = this.xscl; ix > 0; ix--)
|
||||
{
|
||||
for (double steps = 0; (steps <= TWO_PI); steps += stepSize)
|
||||
{
|
||||
final int x = (int) Math.round(ix * Math.cos(steps));
|
||||
final int y = (int) Math.round(iy * Math.sin(steps));
|
||||
|
||||
switch (getTargetBlock().getFace(this.getLastBlock()))
|
||||
{
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
current.perform(targetBlock.getRelative(0, x, y));
|
||||
break;
|
||||
case EAST:
|
||||
case WEST:
|
||||
current.perform(targetBlock.getRelative(x, y, 0));
|
||||
break;
|
||||
case UP:
|
||||
case DOWN:
|
||||
current.perform(targetBlock.getRelative(x, 0, y));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (steps >= TWO_PI)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
iy--;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid target.");
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void execute(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
this.stepSize = (TWO_PI / this.steps);
|
||||
|
||||
if (this.fill)
|
||||
{
|
||||
this.ellipsefill(v, targetBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ellipse(v, targetBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.execute(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.execute(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
if (this.xscl < SCL_MIN || this.xscl > SCL_MAX)
|
||||
{
|
||||
this.xscl = SCL_DEFAULT;
|
||||
}
|
||||
|
||||
if (this.yscl < SCL_MIN || this.yscl > SCL_MAX)
|
||||
{
|
||||
this.yscl = SCL_DEFAULT;
|
||||
}
|
||||
|
||||
if (this.steps < STEPS_MIN || this.steps > STEPS_MAX)
|
||||
{
|
||||
this.steps = STEPS_DEFAULT;
|
||||
}
|
||||
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.AQUA + "X-size set to: " + ChatColor.DARK_AQUA + this.xscl);
|
||||
vm.custom(ChatColor.AQUA + "Y-size set to: " + ChatColor.DARK_AQUA + this.yscl);
|
||||
vm.custom(ChatColor.AQUA + "Render step number set to: " + ChatColor.DARK_AQUA + this.steps);
|
||||
if (this.fill)
|
||||
{
|
||||
vm.custom(ChatColor.AQUA + "Fill mode is enabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
vm.custom(ChatColor.AQUA + "Fill mode is disabled");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
try
|
||||
{
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Ellipse brush parameters");
|
||||
v.sendMessage(ChatColor.AQUA + "x[n]: Set X size modifier to n");
|
||||
v.sendMessage(ChatColor.AQUA + "y[n]: Set Y size modifier to n");
|
||||
v.sendMessage(ChatColor.AQUA + "t[n]: Set the amount of time steps");
|
||||
v.sendMessage(ChatColor.AQUA + "fill: Toggles fill mode");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("x"))
|
||||
{
|
||||
int tempXScale = Integer.parseInt(par[i].replace("x", ""));
|
||||
if (tempXScale < SCL_MIN || tempXScale > SCL_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Invalid X scale (" + SCL_MIN + "-" + SCL_MAX + ")");
|
||||
continue;
|
||||
}
|
||||
this.xscl = tempXScale;
|
||||
v.sendMessage(ChatColor.AQUA + "X-scale modifier set to: " + this.xscl);
|
||||
}
|
||||
else if (parameter.startsWith("y"))
|
||||
{
|
||||
int tempYScale = Integer.parseInt(par[i].replace("y", ""));
|
||||
if (tempYScale < SCL_MIN || tempYScale > SCL_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Invalid Y scale (" + SCL_MIN + "-" + SCL_MAX + ")");
|
||||
continue;
|
||||
}
|
||||
this.yscl = tempYScale;
|
||||
v.sendMessage(ChatColor.AQUA + "Y-scale modifier set to: " + this.yscl);
|
||||
}
|
||||
else if (parameter.startsWith("t"))
|
||||
{
|
||||
int tempSteps = Integer.parseInt(par[i].replace("t", ""));
|
||||
if (tempSteps < STEPS_MIN || tempSteps > STEPS_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Invalid step number (" + STEPS_MIN + "-" + STEPS_MAX + ")");
|
||||
continue;
|
||||
}
|
||||
this.steps = tempSteps;
|
||||
v.sendMessage(ChatColor.AQUA + "Render step number set to: " + this.steps);
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("fill"))
|
||||
{
|
||||
if (this.fill)
|
||||
{
|
||||
this.fill = false;
|
||||
v.sendMessage(ChatColor.AQUA + "Fill mode is disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.fill = true;
|
||||
v.sendMessage(ChatColor.AQUA + "Fill mode is enabled");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! Use the \"info\" parameter to display parameter info.");
|
||||
}
|
||||
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Incorrect parameter \"" + parameter + "\"; use the \"info\" parameter.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.ellipse";
|
||||
}
|
||||
}
|
147
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipsoidBrush.java
Normale Datei
147
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/EllipsoidBrush.java
Normale Datei
@ -0,0 +1,147 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Ellipsoid_Brush
|
||||
*
|
||||
*/
|
||||
public class EllipsoidBrush extends PerformBrush
|
||||
{
|
||||
private double xRad;
|
||||
private double yRad;
|
||||
private double zRad;
|
||||
private boolean istrue;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public EllipsoidBrush()
|
||||
{
|
||||
this.setName("Ellipsoid");
|
||||
}
|
||||
|
||||
private void execute(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
this.current.perform(targetBlock);
|
||||
double istrueoffset = istrue ? 0.5 : 0;
|
||||
int blockPositionX = targetBlock.getX();
|
||||
int blockPositionY = targetBlock.getY();
|
||||
int blockPositionZ = targetBlock.getZ();
|
||||
|
||||
for (double x = 0; x <= xRad; x++)
|
||||
{
|
||||
|
||||
final double xSquared = (x / (xRad + istrueoffset)) * (x / (xRad + istrueoffset));
|
||||
|
||||
for (double z = 0; z <= zRad; z++)
|
||||
{
|
||||
|
||||
final double zSquared = (z / (zRad + istrueoffset)) * (z / (zRad + istrueoffset));
|
||||
|
||||
for (double y = 0; y <= yRad; y++)
|
||||
{
|
||||
|
||||
final double ySquared = (y / (yRad + istrueoffset)) * (y / (yRad + istrueoffset));
|
||||
|
||||
if (xSquared + ySquared + zSquared <= 1)
|
||||
{
|
||||
this.current.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY + y), (int) (blockPositionZ + z)));
|
||||
this.current.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY + y), (int) (blockPositionZ - z)));
|
||||
this.current.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY - y), (int) (blockPositionZ + z)));
|
||||
this.current.perform(this.clampY((int) (blockPositionX + x), (int) (blockPositionY - y), (int) (blockPositionZ - z)));
|
||||
this.current.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY + y), (int) (blockPositionZ + z)));
|
||||
this.current.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY + y), (int) (blockPositionZ - z)));
|
||||
this.current.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY - y), (int) (blockPositionZ + z)));
|
||||
this.current.perform(this.clampY((int) (blockPositionX - x), (int) (blockPositionY - y), (int) (blockPositionZ - z)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.execute(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.execute(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.AQUA + "X-size set to: " + ChatColor.DARK_AQUA + this.xRad);
|
||||
vm.custom(ChatColor.AQUA + "Y-size set to: " + ChatColor.DARK_AQUA + this.yRad);
|
||||
vm.custom(ChatColor.AQUA + "Z-size set to: " + ChatColor.DARK_AQUA + this.zRad);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v)
|
||||
{
|
||||
this.istrue = false;
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
try
|
||||
{
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Ellipse brush parameters");
|
||||
v.sendMessage(ChatColor.AQUA + "x[n]: Set X radius to n");
|
||||
v.sendMessage(ChatColor.AQUA + "y[n]: Set Y radius to n");
|
||||
v.sendMessage(ChatColor.AQUA + "z[n]: Set Z radius to n");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("x"))
|
||||
{
|
||||
this.xRad = Integer.parseInt(par[i].replace("x", ""));
|
||||
v.sendMessage(ChatColor.AQUA + "X radius set to: " + this.xRad);
|
||||
}
|
||||
else if (parameter.startsWith("y"))
|
||||
{
|
||||
this.yRad = Integer.parseInt(par[i].replace("y", ""));
|
||||
v.sendMessage(ChatColor.AQUA + "Y radius set to: " + this.yRad);
|
||||
}
|
||||
else if (parameter.startsWith("z"))
|
||||
{
|
||||
this.zRad = Integer.parseInt(par[i].replace("z", ""));
|
||||
v.sendMessage(ChatColor.AQUA + "Z radius set to: " + this.zRad);
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("true"))
|
||||
{
|
||||
this.istrue = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! Use the \"info\" parameter to display parameter info.");
|
||||
}
|
||||
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Incorrect parameter \"" + parameter + "\"; use the \"info\" parameter.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.ellipsoid";
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Entity_Brush
|
||||
*
|
||||
* @author Piotr
|
||||
*/
|
||||
public class EntityBrush extends Brush
|
||||
{
|
||||
private EntityType entityType = EntityType.ZOMBIE;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public EntityBrush()
|
||||
{
|
||||
this.setName("Entity");
|
||||
}
|
||||
|
||||
private void spawn(final SnipeData v)
|
||||
{
|
||||
for (int x = 0; x < v.getBrushSize(); x++)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.getWorld().spawn(this.getLastBlock().getLocation(), this.entityType.getEntityClass());
|
||||
}
|
||||
catch (final IllegalArgumentException exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Cannot spawn entity!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.spawn(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.spawn(v);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushMessage(ChatColor.LIGHT_PURPLE + "Entity brush" + " (" + this.entityType.getName() + ")");
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
String names = "";
|
||||
|
||||
v.sendMessage(ChatColor.BLUE + "The available entity types are as follows:");
|
||||
for (final EntityType currentEntity : EntityType.values())
|
||||
{
|
||||
|
||||
names += ChatColor.AQUA + " | " + ChatColor.DARK_GREEN + currentEntity.getName();
|
||||
}
|
||||
names += ChatColor.AQUA + " |";
|
||||
v.sendMessage(names);
|
||||
}
|
||||
else
|
||||
{
|
||||
final EntityType currentEntity = EntityType.fromName(par[1]);
|
||||
if (currentEntity != null)
|
||||
{
|
||||
this.entityType = currentEntity;
|
||||
v.sendMessage(ChatColor.GREEN + "Entity type set to " + this.entityType.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "This is not a valid entity!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.entity";
|
||||
}
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class EntityRemovalBrush extends Brush
|
||||
{
|
||||
private final List<String> exemptions = new ArrayList<String>(3);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public EntityRemovalBrush()
|
||||
{
|
||||
this.setName("Entity Removal");
|
||||
|
||||
exemptions.add("org.bukkit.entity.Player");
|
||||
exemptions.add("org.bukkit.entity.Hanging");
|
||||
exemptions.add("org.bukkit.entity.NPC");
|
||||
}
|
||||
|
||||
private void radialRemoval(SnipeData v)
|
||||
{
|
||||
final Chunk targetChunk = getTargetBlock().getChunk();
|
||||
int entityCount = 0;
|
||||
int chunkCount = 0;
|
||||
|
||||
try
|
||||
{
|
||||
entityCount += removeEntities(targetChunk);
|
||||
|
||||
int radius = Math.round(v.getBrushSize() / 16);
|
||||
|
||||
for (int x = targetChunk.getX() - radius; x <= targetChunk.getX() + radius; x++)
|
||||
{
|
||||
for (int z = targetChunk.getZ() - radius; z <= targetChunk.getZ() + radius; z++)
|
||||
{
|
||||
entityCount += removeEntities(getWorld().getChunkAt(x, z));
|
||||
|
||||
chunkCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (final PatternSyntaxException pse)
|
||||
{
|
||||
pse.printStackTrace();
|
||||
v.sendMessage(ChatColor.RED + "Error in RegEx: " + ChatColor.LIGHT_PURPLE + pse.getPattern());
|
||||
v.sendMessage(ChatColor.RED + String.format("%s (Index: %d)", pse.getDescription(), pse.getIndex()));
|
||||
}
|
||||
v.sendMessage(ChatColor.GREEN + "Removed " + ChatColor.RED + entityCount + ChatColor.GREEN + " entities out of " + ChatColor.BLUE + chunkCount + ChatColor.GREEN + (chunkCount == 1 ? " chunk." : " chunks."));
|
||||
}
|
||||
|
||||
private int removeEntities(Chunk chunk) throws PatternSyntaxException
|
||||
{
|
||||
int entityCount = 0;
|
||||
|
||||
for (Entity entity : chunk.getEntities())
|
||||
{
|
||||
if (isClassInExemptionList(entity.getClass()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
entity.remove();
|
||||
entityCount++;
|
||||
}
|
||||
|
||||
return entityCount;
|
||||
}
|
||||
|
||||
private boolean isClassInExemptionList(Class<? extends Entity> entityClass) throws PatternSyntaxException
|
||||
{
|
||||
// Create a list of superclasses and interfaces implemented by the current entity type
|
||||
final List<String> entityClassHierarchy = new ArrayList<String>();
|
||||
|
||||
Class<?> currentClass = entityClass;
|
||||
while (currentClass != null && !currentClass.equals(Object.class))
|
||||
{
|
||||
entityClassHierarchy.add(currentClass.getCanonicalName());
|
||||
|
||||
for (final Class<?> intrf : currentClass.getInterfaces())
|
||||
{
|
||||
entityClassHierarchy.add(intrf.getCanonicalName());
|
||||
}
|
||||
|
||||
currentClass = currentClass.getSuperclass();
|
||||
}
|
||||
|
||||
for (final String exemptionPattern : exemptions)
|
||||
{
|
||||
for (final String typeName : entityClassHierarchy)
|
||||
{
|
||||
if (typeName.matches(exemptionPattern))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void arrow(SnipeData v)
|
||||
{
|
||||
this.radialRemoval(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void powder(SnipeData v)
|
||||
{
|
||||
this.radialRemoval(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Message vm)
|
||||
{
|
||||
vm.brushName(getName());
|
||||
|
||||
final StringBuilder exemptionsList = new StringBuilder(ChatColor.GREEN + "Exemptions: " + ChatColor.LIGHT_PURPLE);
|
||||
for (Iterator it = exemptions.iterator(); it.hasNext(); )
|
||||
{
|
||||
exemptionsList.append(it.next());
|
||||
if (it.hasNext())
|
||||
{
|
||||
exemptionsList.append(", ");
|
||||
}
|
||||
}
|
||||
vm.custom(exemptionsList.toString());
|
||||
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (final String currentParam : par)
|
||||
{
|
||||
if (currentParam.startsWith("+") || currentParam.startsWith("-"))
|
||||
{
|
||||
final boolean isAddOperation = currentParam.startsWith("+");
|
||||
|
||||
// +#/-# will suppress auto-prefixing
|
||||
final String exemptionPattern = currentParam.startsWith("+#") || currentParam.startsWith("-#") ?
|
||||
currentParam.substring(2) :
|
||||
(currentParam.contains(".") ? currentParam.substring(1) : ".*." + currentParam.substring(1));
|
||||
|
||||
if (isAddOperation)
|
||||
{
|
||||
exemptions.add(exemptionPattern);
|
||||
v.sendMessage(String.format("Added %s to entity exemptions list.", exemptionPattern));
|
||||
}
|
||||
else
|
||||
{
|
||||
exemptions.remove(exemptionPattern);
|
||||
v.sendMessage(String.format("Removed %s from entity exemptions list.", exemptionPattern));
|
||||
}
|
||||
}
|
||||
|
||||
if (currentParam.equalsIgnoreCase("list-exemptions") || currentParam.equalsIgnoreCase("lex"))
|
||||
{
|
||||
for (final String exemption : exemptions)
|
||||
{
|
||||
v.sendMessage(ChatColor.LIGHT_PURPLE + exemption);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.entityremoval";
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Eraser_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class EraserBrush extends Brush
|
||||
{
|
||||
|
||||
private static final Set<Material> EXCLUSIVE_MATERIALS = EnumSet.of(
|
||||
Material.AIR, Material.STONE, Material.GRASS, Material.DIRT, Material.SAND, Material.GRAVEL, Material.SANDSTONE);
|
||||
private static final Set<Material> EXCLUSIVE_LIQUIDS = EnumSet.of(
|
||||
Material.WATER, Material.WATER, Material.LAVA, Material.LAVA);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public EraserBrush()
|
||||
{
|
||||
this.setName("Eraser");
|
||||
}
|
||||
|
||||
private void doErase(final SnipeData v, final boolean keepWater)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final int brushSizeDoubled = 2 * brushSize;
|
||||
World world = this.getTargetBlock().getWorld();
|
||||
final Undo undo = new Undo();
|
||||
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
int currentX = this.getTargetBlock().getX() - brushSize + x;
|
||||
for (int y = 0; y <= brushSizeDoubled; y++)
|
||||
{
|
||||
int currentY = this.getTargetBlock().getY() - brushSize + y;
|
||||
for (int z = brushSizeDoubled; z >= 0; z--)
|
||||
{
|
||||
int currentZ = this.getTargetBlock().getZ() - brushSize + z;
|
||||
Block currentBlock = world.getBlockAt(currentX, currentY, currentZ);
|
||||
if (EXCLUSIVE_MATERIALS.contains(currentBlock.getType())
|
||||
|| (keepWater && EXCLUSIVE_LIQUIDS.contains(currentBlock.getType())))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
undo.put(currentBlock);
|
||||
currentBlock.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.doErase(v, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.doErase(v, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.eraser";
|
||||
}
|
||||
}
|
570
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ErodeBrush.java
Normale Datei
570
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ErodeBrush.java
Normale Datei
@ -0,0 +1,570 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncWorld;
|
||||
import com.google.common.base.Objects;
|
||||
import com.martiansoftware.jsap.FlaggedOption;
|
||||
import com.martiansoftware.jsap.JSAPException;
|
||||
import com.martiansoftware.jsap.JSAPResult;
|
||||
import com.martiansoftware.jsap.UnflaggedOption;
|
||||
import com.martiansoftware.jsap.stringparsers.EnumeratedStringParser;
|
||||
import com.massivecraft.factions.P;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import com.thevoxelbox.voxelsniper.jsap.HelpJSAP;
|
||||
import com.thevoxelbox.voxelsniper.jsap.NullableIntegerStringParser;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.ChatPaginator;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/VoxelSniper#The_Erosion_Brush
|
||||
*
|
||||
* @author Piotr
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
public class ErodeBrush extends Brush
|
||||
{
|
||||
private static final Vector[] FACES_TO_CHECK = {new Vector(0, 0, 1), new Vector(0, 0, -1), new Vector(0, 1, 0), new Vector(0, -1, 0), new Vector(1, 0, 0), new Vector(-1, 0, 0)};
|
||||
private final HelpJSAP parser = new HelpJSAP("/b e", "Brush for eroding landscape.", ChatPaginator.GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH);
|
||||
private ErosionPreset currentPreset = new ErosionPreset(0, 1, 0, 1);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public ErodeBrush()
|
||||
{
|
||||
this.setName("Erode");
|
||||
|
||||
try
|
||||
{
|
||||
this.parser.registerParameter(new UnflaggedOption("preset", EnumeratedStringParser.getParser(Preset.getValuesString(";"), false), null, false, false, "Preset options: " + Preset.getValuesString(", ")));
|
||||
this.parser.registerParameter(new FlaggedOption("fill", NullableIntegerStringParser.getParser(), null, false, 'f', "fill", "Surrounding blocks required to fill the block."));
|
||||
this.parser.registerParameter(new FlaggedOption("erode", NullableIntegerStringParser.getParser(), null, false, 'e', "erode", "Surrounding air required to erode the block."));
|
||||
this.parser.registerParameter(new FlaggedOption("fillrecursion", NullableIntegerStringParser.getParser(), null, false, 'F', "fillrecursion", "Repeated fill iterations."));
|
||||
this.parser.registerParameter(new FlaggedOption("eroderecursion", NullableIntegerStringParser.getParser(), null, false, 'E', "eroderecursion", "Repeated erode iterations."));
|
||||
}
|
||||
catch (JSAPException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param result
|
||||
* @param player
|
||||
* @param helpJSAP
|
||||
* @return if a message was sent.
|
||||
*/
|
||||
public static boolean sendHelpOrErrorMessageToPlayer(final JSAPResult result, final Player player, final HelpJSAP helpJSAP)
|
||||
{
|
||||
final List<String> output = helpJSAP.writeHelpOrErrorMessageIfRequired(result);
|
||||
if (!output.isEmpty())
|
||||
{
|
||||
for (final String string : output)
|
||||
{
|
||||
player.sendMessage(string);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.erosion(v, this.currentPreset);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void erosion(final SnipeData v, final ErosionPreset erosionPreset)
|
||||
{
|
||||
|
||||
final BlockChangeTracker blockChangeTracker = new BlockChangeTracker(this.getTargetBlock().getWorld());
|
||||
|
||||
final Vector targetBlockVector = this.getTargetBlock().getLocation().toVector();
|
||||
|
||||
for (int i = 0; i < erosionPreset.getErosionRecursion(); ++i)
|
||||
{
|
||||
erosionIteration(v, erosionPreset, blockChangeTracker, targetBlockVector);
|
||||
}
|
||||
|
||||
for (int i = 0; i < erosionPreset.getFillRecursion(); ++i)
|
||||
{
|
||||
fillIteration(v, erosionPreset, blockChangeTracker, targetBlockVector);
|
||||
}
|
||||
|
||||
final Undo undo = new Undo();
|
||||
for (final BlockWrapper blockWrapper : blockChangeTracker.getAll())
|
||||
{
|
||||
undo.put(blockWrapper.getBlock());
|
||||
blockWrapper.getBlock().setTypeIdAndPropertyId(blockWrapper.getMaterial().getId(), blockWrapper.getPropertyId(), true);
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
private void fillIteration(final SnipeData v, final ErosionPreset erosionPreset, final BlockChangeTracker blockChangeTracker, final Vector targetBlockVector)
|
||||
{
|
||||
final int currentIteration = blockChangeTracker.nextIteration();
|
||||
for (int x = this.getTargetBlock().getX() - v.getBrushSize(); x <= this.getTargetBlock().getX() + v.getBrushSize(); ++x)
|
||||
{
|
||||
for (int z = this.getTargetBlock().getZ() - v.getBrushSize(); z <= this.getTargetBlock().getZ() + v.getBrushSize(); ++z)
|
||||
{
|
||||
for (int y = this.getTargetBlock().getY() - v.getBrushSize(); y <= this.getTargetBlock().getY() + v.getBrushSize(); ++y)
|
||||
{
|
||||
final Vector currentPosition = new Vector(x, y, z);
|
||||
if (currentPosition.isInSphere(targetBlockVector, v.getBrushSize()))
|
||||
{
|
||||
final BlockWrapper currentBlock = blockChangeTracker.get(currentPosition, currentIteration);
|
||||
|
||||
if (!(currentBlock.isEmpty() || currentBlock.isLiquid()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
final Map<BlockWrapper, Integer> blockCount = new HashMap<BlockWrapper, Integer>();
|
||||
|
||||
for (final Vector vector : ErodeBrush.FACES_TO_CHECK)
|
||||
{
|
||||
final Vector relativePosition = currentPosition.clone().add(vector);
|
||||
final BlockWrapper relativeBlock = blockChangeTracker.get(relativePosition, currentIteration);
|
||||
|
||||
if (!(relativeBlock.isEmpty() || relativeBlock.isLiquid()))
|
||||
{
|
||||
count++;
|
||||
final BlockWrapper typeBlock = new BlockWrapper(null, relativeBlock.getMaterial(), relativeBlock.getPropertyId());
|
||||
if (blockCount.containsKey(typeBlock))
|
||||
{
|
||||
blockCount.put(typeBlock, blockCount.get(typeBlock) + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
blockCount.put(typeBlock, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlockWrapper currentMaterial = new BlockWrapper(null, Material.AIR, 0);
|
||||
int amount = 0;
|
||||
|
||||
for (final BlockWrapper wrapper : blockCount.keySet())
|
||||
{
|
||||
final Integer currentCount = blockCount.get(wrapper);
|
||||
if (amount <= currentCount)
|
||||
{
|
||||
currentMaterial = wrapper;
|
||||
amount = currentCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= erosionPreset.getFillFaces())
|
||||
{
|
||||
blockChangeTracker.put(currentPosition, new BlockWrapper(currentBlock.getBlock(), currentMaterial.getMaterial(), currentMaterial.getPropertyId()), currentIteration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void erosionIteration(final SnipeData v, final ErosionPreset erosionPreset, final BlockChangeTracker blockChangeTracker, final Vector targetBlockVector)
|
||||
{
|
||||
final int currentIteration = blockChangeTracker.nextIteration();
|
||||
for (int x = this.getTargetBlock().getX() - v.getBrushSize(); x <= this.getTargetBlock().getX() + v.getBrushSize(); ++x)
|
||||
{
|
||||
for (int z = this.getTargetBlock().getZ() - v.getBrushSize(); z <= this.getTargetBlock().getZ() + v.getBrushSize(); ++z)
|
||||
{
|
||||
for (int y = this.getTargetBlock().getY() - v.getBrushSize(); y <= this.getTargetBlock().getY() + v.getBrushSize(); ++y)
|
||||
{
|
||||
final Vector currentPosition = new Vector(x, y, z);
|
||||
if (currentPosition.isInSphere(targetBlockVector, v.getBrushSize()))
|
||||
{
|
||||
final BlockWrapper currentBlock = blockChangeTracker.get(currentPosition, currentIteration);
|
||||
|
||||
if (currentBlock.isEmpty() || currentBlock.isLiquid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (final Vector vector : ErodeBrush.FACES_TO_CHECK)
|
||||
{
|
||||
final Vector relativePosition = currentPosition.clone().add(vector);
|
||||
final BlockWrapper relativeBlock = blockChangeTracker.get(relativePosition, currentIteration);
|
||||
|
||||
if (relativeBlock.isEmpty() || relativeBlock.isLiquid())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= erosionPreset.getErosionFaces())
|
||||
{
|
||||
blockChangeTracker.put(currentPosition, new BlockWrapper(currentBlock.getBlock(), Material.AIR, 0), currentIteration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.erosion(v, this.currentPreset.getInverted());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.custom(ChatColor.AQUA + "Erosion minimum exposed faces set to " + this.currentPreset.getErosionFaces());
|
||||
vm.custom(ChatColor.BLUE + "Fill minumum touching faces set to " + this.currentPreset.getFillFaces());
|
||||
vm.custom(ChatColor.DARK_BLUE + "Erosion recursion amount set to " + this.currentPreset.getErosionRecursion());
|
||||
vm.custom(ChatColor.DARK_GREEN + "Fill recursion amount set to " + this.currentPreset.getFillRecursion());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
JSAPResult result = this.parser.parse(Arrays.copyOfRange(par, 1, par.length));
|
||||
|
||||
if (sendHelpOrErrorMessageToPlayer(result, v.owner().getPlayer(), this.parser))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.getString("preset") != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.currentPreset = Preset.valueOf(result.getString("preset").toUpperCase()).getPreset();
|
||||
v.getVoxelMessage().brushMessage("Brush preset set to " + result.getString("preset"));
|
||||
return;
|
||||
}
|
||||
catch (final IllegalArgumentException exception)
|
||||
{
|
||||
v.getVoxelMessage().brushMessage("No such preset.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ErosionPreset currentPresetBackup = this.currentPreset;
|
||||
|
||||
if (result.getObject("fill") != null)
|
||||
{
|
||||
this.currentPreset = new ErosionPreset(this.currentPreset.getErosionFaces(), this.currentPreset.getErosionRecursion(), result.getInt("fill"), this.currentPreset.getFillRecursion());
|
||||
}
|
||||
|
||||
if (result.getObject("erode") != null)
|
||||
{
|
||||
this.currentPreset = new ErosionPreset(result.getInt("erode"), this.currentPreset.getErosionRecursion(), this.currentPreset.getFillFaces(), this.currentPreset.getFillRecursion());
|
||||
}
|
||||
|
||||
if (result.getObject("fillrecursion") != null)
|
||||
{
|
||||
this.currentPreset = new ErosionPreset(this.currentPreset.getErosionFaces(), this.currentPreset.getErosionRecursion(), this.currentPreset.getFillFaces(), result.getInt("fillrecursion"));
|
||||
}
|
||||
|
||||
if (result.getObject("eroderecursion") != null)
|
||||
{
|
||||
this.currentPreset = new ErosionPreset(this.currentPreset.getErosionFaces(), result.getInt("eroderecursion"), this.currentPreset.getFillFaces(), this.currentPreset.getFillRecursion());
|
||||
}
|
||||
|
||||
if (!currentPreset.equals(currentPresetBackup))
|
||||
{
|
||||
if (currentPreset.getErosionFaces() != currentPresetBackup.getErosionFaces())
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Erosion faces set to: " + ChatColor.WHITE + currentPreset.getErosionFaces());
|
||||
}
|
||||
if (currentPreset.getFillFaces() != currentPresetBackup.getFillFaces())
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Fill faces set to: " + ChatColor.WHITE + currentPreset.getFillFaces());
|
||||
}
|
||||
if (currentPreset.getErosionRecursion() != currentPresetBackup.getErosionRecursion())
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Erosion recursions set to: " + ChatColor.WHITE + currentPreset.getErosionRecursion());
|
||||
}
|
||||
if (currentPreset.getFillRecursion() != currentPresetBackup.getFillRecursion())
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Fill recursions set to: " + ChatColor.WHITE + currentPreset.getFillRecursion());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
private enum Preset
|
||||
{
|
||||
MELT(new ErosionPreset(2, 1, 5, 1)), FILL(new ErosionPreset(5, 1, 2, 1)), SMOOTH(new ErosionPreset(3, 1, 3, 1)), LIFT(new ErosionPreset(6, 0, 1, 1)), FLOATCLEAN(new ErosionPreset(6, 1, 6, 1));
|
||||
private ErosionPreset preset;
|
||||
|
||||
Preset(final ErosionPreset preset)
|
||||
{
|
||||
this.preset = preset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a concat string of all options.
|
||||
*
|
||||
* @param seperator Seperator for delimiting entries.
|
||||
* @return
|
||||
*/
|
||||
public static String getValuesString(String seperator)
|
||||
{
|
||||
String valuesString = "";
|
||||
|
||||
boolean delimiterHelper = true;
|
||||
for (final Preset preset : Preset.values())
|
||||
{
|
||||
if (delimiterHelper)
|
||||
{
|
||||
delimiterHelper = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
valuesString += seperator;
|
||||
}
|
||||
valuesString += preset.name();
|
||||
}
|
||||
return valuesString;
|
||||
}
|
||||
|
||||
public ErosionPreset getPreset()
|
||||
{
|
||||
return this.preset;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
private static final class BlockChangeTracker
|
||||
{
|
||||
private final Map<Integer, Map<Vector, BlockWrapper>> blockChanges;
|
||||
private final Map<Vector, BlockWrapper> flatChanges;
|
||||
private final AsyncWorld world;
|
||||
private int nextIterationId = 0;
|
||||
|
||||
public BlockChangeTracker(final AsyncWorld world)
|
||||
{
|
||||
this.blockChanges = new HashMap<Integer, Map<Vector, BlockWrapper>>();
|
||||
this.flatChanges = new HashMap<Vector, BlockWrapper>();
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public BlockWrapper get(final Vector position, final int iteration)
|
||||
{
|
||||
BlockWrapper changedBlock = null;
|
||||
|
||||
for (int i = iteration - 1; i >= 0; --i)
|
||||
{
|
||||
if (this.blockChanges.containsKey(i) && this.blockChanges.get(i).containsKey(position))
|
||||
{
|
||||
changedBlock = this.blockChanges.get(i).get(position);
|
||||
return changedBlock;
|
||||
}
|
||||
}
|
||||
|
||||
changedBlock = new BlockWrapper((AsyncBlock) position.toLocation(this.world).getBlock());
|
||||
|
||||
return changedBlock;
|
||||
}
|
||||
|
||||
public Collection<BlockWrapper> getAll()
|
||||
{
|
||||
return this.flatChanges.values();
|
||||
}
|
||||
|
||||
public int nextIteration()
|
||||
{
|
||||
return this.nextIterationId++;
|
||||
}
|
||||
|
||||
public void put(final Vector position, final BlockWrapper changedBlock, final int iteration)
|
||||
{
|
||||
if (!this.blockChanges.containsKey(iteration))
|
||||
{
|
||||
this.blockChanges.put(iteration, new HashMap<Vector, BlockWrapper>());
|
||||
}
|
||||
|
||||
this.blockChanges.get(iteration).put(position, changedBlock);
|
||||
this.flatChanges.put(position, changedBlock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
private static final class BlockWrapper
|
||||
{
|
||||
|
||||
private final AsyncBlock block;
|
||||
private final Material material;
|
||||
private final int data;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public BlockWrapper(final AsyncBlock block)
|
||||
{
|
||||
this.block = block;
|
||||
this.data = block.getPropertyId();
|
||||
this.material = block.getType();
|
||||
}
|
||||
|
||||
public BlockWrapper(final AsyncBlock block, final Material material, final int data)
|
||||
{
|
||||
this.block = block;
|
||||
this.material = material;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the block
|
||||
*/
|
||||
public AsyncBlock getBlock()
|
||||
{
|
||||
return this.block;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the data
|
||||
*/
|
||||
public int getPropertyId()
|
||||
{
|
||||
return this.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the material
|
||||
*/
|
||||
public Material getMaterial()
|
||||
{
|
||||
return this.material;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if the block is Empty.
|
||||
*/
|
||||
public boolean isEmpty()
|
||||
{
|
||||
switch (material) {
|
||||
case AIR:
|
||||
case CAVE_AIR:
|
||||
case VOID_AIR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if the block is a Liquid.
|
||||
*/
|
||||
public boolean isLiquid()
|
||||
{
|
||||
switch (this.material)
|
||||
{
|
||||
case WATER:
|
||||
case LAVA:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
private static final class ErosionPreset
|
||||
{
|
||||
private final int erosionFaces;
|
||||
private final int erosionRecursion;
|
||||
private final int fillFaces;
|
||||
private final int fillRecursion;
|
||||
|
||||
public ErosionPreset(final int erosionFaces, final int erosionRecursion, final int fillFaces, final int fillRecursion)
|
||||
{
|
||||
this.erosionFaces = erosionFaces;
|
||||
this.erosionRecursion = erosionRecursion;
|
||||
this.fillFaces = fillFaces;
|
||||
this.fillRecursion = fillRecursion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hashCode(erosionFaces, erosionRecursion, fillFaces, fillRecursion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj)
|
||||
{
|
||||
if (obj instanceof ErosionPreset)
|
||||
{
|
||||
ErosionPreset other = (ErosionPreset) obj;
|
||||
return Objects.equal(this.erosionFaces, other.erosionFaces) && Objects.equal(this.erosionRecursion, other.erosionRecursion) && Objects.equal(this.fillFaces, other.fillFaces) && Objects.equal(this.fillRecursion, other.fillRecursion);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the erosionFaces
|
||||
*/
|
||||
public int getErosionFaces()
|
||||
{
|
||||
return this.erosionFaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the erosionRecursion
|
||||
*/
|
||||
public int getErosionRecursion()
|
||||
{
|
||||
return this.erosionRecursion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the fillFaces
|
||||
*/
|
||||
public int getFillFaces()
|
||||
{
|
||||
return this.fillFaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the fillRecursion
|
||||
*/
|
||||
public int getFillRecursion()
|
||||
{
|
||||
return this.fillRecursion;
|
||||
}
|
||||
|
||||
public ErosionPreset getInverted()
|
||||
{
|
||||
return new ErosionPreset(this.fillFaces, this.fillRecursion, this.erosionFaces, this.erosionRecursion);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.erode";
|
||||
}
|
||||
}
|
223
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ExtrudeBrush.java
Normale Datei
223
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ExtrudeBrush.java
Normale Datei
@ -0,0 +1,223 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Extrude_Brush
|
||||
*
|
||||
* @author psanker
|
||||
*/
|
||||
public class ExtrudeBrush extends Brush
|
||||
{
|
||||
private double trueCircle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public ExtrudeBrush()
|
||||
{
|
||||
this.setName("Extrude");
|
||||
}
|
||||
|
||||
private void extrudeUpOrDown(final SnipeData v, boolean isUp)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
Undo undo = new Undo();
|
||||
|
||||
for (int x = -brushSize; x <= brushSize; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
for (int z = -brushSize; z <= brushSize; z++)
|
||||
{
|
||||
if ((xSquared + Math.pow(z, 2)) <= brushSizeSquared)
|
||||
{
|
||||
final int direction = (isUp ? 1 : -1);
|
||||
for (int y = 0; y < Math.abs(v.getVoxelHeight()); y++)
|
||||
{
|
||||
final int tempY = y * direction;
|
||||
undo = this.perform(
|
||||
this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + tempY, this.getTargetBlock().getZ() + z),
|
||||
this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + tempY + direction, this.getTargetBlock().getZ() + z),
|
||||
v, undo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
private void extrudeNorthOrSouth(final SnipeData v, boolean isSouth)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
Undo undo = new Undo();
|
||||
|
||||
for (int x = -brushSize; x <= brushSize; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
for (int y = -brushSize; y <= brushSize; y++)
|
||||
{
|
||||
if ((xSquared + Math.pow(y, 2)) <= brushSizeSquared)
|
||||
{
|
||||
final int direction = (isSouth) ? 1 : -1;
|
||||
for (int z = 0; z < Math.abs(v.getVoxelHeight()); z++)
|
||||
{
|
||||
final int tempZ = z * direction;
|
||||
undo = this.perform(
|
||||
this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + tempZ),
|
||||
this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + tempZ + direction),
|
||||
v, undo);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
private void extrudeEastOrWest(final SnipeData v, boolean isEast)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
Undo undo = new Undo();
|
||||
|
||||
for (int y = -brushSize; y <= brushSize; y++)
|
||||
{
|
||||
final double ySquared = Math.pow(y, 2);
|
||||
for (int z = -brushSize; z <= brushSize; z++)
|
||||
{
|
||||
if ((ySquared + Math.pow(z, 2)) <= brushSizeSquared)
|
||||
{
|
||||
final int direction = (isEast) ? 1 : -1;
|
||||
for (int x = 0; x < Math.abs(v.getVoxelHeight()); x++)
|
||||
{
|
||||
final int tempX = x * direction;
|
||||
undo = this.perform(
|
||||
this.clampY(this.getTargetBlock().getX() + tempX, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z),
|
||||
this.clampY(this.getTargetBlock().getX() + tempX + direction, this.getTargetBlock().getY() + y, this.getTargetBlock().getZ() + z),
|
||||
v, undo);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private Undo perform(final Block b1, final Block b2, final SnipeData v, final Undo undo)
|
||||
{
|
||||
if (v.getVoxelList().contains(b1.getBlockData()))
|
||||
{
|
||||
undo.put(b2);
|
||||
this.setBlockIdAt(b2.getZ(), b2.getX(), b2.getY(), this.getBlockIdAt(b1.getX(), b1.getY(), b1.getZ()));
|
||||
this.clampY(b2.getX(), b2.getY(), b2.getZ()).setPropertyId(this.clampY(b1.getX(), b1.getY(), b1.getZ()).getPropertyId());
|
||||
}
|
||||
|
||||
return undo;
|
||||
}
|
||||
|
||||
private void selectExtrudeMethod(final SnipeData v, final BlockFace blockFace, final boolean towardsUser)
|
||||
{
|
||||
if (blockFace == null || v.getVoxelHeight() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
boolean tempDirection = towardsUser;
|
||||
switch (blockFace)
|
||||
{
|
||||
case DOWN:
|
||||
tempDirection = !towardsUser;
|
||||
case UP:
|
||||
extrudeUpOrDown(v, tempDirection);
|
||||
break;
|
||||
case NORTH:
|
||||
tempDirection = !towardsUser;
|
||||
case SOUTH:
|
||||
extrudeNorthOrSouth(v, tempDirection);
|
||||
break;
|
||||
case WEST:
|
||||
tempDirection = !towardsUser;
|
||||
case EAST:
|
||||
extrudeEastOrWest(v, tempDirection);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.selectExtrudeMethod(v, this.getTargetBlock().getFace(this.getLastBlock()), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.selectExtrudeMethod(v, this.getTargetBlock().getFace(this.getLastBlock()), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.height();
|
||||
vm.voxelList();
|
||||
|
||||
vm.custom(ChatColor.AQUA + ((this.trueCircle == 0.5) ? "True circle mode ON" : "True circle mode OFF"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
try
|
||||
{
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Extrude brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b ex true -- will use a true circle algorithm instead of the skinnier version with classic sniper nubs. /b ex false will switch back. (false is default)");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("true"))
|
||||
{
|
||||
this.trueCircle = 0.5;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode ON.");
|
||||
}
|
||||
else if (parameter.startsWith("false"))
|
||||
{
|
||||
this.trueCircle = 0;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode OFF.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! Use the \"info\" parameter to display parameter info.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Incorrect parameter \"" + parameter + "\"; use the \"info\" parameter.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.extrude";
|
||||
}
|
||||
}
|
149
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FillDownBrush.java
Normale Datei
149
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FillDownBrush.java
Normale Datei
@ -0,0 +1,149 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* @author Voxel
|
||||
*/
|
||||
public class FillDownBrush extends PerformBrush
|
||||
{
|
||||
private double trueCircle = 0;
|
||||
private boolean fillLiquid = true;
|
||||
private boolean fromExisting = false;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public FillDownBrush()
|
||||
{
|
||||
this.setName("Fill Down");
|
||||
}
|
||||
|
||||
private void fillDown(final SnipeData v, final Block b)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
final Block targetBlock = this.getTargetBlock();
|
||||
for (int x = -brushSize; x <= brushSize; x++)
|
||||
{
|
||||
final double currentXSquared = Math.pow(x, 2);
|
||||
|
||||
for (int z = -brushSize; z <= brushSize; z++)
|
||||
{
|
||||
if (currentXSquared + Math.pow(z, 2) <= brushSizeSquared)
|
||||
{
|
||||
int y = 0;
|
||||
boolean found = false;
|
||||
if(this.fromExisting) {
|
||||
for(y = -v.getVoxelHeight(); y < v.getVoxelHeight(); y++) {
|
||||
final Block currentBlock = this.getWorld().getBlockAt(
|
||||
targetBlock.getX() + x,
|
||||
targetBlock.getY() + y,
|
||||
targetBlock.getZ() + z);
|
||||
if(!currentBlock.isEmpty()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) continue;
|
||||
y--;
|
||||
}
|
||||
for (; y >= -targetBlock.getY(); --y)
|
||||
{
|
||||
final AsyncBlock currentBlock = this.getWorld().getBlockAt(
|
||||
targetBlock.getX() + x,
|
||||
targetBlock.getY() + y,
|
||||
targetBlock.getZ() + z);
|
||||
if (currentBlock.isEmpty() || (fillLiquid && currentBlock.isLiquid()))
|
||||
{
|
||||
this.current.perform(currentBlock);
|
||||
} else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.fillDown(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.fillDown(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
if (par[i].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Fill Down Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b fd true -- will use a true circle algorithm.");
|
||||
v.sendMessage(ChatColor.AQUA + "/b fd false -- will switch back. (Default)");
|
||||
v.sendMessage(ChatColor.AQUA + "/b fd some -- Fills only into air.");
|
||||
v.sendMessage(ChatColor.AQUA + "/b fd all -- Fills into liquids as well. (Default)");
|
||||
v.sendMessage(ChatColor.AQUA + "/b fd -e -- Fills into only existing blocks. (Toggle)");
|
||||
return;
|
||||
}
|
||||
else if (par[i].equalsIgnoreCase("true"))
|
||||
{
|
||||
this.trueCircle = 0.5;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode ON.");
|
||||
}
|
||||
else if (par[i].equalsIgnoreCase("false"))
|
||||
{
|
||||
this.trueCircle = 0;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode OFF.");
|
||||
}
|
||||
else if (par[i].equalsIgnoreCase("all"))
|
||||
{
|
||||
this.fillLiquid = true;
|
||||
v.sendMessage(ChatColor.AQUA + "Now filling liquids as well as air.");
|
||||
}
|
||||
else if (par[i].equalsIgnoreCase("some"))
|
||||
{
|
||||
this.fillLiquid = false;
|
||||
v.setReplaceId(0);
|
||||
v.sendMessage(ChatColor.AQUA + "Now only filling air.");
|
||||
}
|
||||
else if (par[i].equalsIgnoreCase("-e"))
|
||||
{
|
||||
this.fromExisting = !this.fromExisting;
|
||||
v.sendMessage(ChatColor.AQUA + "Now filling down from " + ((this.fromExisting) ? "existing" : "all") + " blocks.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.filldown";
|
||||
}
|
||||
}
|
128
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FlatOceanBrush.java
Normale Datei
128
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/FlatOceanBrush.java
Normale Datei
@ -0,0 +1,128 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncChunk;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* @author GavJenks
|
||||
*/
|
||||
public class FlatOceanBrush extends Brush
|
||||
{
|
||||
private static final int DEFAULT_WATER_LEVEL = 29;
|
||||
private static final int DEFAULT_FLOOR_LEVEL = 8;
|
||||
private int waterLevel = DEFAULT_WATER_LEVEL;
|
||||
private int floorLevel = DEFAULT_FLOOR_LEVEL;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public FlatOceanBrush()
|
||||
{
|
||||
this.setName("FlatOcean");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void flatOcean(final AsyncChunk chunk)
|
||||
{
|
||||
for (int x = 0; x < CHUNK_SIZE; x++)
|
||||
{
|
||||
for (int z = 0; z < CHUNK_SIZE; z++)
|
||||
{
|
||||
for (int y = 0; y < chunk.getWorld().getMaxHeight(); y++)
|
||||
{
|
||||
if (y <= this.floorLevel)
|
||||
{
|
||||
chunk.getBlock(x, y, z).setType(Material.DIRT);
|
||||
}
|
||||
else if (y <= this.waterLevel)
|
||||
{
|
||||
chunk.getBlock(x, y, z).setType(Material.WATER);
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk.getBlock(x, y, z).setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.flatOcean(this.getWorld().getChunkAt(this.getTargetBlock()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.flatOcean(this.getWorld().getChunkAt(this.getTargetBlock()));
|
||||
this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ())));
|
||||
this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ() + CHUNK_SIZE)));
|
||||
this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX(), 1, this.getTargetBlock().getZ() + CHUNK_SIZE)));
|
||||
this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ() + CHUNK_SIZE)));
|
||||
this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ())));
|
||||
this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() - CHUNK_SIZE, 1, this.getTargetBlock().getZ() - CHUNK_SIZE)));
|
||||
this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX(), 1, this.getTargetBlock().getZ() - CHUNK_SIZE)));
|
||||
this.flatOcean(this.getWorld().getChunkAt(this.clampY(this.getTargetBlock().getX() + CHUNK_SIZE, 1, this.getTargetBlock().getZ() - CHUNK_SIZE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.RED + "THIS BRUSH DOES NOT UNDO");
|
||||
vm.custom(ChatColor.GREEN + "Water level set to " + this.waterLevel);
|
||||
vm.custom(ChatColor.GREEN + "Ocean floor level set to " + this.floorLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GREEN + "yo[number] to set the Level to which the water will rise.");
|
||||
v.sendMessage(ChatColor.GREEN + "yl[number] to set the Level to which the ocean floor will rise.");
|
||||
}
|
||||
if (parameter.startsWith("yo"))
|
||||
{
|
||||
int newWaterLevel = Integer.parseInt(parameter.replace("yo", ""));
|
||||
if (newWaterLevel < this.floorLevel)
|
||||
{
|
||||
newWaterLevel = this.floorLevel + 1;
|
||||
}
|
||||
this.waterLevel = newWaterLevel;
|
||||
v.sendMessage(ChatColor.GREEN + "Water Level set to " + this.waterLevel);
|
||||
}
|
||||
else if (parameter.startsWith("yl"))
|
||||
{
|
||||
int newFloorLevel = Integer.parseInt(parameter.replace("yl", ""));
|
||||
if (newFloorLevel > this.waterLevel)
|
||||
{
|
||||
newFloorLevel = this.waterLevel - 1;
|
||||
if (newFloorLevel == 0)
|
||||
{
|
||||
newFloorLevel = 1;
|
||||
this.waterLevel = 2;
|
||||
}
|
||||
}
|
||||
this.floorLevel = newFloorLevel;
|
||||
v.sendMessage(ChatColor.GREEN + "Ocean floor Level set to " + this.floorLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.flatocean";
|
||||
}
|
||||
}
|
@ -0,0 +1,781 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
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;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
// Proposal: Use /v and /vr for leave and wood material // or two more parameters -- Monofraps
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#VoxelTrees_Brush
|
||||
*
|
||||
* @author Ghost8700 @ Voxel
|
||||
*/
|
||||
public class GenerateTreeBrush extends Brush
|
||||
{
|
||||
// Tree Variables.
|
||||
private Random randGenerator = new Random();
|
||||
private ArrayList<Block> branchBlocks = new ArrayList<Block>();
|
||||
private Undo undo;
|
||||
// If these default values are edited. Remember to change default values in the default preset.
|
||||
private Material leafType = Material.OAK_LEAVES;
|
||||
private Material woodType = Material.OAK_WOOD;
|
||||
private boolean rootFloat = false;
|
||||
private int startHeight = 0;
|
||||
private int rootLength = 9;
|
||||
private int maxRoots = 2;
|
||||
private int minRoots = 1;
|
||||
private int thickness = 1;
|
||||
private int slopeChance = 40;
|
||||
private int twistChance = 5; // This is a hidden value not available through Parameters. Otherwise messy.
|
||||
private int heightMininmum = 14;
|
||||
private int heightMaximum = 18;
|
||||
private int branchLength = 8;
|
||||
private int nodeMax = 4;
|
||||
private int nodeMin = 3;
|
||||
|
||||
private int blockPositionX;
|
||||
private int blockPositionY;
|
||||
private int blockPositionZ;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public GenerateTreeBrush()
|
||||
{
|
||||
this.setName("Generate Tree");
|
||||
}
|
||||
|
||||
public boolean isLog(Material m) {
|
||||
switch (m) {
|
||||
case ACACIA_LOG:
|
||||
case BIRCH_LOG:
|
||||
case DARK_OAK_LOG:
|
||||
case JUNGLE_LOG:
|
||||
case OAK_LOG:
|
||||
case SPRUCE_LOG:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLeave(Material m) {
|
||||
switch (m) {
|
||||
case ACACIA_LEAVES:
|
||||
case BIRCH_LEAVES:
|
||||
case DARK_OAK_LEAVES:
|
||||
case JUNGLE_LEAVES:
|
||||
case OAK_LEAVES:
|
||||
case SPRUCE_LEAVES:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Branch Creation based on direction chosen from the parameters passed.
|
||||
@SuppressWarnings("deprecation")
|
||||
private void branchCreate(final int xDirection, final int zDirection)
|
||||
{
|
||||
|
||||
// Sets branch origin.
|
||||
final int originX = blockPositionX;
|
||||
final int originY = blockPositionY;
|
||||
final int originZ = blockPositionZ;
|
||||
|
||||
// Sets direction preference.
|
||||
final int xPreference = this.randGenerator.nextInt(60) + 20;
|
||||
final int zPreference = this.randGenerator.nextInt(60) + 20;
|
||||
|
||||
// Iterates according to branch length.
|
||||
for (int r = 0; r < this.branchLength; r++)
|
||||
{
|
||||
|
||||
// Alters direction according to preferences.
|
||||
if (this.randGenerator.nextInt(100) < xPreference)
|
||||
{
|
||||
blockPositionX = blockPositionX + 1 * xDirection;
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) < zPreference)
|
||||
{
|
||||
blockPositionZ = blockPositionZ + 1 * zDirection;
|
||||
}
|
||||
|
||||
// 50% chance to increase elevation every second block.
|
||||
if (Math.abs(r % 2) == 1)
|
||||
{
|
||||
blockPositionY = blockPositionY + this.randGenerator.nextInt(2);
|
||||
}
|
||||
|
||||
// Add block to undo function.
|
||||
if (!isLog(this.getBlockType(blockPositionX, blockPositionY, blockPositionZ)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX, blockPositionY, blockPositionZ));
|
||||
}
|
||||
|
||||
// Creates a branch block.
|
||||
this.clampY(blockPositionX, blockPositionY, blockPositionZ).setType(this.woodType);
|
||||
this.branchBlocks.add(this.clampY(blockPositionX, blockPositionY, blockPositionZ));
|
||||
}
|
||||
|
||||
// Resets the origin
|
||||
blockPositionX = originX;
|
||||
blockPositionY = originY;
|
||||
blockPositionZ = originZ;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void leafNodeCreate()
|
||||
{
|
||||
// Generates the node size.
|
||||
final int nodeRadius = this.randGenerator.nextInt(this.nodeMax - this.nodeMin + 1) + this.nodeMin;
|
||||
final double bSquared = Math.pow(nodeRadius + 0.5, 2);
|
||||
|
||||
// Lowers the current block in order to start at the bottom of the node.
|
||||
blockPositionY = blockPositionY - 2;
|
||||
|
||||
|
||||
for (int z = nodeRadius; z >= 0; z--)
|
||||
{
|
||||
final double zSquared = Math.pow(z, 2);
|
||||
|
||||
for (int x = nodeRadius; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
|
||||
for (int y = nodeRadius; y >= 0; y--)
|
||||
{
|
||||
if ((xSquared + Math.pow(y, 2) + zSquared) <= bSquared)
|
||||
{
|
||||
// Chance to skip creation of a block.
|
||||
if (this.randGenerator.nextInt(100) >= 30)
|
||||
{
|
||||
// If block is Air, create a leaf block.
|
||||
if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY + y, blockPositionZ + z).isEmpty())
|
||||
{
|
||||
// Adds block to undo function.
|
||||
if (!isLeave(this.getBlockType(blockPositionX + x, blockPositionY + y, blockPositionZ + z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ + z));
|
||||
}
|
||||
// Creates block.
|
||||
this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ + z).setType(this.leafType);
|
||||
}
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) >= 30)
|
||||
{
|
||||
if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY + y, blockPositionZ - z).isEmpty())
|
||||
{
|
||||
if (!isLeave(this.getBlockType(blockPositionX + x, blockPositionY + y, blockPositionZ - z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ - z));
|
||||
}
|
||||
this.clampY(blockPositionX + x, blockPositionY + y, blockPositionZ - z).setType(this.leafType);
|
||||
}
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) >= 30)
|
||||
{
|
||||
if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY + y, blockPositionZ + z).isEmpty())
|
||||
{
|
||||
if (!isLeave(this.getBlockType(blockPositionX - x, blockPositionY + y, blockPositionZ + z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ + z));
|
||||
}
|
||||
this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ + z).setType(this.leafType);
|
||||
}
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) >= 30)
|
||||
{
|
||||
if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY + y, blockPositionZ - z).isEmpty())
|
||||
{
|
||||
if (!isLeave(this.getBlockType(blockPositionX - x, blockPositionY + y, blockPositionZ - z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ - z));
|
||||
}
|
||||
this.clampY(blockPositionX - x, blockPositionY + y, blockPositionZ - z).setType(this.leafType);
|
||||
}
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) >= 30)
|
||||
{
|
||||
if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY - y, blockPositionZ + z).isEmpty())
|
||||
{
|
||||
if (!isLeave(this.getBlockType(blockPositionX + x, blockPositionY - y, blockPositionZ + z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ + z));
|
||||
}
|
||||
this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ + z).setType(this.leafType);
|
||||
}
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) >= 30)
|
||||
{
|
||||
if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY - y, blockPositionZ - z).isEmpty())
|
||||
{
|
||||
if (!isLeave(this.getBlockType(blockPositionX + x, blockPositionY - y, blockPositionZ - z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ - z));
|
||||
}
|
||||
this.clampY(blockPositionX + x, blockPositionY - y, blockPositionZ - z).setType(this.leafType);
|
||||
}
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) >= 30)
|
||||
{
|
||||
if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY - y, blockPositionZ + z).isEmpty())
|
||||
{
|
||||
if (!isLeave(this.getBlockType(blockPositionX - x, blockPositionY - y, blockPositionZ + z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ + z));
|
||||
}
|
||||
this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ + z).setType(this.leafType);
|
||||
}
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) >= 30)
|
||||
{
|
||||
if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY - y, blockPositionZ - z).isEmpty())
|
||||
{
|
||||
if (!isLeave(this.getBlockType(blockPositionX - x, blockPositionY - y, blockPositionZ - z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ - z));
|
||||
}
|
||||
this.clampY(blockPositionX - x, blockPositionY - y, blockPositionZ - z).setType(this.leafType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Code Concerning Root Generation.
|
||||
*
|
||||
* @param xDirection
|
||||
* @param zDirection
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void rootCreate(final int xDirection, final int zDirection)
|
||||
{
|
||||
// Sets Origin.
|
||||
final int originX = blockPositionX;
|
||||
final int originY = blockPositionY;
|
||||
final int originZ = blockPositionZ;
|
||||
|
||||
// Generates the number of roots to create.
|
||||
final int roots = this.randGenerator.nextInt(this.maxRoots - this.minRoots + 1) + this.minRoots;
|
||||
|
||||
// A roots preference to move along the X and Y axis.
|
||||
|
||||
|
||||
// Loops for each root to be created.
|
||||
for (int i = 0; i < roots; i++)
|
||||
{
|
||||
// Pushes the root'world starting point out from the center of the tree.
|
||||
for (int t = 0; t < this.thickness - 1; t++)
|
||||
{
|
||||
blockPositionX = blockPositionX + xDirection;
|
||||
blockPositionZ = blockPositionZ + zDirection;
|
||||
}
|
||||
|
||||
// Generate directional preference between 30% and 70%
|
||||
final int xPreference = this.randGenerator.nextInt(30) + 40;
|
||||
final int zPreference = this.randGenerator.nextInt(30) + 40;
|
||||
|
||||
for (int j = 0; j < this.rootLength; j++)
|
||||
{
|
||||
// For the purposes of this algorithm, logs aren't considered solid.
|
||||
|
||||
// If not solid then...
|
||||
// Save for undo function
|
||||
if (!isLog(this.getBlockType(blockPositionX, blockPositionY, blockPositionZ)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX, blockPositionY, blockPositionZ));
|
||||
|
||||
// Place log block.
|
||||
this.clampY(blockPositionX, blockPositionY, blockPositionZ).setType(this.woodType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If solid then...
|
||||
// End loop
|
||||
break;
|
||||
}
|
||||
|
||||
// Checks is block below is solid
|
||||
if (this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).isEmpty() || this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType() == Material.WATER || this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType() == Material.SNOW || isLog(this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType()))
|
||||
{
|
||||
// Mos down if solid.
|
||||
blockPositionY = blockPositionY - 1;
|
||||
if (this.rootFloat)
|
||||
{
|
||||
if (this.randGenerator.nextInt(100) < xPreference)
|
||||
{
|
||||
blockPositionX = blockPositionX + xDirection;
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) < zPreference)
|
||||
{
|
||||
blockPositionZ = blockPositionZ + zDirection;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If solid then move.
|
||||
if (this.randGenerator.nextInt(100) < xPreference)
|
||||
{
|
||||
blockPositionX = blockPositionX + xDirection;
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) < zPreference)
|
||||
{
|
||||
blockPositionZ = blockPositionZ + zDirection;
|
||||
}
|
||||
// Checks if new location is solid, if not then move down.
|
||||
if (this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).isEmpty() || this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType() == Material.WATER || this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType() == Material.SNOW || isLog(this.clampY(blockPositionX, blockPositionY - 1, blockPositionZ).getType()))
|
||||
{
|
||||
blockPositionY = blockPositionY - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset origin.
|
||||
blockPositionX = originX;
|
||||
blockPositionY = originY;
|
||||
blockPositionZ = originZ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void rootGen()
|
||||
{
|
||||
// Quadrant 1
|
||||
this.rootCreate(1, 1);
|
||||
|
||||
// Quadrant 2
|
||||
this.rootCreate(-1, 1);
|
||||
|
||||
// Quadrant 3
|
||||
this.rootCreate(1, -1);
|
||||
|
||||
// Quadrant 4
|
||||
this.rootCreate(-1, -1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void trunkCreate()
|
||||
{
|
||||
// Creates true circle discs of the set size using the wood type selected.
|
||||
final double bSquared = Math.pow(this.thickness + 0.5, 2);
|
||||
|
||||
for (int x = this.thickness; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
|
||||
for (int z = this.thickness; z >= 0; z--)
|
||||
{
|
||||
if ((xSquared + Math.pow(z, 2)) <= bSquared)
|
||||
{
|
||||
// If block is air, then create a block.
|
||||
if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY, blockPositionZ + z).isEmpty())
|
||||
{
|
||||
// Adds block to undo function.
|
||||
if (!isLog(this.getBlockType(blockPositionX + x, blockPositionY, blockPositionZ + z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX + x, blockPositionY, blockPositionZ + z));
|
||||
}
|
||||
// Creates block.
|
||||
this.clampY(blockPositionX + x, blockPositionY, blockPositionZ + z).setType(this.woodType);
|
||||
}
|
||||
if (this.getWorld().getBlockAt(blockPositionX + x, blockPositionY, blockPositionZ - z).isEmpty())
|
||||
{
|
||||
if (!isLog(this.getBlockType(blockPositionX + x, blockPositionY, blockPositionZ - z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX + x, blockPositionY, blockPositionZ - z));
|
||||
}
|
||||
this.clampY(blockPositionX + x, blockPositionY, blockPositionZ - z).setType(this.woodType);
|
||||
}
|
||||
if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY, blockPositionZ + z).isEmpty())
|
||||
{
|
||||
if (!isLog(this.getBlockType(blockPositionX - x, blockPositionY, blockPositionZ + z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX - x, blockPositionY, blockPositionZ + z));
|
||||
}
|
||||
this.clampY(blockPositionX - x, blockPositionY, blockPositionZ + z).setType(this.woodType);
|
||||
}
|
||||
if (this.getWorld().getBlockAt(blockPositionX - x, blockPositionY, blockPositionZ - z).isEmpty())
|
||||
{
|
||||
if (!isLog(this.getBlockType(blockPositionX - x, blockPositionY, blockPositionZ - z)))
|
||||
{
|
||||
this.undo.put(this.clampY(blockPositionX - x, blockPositionY, blockPositionZ - z));
|
||||
}
|
||||
this.clampY(blockPositionX - x, blockPositionY, blockPositionZ - z).setType(this.woodType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Code Concerning Trunk Generation
|
||||
*/
|
||||
private void trunkGen()
|
||||
{
|
||||
// Sets Origin
|
||||
final int originX = blockPositionX;
|
||||
final int originY = blockPositionY;
|
||||
final int originZ = blockPositionZ;
|
||||
|
||||
// ----------
|
||||
// Main Trunk
|
||||
// ----------
|
||||
// Sets diretional preferences.
|
||||
int xPreference = this.randGenerator.nextInt(this.slopeChance);
|
||||
int zPreference = this.randGenerator.nextInt(this.slopeChance);
|
||||
|
||||
// Sets direction.
|
||||
int xDirection = 1;
|
||||
if (this.randGenerator.nextInt(100) < 50)
|
||||
{
|
||||
xDirection = -1;
|
||||
}
|
||||
|
||||
int zDirection = 1;
|
||||
if (this.randGenerator.nextInt(100) < 50)
|
||||
{
|
||||
zDirection = -1;
|
||||
}
|
||||
|
||||
// Generates a height for trunk.
|
||||
int height = this.randGenerator.nextInt(this.heightMaximum - this.heightMininmum + 1) + this.heightMininmum;
|
||||
|
||||
for (int p = 0; p < height; p++)
|
||||
{
|
||||
if (p > 3)
|
||||
{
|
||||
if (this.randGenerator.nextInt(100) <= this.twistChance)
|
||||
{
|
||||
xDirection *= -1;
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) <= this.twistChance)
|
||||
{
|
||||
zDirection *= -1;
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) < xPreference)
|
||||
{
|
||||
blockPositionX += xDirection;
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) < zPreference)
|
||||
{
|
||||
blockPositionZ += zDirection;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates trunk section
|
||||
this.trunkCreate();
|
||||
|
||||
// Mos up for next section
|
||||
blockPositionY = blockPositionY + 1;
|
||||
}
|
||||
|
||||
// Generates branchs at top of trunk for each quadrant.
|
||||
this.branchCreate(1, 1);
|
||||
this.branchCreate(-1, 1);
|
||||
this.branchCreate(1, -1);
|
||||
this.branchCreate(-1, -1);
|
||||
|
||||
// Reset Origin for next trunk.
|
||||
blockPositionX = originX;
|
||||
blockPositionY = originY + 4;
|
||||
blockPositionZ = originZ;
|
||||
|
||||
// ---------------
|
||||
// Secondary Trunk
|
||||
// ---------------
|
||||
// Sets diretional preferences.
|
||||
xPreference = this.randGenerator.nextInt(this.slopeChance);
|
||||
zPreference = this.randGenerator.nextInt(this.slopeChance);
|
||||
|
||||
// Sets direction.
|
||||
xDirection = 1;
|
||||
if (this.randGenerator.nextInt(100) < 50)
|
||||
{
|
||||
xDirection = -1;
|
||||
}
|
||||
|
||||
zDirection = 1;
|
||||
if (this.randGenerator.nextInt(100) < 50)
|
||||
{
|
||||
zDirection = -1;
|
||||
}
|
||||
|
||||
// Generates a height for trunk.
|
||||
height = this.randGenerator.nextInt(this.heightMaximum - this.heightMininmum + 1) + this.heightMininmum;
|
||||
|
||||
if (height > 4)
|
||||
{
|
||||
for (int p = 0; p < height; p++)
|
||||
{
|
||||
if (this.randGenerator.nextInt(100) <= this.twistChance)
|
||||
{
|
||||
xDirection *= -1;
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) <= this.twistChance)
|
||||
{
|
||||
zDirection *= -1;
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) < xPreference)
|
||||
{
|
||||
blockPositionX = blockPositionX + 1 * xDirection;
|
||||
}
|
||||
if (this.randGenerator.nextInt(100) < zPreference)
|
||||
{
|
||||
blockPositionZ = blockPositionZ + 1 * zDirection;
|
||||
}
|
||||
|
||||
// Creates a trunk section
|
||||
this.trunkCreate();
|
||||
|
||||
// Mos up for next section
|
||||
blockPositionY = blockPositionY + 1;
|
||||
}
|
||||
|
||||
// Generates branchs at top of trunk for each quadrant.
|
||||
this.branchCreate(1, 1);
|
||||
this.branchCreate(-1, 1);
|
||||
this.branchCreate(1, -1);
|
||||
this.branchCreate(-1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.undo = new Undo();
|
||||
|
||||
this.branchBlocks.clear();
|
||||
|
||||
// Sets the location variables.
|
||||
blockPositionX = this.getTargetBlock().getX();
|
||||
blockPositionY = this.getTargetBlock().getY() + this.startHeight;
|
||||
blockPositionZ = this.getTargetBlock().getZ();
|
||||
|
||||
// Generates the roots.
|
||||
this.rootGen();
|
||||
|
||||
// Generates the trunk, which also generates branches.
|
||||
this.trunkGen();
|
||||
|
||||
// Each branch block was saved in an array. This is now fed through an array.
|
||||
// This array takes each branch block and constructs a leaf node around it.
|
||||
for (final Block block : this.branchBlocks)
|
||||
{
|
||||
blockPositionX = block.getX();
|
||||
blockPositionY = block.getY();
|
||||
blockPositionZ = block.getZ();
|
||||
this.leafNodeCreate();
|
||||
}
|
||||
|
||||
// Ends the undo function and mos on.
|
||||
v.owner().storeUndo(this.undo);
|
||||
}
|
||||
|
||||
// The Powder currently does nothing extra.
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.arrow(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
try
|
||||
{
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "This brush takes the following parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "lt# - leaf type (data value)");
|
||||
v.sendMessage(ChatColor.AQUA + "wt# - wood type (data value)");
|
||||
v.sendMessage(ChatColor.AQUA + "tt# - tree thickness (whote number)");
|
||||
v.sendMessage(ChatColor.AQUA + "rfX - root float (true or false)");
|
||||
v.sendMessage(ChatColor.AQUA + "sh# - starting height (whole number)");
|
||||
v.sendMessage(ChatColor.AQUA + "rl# - root length (whole number)");
|
||||
v.sendMessage(ChatColor.AQUA + "ts# - trunk slope chance (0-100)");
|
||||
v.sendMessage(ChatColor.AQUA + "bl# - branch length (whole number)");
|
||||
v.sendMessage(ChatColor.AQUA + "info2 - more parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parameter.equalsIgnoreCase("info2"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "This brush takes the following parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "minr# - minimum roots (whole number)");
|
||||
v.sendMessage(ChatColor.AQUA + "maxr# - maximum roots (whole number)");
|
||||
v.sendMessage(ChatColor.AQUA + "minh# - minimum height (whole number)");
|
||||
v.sendMessage(ChatColor.AQUA + "maxh# - maximum height (whole number)");
|
||||
v.sendMessage(ChatColor.AQUA + "minl# - minimum leaf node size (whole number)");
|
||||
v.sendMessage(ChatColor.AQUA + "maxl# - maximum leaf node size (whole number)");
|
||||
v.sendMessage(ChatColor.AQUA + "default - restore default params");
|
||||
return;
|
||||
}
|
||||
if (parameter.startsWith("lt"))
|
||||
{ // Leaf Type
|
||||
this.leafType = BukkitAdapter.adapt(BlockTypes.parse(parameter.replace("lt", "")));
|
||||
v.sendMessage(ChatColor.BLUE + "Leaf Type set to " + this.leafType);
|
||||
}
|
||||
else if (parameter.startsWith("wt"))
|
||||
{ // Wood Type
|
||||
this.woodType = BukkitAdapter.adapt(BlockTypes.parse(parameter.replace("wt", "")));
|
||||
v.sendMessage(ChatColor.BLUE + "Wood Type set to " + this.woodType);
|
||||
}
|
||||
else if (parameter.startsWith("tt"))
|
||||
{ // Tree Thickness
|
||||
this.thickness = Integer.parseInt(parameter.replace("tt", ""));
|
||||
v.sendMessage(ChatColor.BLUE + "Thickness set to " + this.thickness);
|
||||
}
|
||||
else if (parameter.startsWith("rf"))
|
||||
{ // Root Float
|
||||
this.rootFloat = Boolean.parseBoolean(parameter.replace("rf", ""));
|
||||
v.sendMessage(ChatColor.BLUE + "Floating Roots set to " + this.rootFloat);
|
||||
}
|
||||
else if (parameter.startsWith("sh"))
|
||||
{ // Starting Height
|
||||
this.startHeight = Integer.parseInt(parameter.replace("sh", ""));
|
||||
v.sendMessage(ChatColor.BLUE + "Starting Height set to " + this.startHeight);
|
||||
}
|
||||
else if (parameter.startsWith("rl"))
|
||||
{ // Root Length
|
||||
this.rootLength = Integer.parseInt(parameter.replace("rl", ""));
|
||||
v.sendMessage(ChatColor.BLUE + "Root Length set to " + this.rootLength);
|
||||
}
|
||||
else if (parameter.startsWith("minr"))
|
||||
{ // Minimum Roots
|
||||
this.minRoots = Integer.parseInt(parameter.replace("minr", ""));
|
||||
if (this.minRoots > this.maxRoots)
|
||||
{
|
||||
this.minRoots = this.maxRoots;
|
||||
v.sendMessage(ChatColor.RED + "Minimum Roots can't exceed Maximum Roots, has been set to " + this.minRoots + " Instead!");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Minimum Roots set to " + this.minRoots);
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("maxr"))
|
||||
{ // Maximum Roots
|
||||
this.maxRoots = Integer.parseInt(parameter.replace("maxr", ""));
|
||||
if (this.minRoots > this.maxRoots)
|
||||
{
|
||||
this.maxRoots = this.minRoots;
|
||||
v.sendMessage(ChatColor.RED + "Maximum Roots can't be lower than Minimum Roots, has been set to " + this.minRoots + " Instead!");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Maximum Roots set to " + this.maxRoots);
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("ts"))
|
||||
{ // Trunk Slope Chance
|
||||
this.slopeChance = Integer.parseInt(parameter.replace("ts", ""));
|
||||
v.sendMessage(ChatColor.BLUE + "Trunk Slope set to " + this.slopeChance);
|
||||
}
|
||||
else if (parameter.startsWith("minh"))
|
||||
{ // Height Minimum
|
||||
this.heightMininmum = Integer.parseInt(parameter.replace("minh", ""));
|
||||
if (this.heightMininmum > this.heightMaximum)
|
||||
{
|
||||
this.heightMininmum = this.heightMaximum;
|
||||
v.sendMessage(ChatColor.RED + "Minimum Height exceed than Maximum Height, has been set to " + this.heightMininmum + " Instead!");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Minimum Height set to " + this.heightMininmum);
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("maxh"))
|
||||
{ // Height Maximum
|
||||
this.heightMaximum = Integer.parseInt(parameter.replace("maxh", ""));
|
||||
if (this.heightMininmum > this.heightMaximum)
|
||||
{
|
||||
this.heightMaximum = this.heightMininmum;
|
||||
v.sendMessage(ChatColor.RED + "Maximum Height can't be lower than Minimum Height, has been set to " + this.heightMaximum + " Instead!");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Maximum Roots set to " + this.heightMaximum);
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("bl"))
|
||||
{ // Branch Length
|
||||
this.branchLength = Integer.parseInt(parameter.replace("bl", ""));
|
||||
v.sendMessage(ChatColor.BLUE + "Branch Length set to " + this.branchLength);
|
||||
}
|
||||
else if (parameter.startsWith("maxl"))
|
||||
{ // Leaf Node Max Size
|
||||
this.nodeMax = Integer.parseInt(parameter.replace("maxl", ""));
|
||||
v.sendMessage(ChatColor.BLUE + "Leaf Max Thickness set to " + this.nodeMax + " (Default 4)");
|
||||
}
|
||||
else if (parameter.startsWith("minl"))
|
||||
{ // Leaf Node Min Size
|
||||
this.nodeMin = Integer.parseInt(parameter.replace("minl", ""));
|
||||
v.sendMessage(ChatColor.BLUE + "Leaf Min Thickness set to " + this.nodeMin + " (Default 3)");
|
||||
|
||||
// -------
|
||||
// Presets
|
||||
// -------
|
||||
}
|
||||
else if (parameter.startsWith("default"))
|
||||
{ // Default settings.
|
||||
this.leafType = Material.OAK_LEAVES;
|
||||
this.woodType = Material.OAK_WOOD;
|
||||
this.rootFloat = false;
|
||||
this.startHeight = 0;
|
||||
this.rootLength = 9;
|
||||
this.maxRoots = 2;
|
||||
this.minRoots = 1;
|
||||
this.thickness = 1;
|
||||
this.slopeChance = 40;
|
||||
this.heightMininmum = 14;
|
||||
this.heightMaximum = 18;
|
||||
this.branchLength = 8;
|
||||
this.nodeMax = 4;
|
||||
this.nodeMin = 3;
|
||||
v.sendMessage(ChatColor.GOLD + "Brush reset to default parameters.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! \"" + par[i] + "\" is not a valid statement. Please use the 'info' parameter to display parameter info.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.generatetree";
|
||||
}
|
||||
}
|
226
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/HeatRayBrush.java
Normale Datei
226
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/HeatRayBrush.java
Normale Datei
@ -0,0 +1,226 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
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;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.bukkit.util.noise.PerlinNoiseGenerator;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Heat_Ray
|
||||
*
|
||||
* @author Gavjenks
|
||||
*/
|
||||
public class HeatRayBrush extends Brush
|
||||
{
|
||||
|
||||
/**
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
// private enum FlameableBlock
|
||||
// {
|
||||
// WOOD(Material.WOOD), SAPLING(Material.SAPLING), LOG(Material.LOG), LEAVES(Material.LEAVES), SPONGE(Material.SPONGE), WEB(Material.WEB), LONG_GRASS(Material.LONG_GRASS), DEAD_BUSH(Material.DEAD_BUSH), WOOL(Material.WOOL), YELLOW_FLOWER(Material.YELLOW_FLOWER), RED_ROSE(Material.RED_ROSE), TORCH(Material.TORCH), FIRE(Material.FIRE), WOOD_STAIRS(Material.WOOD_STAIRS), CROPS(Material.CROPS), SIGN_POST(Material.SIGN_POST), WOODEN_DOOR(Material.WOODEN_DOOR), LADDER(Material.LADDER), WALL_SIGN(Material.WALL_SIGN), WOOD_PLATE(Material.WOOD_PLATE), SNOW(Material.SNOW), ICE(Material.ICE), SUGAR_CANE_BLOCK(Material.SUGAR_CANE_BLOCK), FENCE(Material.FENCE), TRAP_DOOR(Material.TRAP_DOOR), VINE(Material.VINE), FENCE_GATE(Material.FENCE_GATE), WATER_LILLY(Material.WATER_LILY);
|
||||
//
|
||||
// private Material material;
|
||||
//
|
||||
// FlameableBlock(final Material material)
|
||||
// {
|
||||
// this.material = material;
|
||||
// }
|
||||
// }
|
||||
|
||||
private static final double REQUIRED_OBSIDIAN_DENSITY = 0.6;
|
||||
private static final double REQUIRED_COBBLE_DENSITY = 0.5;
|
||||
private static final double REQUIRED_FIRE_DENSITY = -0.25;
|
||||
private static final double REQUIRED_AIR_DENSITY = 0;
|
||||
|
||||
private static final ArrayList<Material> FLAMABLE_BLOCKS = new ArrayList<Material>();
|
||||
|
||||
private int octaves = 5;
|
||||
private double frequency = 1;
|
||||
|
||||
private double amplitude = 0.3;
|
||||
|
||||
static
|
||||
{
|
||||
for (Material m : Material.values()) {
|
||||
if (!m.isLegacy() && m.isBlock() && m.isFlammable()) {
|
||||
FLAMABLE_BLOCKS.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
public HeatRayBrush()
|
||||
{
|
||||
this.setName("Heat Ray");
|
||||
}
|
||||
|
||||
/**
|
||||
* Heat Ray executer.
|
||||
*
|
||||
* @param v
|
||||
*/
|
||||
public final void heatRay(final SnipeData v)
|
||||
{
|
||||
final PerlinNoiseGenerator generator = new PerlinNoiseGenerator(new Random());
|
||||
|
||||
final Vector targetLocation = this.getTargetBlock().getLocation().toVector();
|
||||
final Location currentLocation = new Location(this.getTargetBlock().getWorld(), 0, 0, 0);
|
||||
final Undo undo = new Undo();
|
||||
Block currentBlock;
|
||||
|
||||
for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--)
|
||||
{
|
||||
currentLocation.setX(this.getTargetBlock().getX() + x);
|
||||
currentLocation.setY(this.getTargetBlock().getY() + y);
|
||||
currentLocation.setZ(this.getTargetBlock().getZ() + z);
|
||||
|
||||
if (currentLocation.toVector().isInSphere(targetLocation, v.getBrushSize()))
|
||||
{
|
||||
currentBlock = currentLocation.getBlock();
|
||||
if (currentBlock == null || currentBlock.getType() == Material.CHEST)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentBlock.isLiquid())
|
||||
{
|
||||
undo.put(currentBlock);
|
||||
currentBlock.setType(Material.AIR);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (HeatRayBrush.FLAMABLE_BLOCKS.contains(currentBlock.getType()))
|
||||
{
|
||||
undo.put(currentBlock);
|
||||
currentBlock.setType(Material.FIRE);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!currentBlock.getType().equals(Material.AIR))
|
||||
{
|
||||
final double airDensity = generator.noise(currentLocation.getX(), currentLocation.getY(), currentLocation.getZ(), this.octaves, this.frequency, this.amplitude);
|
||||
final double fireDensity = generator.noise(currentLocation.getX(), currentLocation.getY(), currentLocation.getZ(), this.octaves, this.frequency, this.amplitude);
|
||||
final double cobbleDensity = generator.noise(currentLocation.getX(), currentLocation.getY(), currentLocation.getZ(), this.octaves, this.frequency, this.amplitude);
|
||||
final double obsidianDensity = generator.noise(currentLocation.getX(), currentLocation.getY(), currentLocation.getZ(), this.octaves, this.frequency, this.amplitude);
|
||||
|
||||
if (obsidianDensity >= HeatRayBrush.REQUIRED_OBSIDIAN_DENSITY)
|
||||
{
|
||||
undo.put(currentBlock);
|
||||
if (currentBlock.getType() != Material.OBSIDIAN)
|
||||
{
|
||||
currentBlock.setType(Material.OBSIDIAN);
|
||||
}
|
||||
}
|
||||
else if (cobbleDensity >= HeatRayBrush.REQUIRED_COBBLE_DENSITY)
|
||||
{
|
||||
undo.put(currentBlock);
|
||||
if (currentBlock.getType() != Material.COBBLESTONE)
|
||||
{
|
||||
currentBlock.setType(Material.COBBLESTONE);
|
||||
}
|
||||
}
|
||||
else if (fireDensity >= HeatRayBrush.REQUIRED_FIRE_DENSITY)
|
||||
{
|
||||
undo.put(currentBlock);
|
||||
if (currentBlock.getType() != Material.FIRE)
|
||||
{
|
||||
currentBlock.setType(Material.FIRE);
|
||||
}
|
||||
}
|
||||
else if (airDensity >= HeatRayBrush.REQUIRED_AIR_DENSITY)
|
||||
{
|
||||
undo.put(currentBlock);
|
||||
if (!currentBlock.isEmpty())
|
||||
{
|
||||
currentBlock.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.heatRay(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.heatRay(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.GREEN + "Octaves: " + this.octaves);
|
||||
vm.custom(ChatColor.GREEN + "Amplitude: " + this.amplitude);
|
||||
vm.custom(ChatColor.GREEN + "Frequency: " + this.frequency);
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i].toLowerCase();
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Heat Ray brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b hr oct[int] -- Octaves parameter for the noise generator.");
|
||||
v.sendMessage(ChatColor.AQUA + "/b hr amp[float] -- Amplitude parameter for the noise generator.");
|
||||
v.sendMessage(ChatColor.AQUA + "/b hr freq[float] -- Frequency parameter for the noise generator.");
|
||||
}
|
||||
if (parameter.startsWith("oct"))
|
||||
{
|
||||
this.octaves = Integer.valueOf(parameter.replace("oct", ""));
|
||||
v.getVoxelMessage().custom(ChatColor.GREEN + "Octaves: " + this.octaves);
|
||||
}
|
||||
else if (parameter.startsWith("amp"))
|
||||
{
|
||||
this.amplitude = Double.valueOf(parameter.replace("amp", ""));
|
||||
v.getVoxelMessage().custom(ChatColor.GREEN + "Amplitude: " + this.amplitude);
|
||||
}
|
||||
else if (parameter.startsWith("freq"))
|
||||
{
|
||||
this.frequency = Double.valueOf(parameter.replace("freq", ""));
|
||||
v.getVoxelMessage().custom(ChatColor.GREEN + "Frequency: " + this.frequency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.heatray";
|
||||
}
|
||||
}
|
53
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/IBrush.java
Normale Datei
53
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/IBrush.java
Normale Datei
@ -0,0 +1,53 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeAction;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.event.block.Action;
|
||||
|
||||
/**
|
||||
* Brush Interface.
|
||||
*
|
||||
*/
|
||||
public interface IBrush
|
||||
{
|
||||
|
||||
/**
|
||||
* @param vm Message object
|
||||
*/
|
||||
void info(Message vm);
|
||||
|
||||
/**
|
||||
* Handles parameters passed to brushes.
|
||||
*
|
||||
* @param par Array of string containing parameters
|
||||
* @param v Snipe Data
|
||||
*/
|
||||
void parameters(String[] par, SnipeData v);
|
||||
|
||||
boolean perform(SnipeAction action, SnipeData data, AsyncBlock targetBlock, AsyncBlock lastBlock);
|
||||
|
||||
/**
|
||||
* @return The name of the Brush
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* @param name New name for the Brush
|
||||
*/
|
||||
void setName(String name);
|
||||
|
||||
/**
|
||||
* @return The name of the category the brush is in.
|
||||
*/
|
||||
String getBrushCategory();
|
||||
|
||||
/**
|
||||
* @return Permission node required to use this brush
|
||||
*/
|
||||
String getPermissionNode();
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.util.BlockIterator;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Jagged_Line_Brush
|
||||
*
|
||||
* @author Giltwist
|
||||
* @author Monofraps
|
||||
*/
|
||||
public class JaggedLineBrush extends PerformBrush
|
||||
{
|
||||
private static final Vector HALF_BLOCK_OFFSET = new Vector(0.5, 0.5, 0.5);
|
||||
private static int timesUsed = 0;
|
||||
|
||||
private static final int RECURSION_MIN = 1;
|
||||
private static final int RECURSION_DEFAULT = 3;
|
||||
private static final int RECURSION_MAX = 10;
|
||||
private static final int SPREAD_DEFAULT = 3;
|
||||
|
||||
private Random random = new Random();
|
||||
private Vector originCoords = null;
|
||||
private Vector targetCoords = new Vector();
|
||||
private int recursion = RECURSION_DEFAULT;
|
||||
private int spread = SPREAD_DEFAULT;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public JaggedLineBrush()
|
||||
{
|
||||
this.setName("Jagged Line");
|
||||
}
|
||||
|
||||
private void jaggedP(final SnipeData v)
|
||||
{
|
||||
final Vector originClone = this.originCoords.clone().add(JaggedLineBrush.HALF_BLOCK_OFFSET);
|
||||
final Vector targetClone = this.targetCoords.clone().add(JaggedLineBrush.HALF_BLOCK_OFFSET);
|
||||
|
||||
final Vector direction = targetClone.clone().subtract(originClone);
|
||||
final double length = this.targetCoords.distance(this.originCoords);
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
this.current.perform((AsyncBlock) this.targetCoords.toLocation(this.getWorld()).getBlock());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (final BlockIterator iterator = new BlockIterator(this.getWorld(), originClone, direction, 0, NumberConversions.round(length)); iterator.hasNext(); )
|
||||
{
|
||||
final Block block = iterator.next();
|
||||
for (int i = 0; i < recursion; i++)
|
||||
{
|
||||
this.current.perform(this.clampY(Math.round(block.getX() + this.random.nextInt(spread * 2) - spread), Math.round(block.getY() + this.random.nextInt(spread * 2) - spread), Math.round(block.getZ() + this.random.nextInt(spread * 2) - spread)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void arrow(final SnipeData v)
|
||||
{
|
||||
if (originCoords == null)
|
||||
{
|
||||
originCoords = new Vector();
|
||||
}
|
||||
this.originCoords = this.getTargetBlock().getLocation().toVector();
|
||||
v.sendMessage(ChatColor.DARK_PURPLE + "First point selected.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void powder(final SnipeData v)
|
||||
{
|
||||
if (originCoords == null)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Warning: You did not select a first coordinate with the arrow");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.targetCoords = this.getTargetBlock().getLocation().toVector();
|
||||
this.jaggedP(v);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.GRAY + String.format("Recursion set to: %d", this.recursion));
|
||||
vm.custom(ChatColor.GRAY + String.format("Spread set to: %d", this.spread));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (final String parameter : par)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Jagged Line Brush instructions: Right click first point with the arrow. Right click with powder to draw a jagged line to set the second point.");
|
||||
v.sendMessage(ChatColor.AQUA + "/b j r# - sets the number of recursions (default 3, must be 1-10)");
|
||||
v.sendMessage(ChatColor.AQUA + "/b j s# - sets the spread (default 3, must be 1-10)");
|
||||
return;
|
||||
}
|
||||
if (parameter.startsWith("r"))
|
||||
{
|
||||
final int temp = Integer.parseInt(parameter.substring(1));
|
||||
if (temp >= RECURSION_MIN && temp <= RECURSION_MAX)
|
||||
{
|
||||
this.recursion = temp;
|
||||
v.sendMessage(ChatColor.GREEN + "Recursion set to: " + this.recursion);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "ERROR: Recursion must be " + RECURSION_MIN + "-" + RECURSION_MAX);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("s"))
|
||||
{
|
||||
final int temp = Integer.parseInt(parameter.substring(1));
|
||||
this.spread = temp;
|
||||
v.sendMessage(ChatColor.GREEN + "Spread set to: " + this.spread);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + String.format("Exception while parsing parameter: %s", parameter));
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.jaggedline";
|
||||
}
|
||||
}
|
278
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/JockeyBrush.java
Normale Datei
278
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/JockeyBrush.java
Normale Datei
@ -0,0 +1,278 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Jockey_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
* @author Monofraps
|
||||
*/
|
||||
public class JockeyBrush extends Brush
|
||||
{
|
||||
private static final int ENTITY_STACK_LIMIT = 50;
|
||||
private JockeyType jockeyType = JockeyType.NORMAL_ALL_ENTITIES;
|
||||
private Entity jockeyedEntity = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public JockeyBrush()
|
||||
{
|
||||
this.setName("Jockey");
|
||||
}
|
||||
|
||||
private void sitOn(final SnipeData v)
|
||||
{
|
||||
final Chunk targetChunk = this.getWorld().getChunkAt(this.getTargetBlock().getLocation());
|
||||
final int targetChunkX = targetChunk.getX();
|
||||
final int targetChunkZ = targetChunk.getZ();
|
||||
|
||||
double range = Double.MAX_VALUE;
|
||||
Entity closest = null;
|
||||
|
||||
for (int x = targetChunkX - 1; x <= targetChunkX + 1; x++)
|
||||
{
|
||||
for (int y = targetChunkZ - 1; y <= targetChunkZ + 1; y++)
|
||||
{
|
||||
for (final Entity entity : this.getWorld().getChunkAt(x, y).getEntities())
|
||||
{
|
||||
if (entity.getEntityId() == v.owner().getPlayer().getEntityId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (jockeyType == JockeyType.NORMAL_PLAYER_ONLY || jockeyType == JockeyType.INVERSE_PLAYER_ONLY)
|
||||
{
|
||||
if (!(entity instanceof Player))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
final Location entityLocation = entity.getLocation();
|
||||
final double entityDistance = entityLocation.distance(v.owner().getPlayer().getLocation());
|
||||
|
||||
if (entityDistance < range)
|
||||
{
|
||||
range = entityDistance;
|
||||
closest = entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (closest != null)
|
||||
{
|
||||
final Player player = v.owner().getPlayer();
|
||||
final PlayerTeleportEvent playerTeleportEvent = new PlayerTeleportEvent(player, player.getLocation(), closest.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
|
||||
Bukkit.getPluginManager().callEvent(playerTeleportEvent);
|
||||
|
||||
if (!playerTeleportEvent.isCancelled())
|
||||
{
|
||||
if (jockeyType == JockeyType.INVERSE_PLAYER_ONLY || jockeyType == JockeyType.INVERSE_ALL_ENTITIES)
|
||||
{
|
||||
player.setPassenger(closest);
|
||||
}
|
||||
else
|
||||
{
|
||||
closest.setPassenger(player);
|
||||
jockeyedEntity = closest;
|
||||
}
|
||||
v.sendMessage(ChatColor.GREEN + "You are now saddles on entity: " + closest.getEntityId());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Could not find any entities");
|
||||
}
|
||||
}
|
||||
|
||||
private void stack(final SnipeData v)
|
||||
{
|
||||
final int brushSizeDoubled = v.getBrushSize() * 2;
|
||||
|
||||
List<Entity> nearbyEntities = v.owner().getPlayer().getNearbyEntities(brushSizeDoubled, brushSizeDoubled, brushSizeDoubled);
|
||||
Entity lastEntity = v.owner().getPlayer();
|
||||
int stackHeight = 0;
|
||||
|
||||
for (Entity entity : nearbyEntities)
|
||||
{
|
||||
if (!(stackHeight >= ENTITY_STACK_LIMIT))
|
||||
{
|
||||
if (jockeyType == JockeyType.STACK_ALL_ENTITIES)
|
||||
{
|
||||
lastEntity.setPassenger(entity);
|
||||
lastEntity = entity;
|
||||
stackHeight++;
|
||||
}
|
||||
else if (jockeyType == JockeyType.STACK_PLAYER_ONLY)
|
||||
{
|
||||
if (entity instanceof Player)
|
||||
{
|
||||
lastEntity.setPassenger(entity);
|
||||
lastEntity = entity;
|
||||
stackHeight++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().getPlayer().sendMessage("You broke stack! :O");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
if (jockeyType == JockeyType.STACK_ALL_ENTITIES || jockeyType == JockeyType.STACK_PLAYER_ONLY)
|
||||
{
|
||||
stack(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.sitOn(v);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (jockeyType == JockeyType.INVERSE_PLAYER_ONLY || jockeyType == JockeyType.INVERSE_ALL_ENTITIES)
|
||||
{
|
||||
v.owner().getPlayer().eject();
|
||||
v.owner().getPlayer().sendMessage(ChatColor.GOLD + "The guy on top of you has been ejected!");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jockeyedEntity != null)
|
||||
{
|
||||
jockeyedEntity.eject();
|
||||
jockeyedEntity = null;
|
||||
v.owner().getPlayer().sendMessage(ChatColor.GOLD + "You have been ejected!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom("Current jockey mode: " + ChatColor.GREEN + jockeyType.toString());
|
||||
vm.custom(ChatColor.GREEN + "Help: " + ChatColor.AQUA + "http://www.voxelwiki.com/minecraft/Voxelsniper#The_Jockey_Brush");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
boolean inverse = false;
|
||||
boolean playerOnly = false;
|
||||
boolean stack = false;
|
||||
|
||||
try
|
||||
{
|
||||
for (String parameter : par)
|
||||
{
|
||||
if (parameter.startsWith("-i:"))
|
||||
{
|
||||
inverse = parameter.endsWith("y");
|
||||
}
|
||||
|
||||
if (parameter.startsWith("-po:"))
|
||||
{
|
||||
playerOnly = parameter.endsWith("y");
|
||||
}
|
||||
if (parameter.startsWith("-s:"))
|
||||
{
|
||||
stack = parameter.endsWith("y");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (inverse)
|
||||
{
|
||||
if (playerOnly)
|
||||
{
|
||||
jockeyType = JockeyType.INVERSE_PLAYER_ONLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
jockeyType = JockeyType.INVERSE_ALL_ENTITIES;
|
||||
}
|
||||
}
|
||||
else if (stack)
|
||||
{
|
||||
if (playerOnly)
|
||||
{
|
||||
jockeyType = JockeyType.STACK_PLAYER_ONLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
jockeyType = JockeyType.STACK_ALL_ENTITIES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (playerOnly)
|
||||
{
|
||||
jockeyType = JockeyType.NORMAL_PLAYER_ONLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
jockeyType = JockeyType.NORMAL_ALL_ENTITIES;
|
||||
}
|
||||
}
|
||||
|
||||
v.sendMessage("Current jockey mode: " + ChatColor.GREEN + jockeyType.toString());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
v.sendMessage("Error while parsing your arguments.");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Available types of jockey modes.
|
||||
*/
|
||||
private enum JockeyType
|
||||
{
|
||||
NORMAL_ALL_ENTITIES("Normal (All)"), NORMAL_PLAYER_ONLY("Normal (Player only)"), INVERSE_ALL_ENTITIES("Inverse (All)"), INVERSE_PLAYER_ONLY("Inverse (Player only)"), STACK_ALL_ENTITIES("Stack (All)"), STACK_PLAYER_ONLY("Stack (Player only)");
|
||||
private String name;
|
||||
|
||||
JockeyType(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.jockey";
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
|
||||
/**
|
||||
* @author Gavjenks
|
||||
*/
|
||||
public class LightningBrush extends Brush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public LightningBrush()
|
||||
{
|
||||
this.setName("Lightning");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.brushMessage("Lightning Brush! Please use in moderation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.getWorld().strikeLightning(this.getTargetBlock().getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.getWorld().strikeLightning(this.getTargetBlock().getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.lightning";
|
||||
}
|
||||
}
|
103
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/LineBrush.java
Normale Datei
103
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/LineBrush.java
Normale Datei
@ -0,0 +1,103 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncWorld;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.util.BlockIterator;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Line_Brush
|
||||
*
|
||||
* @author Gavjenks
|
||||
* @author giltwist
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
public class LineBrush extends PerformBrush
|
||||
{
|
||||
private static final Vector HALF_BLOCK_OFFSET = new Vector(0.5, 0.5, 0.5);
|
||||
private Vector originCoords = null;
|
||||
private Vector targetCoords = new Vector();
|
||||
private AsyncWorld targetWorld;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public LineBrush()
|
||||
{
|
||||
this.setName("Line");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Line Brush instructions: Right click first point with the arrow. Right click with powder to draw a line to set the second point.");
|
||||
}
|
||||
}
|
||||
|
||||
private void linePowder(final SnipeData v)
|
||||
{
|
||||
final Vector originClone = this.originCoords.clone().add(LineBrush.HALF_BLOCK_OFFSET);
|
||||
final Vector targetClone = this.targetCoords.clone().add(LineBrush.HALF_BLOCK_OFFSET);
|
||||
|
||||
final Vector direction = targetClone.clone().subtract(originClone);
|
||||
final double length = this.targetCoords.distance(this.originCoords);
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
this.current.perform((AsyncBlock) this.targetCoords.toLocation(this.targetWorld).getBlock());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (final BlockIterator blockIterator = new BlockIterator(this.targetWorld, originClone, direction, 0, NumberConversions.round(length)); blockIterator.hasNext(); )
|
||||
{
|
||||
final AsyncBlock currentBlock = (AsyncBlock) blockIterator.next();
|
||||
this.current.perform(currentBlock);
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.originCoords = this.getTargetBlock().getLocation().toVector();
|
||||
this.targetWorld = this.getTargetBlock().getWorld();
|
||||
v.owner().getPlayer().sendMessage(ChatColor.DARK_PURPLE + "First point selected.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (this.originCoords == null || !this.getTargetBlock().getWorld().equals(this.targetWorld))
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "Warning: You did not select a first coordinate with the arrow");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.targetCoords = this.getTargetBlock().getLocation().toVector();
|
||||
this.linePowder(v);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.line";
|
||||
}
|
||||
}
|
312
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/MoveBrush.java
Normale Datei
312
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/MoveBrush.java
Normale Datei
@ -0,0 +1,312 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlockState;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncWorld;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Moves a selection blockPositionY a certain amount.
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Move_Brush
|
||||
*
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
public class MoveBrush extends Brush
|
||||
{
|
||||
/**
|
||||
* Saved direction.
|
||||
*/
|
||||
private final int[] moveDirections = {0, 0, 0};
|
||||
/**
|
||||
* Saved selection.
|
||||
*/
|
||||
private Selection selection = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public MoveBrush()
|
||||
{
|
||||
this.setName("Move");
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the given selection blockPositionY the amount given in direction and saves an undo for the player.
|
||||
*
|
||||
* @param v
|
||||
* @param selection
|
||||
* @param direction
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void moveSelection(final SnipeData v, final Selection selection, final int[] direction)
|
||||
{
|
||||
if (selection.getBlockStates().size() > 0)
|
||||
{
|
||||
final AsyncWorld world = selection.getBlockStates().get(0).getWorld();
|
||||
|
||||
final Undo undo = new Undo();
|
||||
final HashSet<Block> undoSet = new HashSet<Block>();
|
||||
|
||||
final Selection newSelection = new Selection();
|
||||
final Location movedLocation1 = selection.getLocation1();
|
||||
movedLocation1.add(direction[0], direction[1], direction[2]);
|
||||
final Location movedLocation2 = selection.getLocation2();
|
||||
movedLocation2.add(direction[0], direction[1], direction[2]);
|
||||
newSelection.setLocation1(movedLocation1);
|
||||
newSelection.setLocation2(movedLocation2);
|
||||
try
|
||||
{
|
||||
newSelection.calculateRegion();
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.getVoxelMessage().brushMessage("The new Selection has more blocks than the original selection. This should never happen!");
|
||||
}
|
||||
|
||||
for (final BlockState blockState : selection.getBlockStates())
|
||||
{
|
||||
undoSet.add(blockState.getBlock());
|
||||
}
|
||||
for (final BlockState blockState : newSelection.getBlockStates())
|
||||
{
|
||||
undoSet.add(blockState.getBlock());
|
||||
}
|
||||
|
||||
for (final Block block : undoSet)
|
||||
{
|
||||
undo.put(block);
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
|
||||
for (final BlockState blockState : selection.getBlockStates())
|
||||
{
|
||||
blockState.getBlock().setType(Material.AIR);
|
||||
}
|
||||
for (final AsyncBlockState blockState : selection.getBlockStates())
|
||||
{
|
||||
final AsyncBlock affectedBlock = world.getBlockAt(blockState.getX() + direction[0], blockState.getY() + direction[1], blockState.getZ() + direction[2]);
|
||||
affectedBlock.setTypeId(blockState.getTypeId());
|
||||
affectedBlock.setPropertyId(blockState.getPropertyId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
if (this.selection == null)
|
||||
{
|
||||
this.selection = new Selection();
|
||||
}
|
||||
this.selection.setLocation1(this.getTargetBlock().getLocation());
|
||||
v.getVoxelMessage().brushMessage("Point 1 set.");
|
||||
|
||||
try
|
||||
{
|
||||
if (this.selection.calculateRegion())
|
||||
{
|
||||
this.moveSelection(v, this.selection, this.moveDirections);
|
||||
this.selection = null;
|
||||
}
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (this.selection == null)
|
||||
{
|
||||
this.selection = new Selection();
|
||||
}
|
||||
this.selection.setLocation2(this.getTargetBlock().getLocation());
|
||||
v.getVoxelMessage().brushMessage("Point 2 set.");
|
||||
|
||||
try
|
||||
{
|
||||
if (this.selection.calculateRegion())
|
||||
{
|
||||
this.moveSelection(v, this.selection, this.moveDirections);
|
||||
this.selection = null;
|
||||
}
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.BLUE + "Move selection blockPositionY " + ChatColor.GOLD + "x:" + this.moveDirections[0] + " y:" + this.moveDirections[1] + " z:" + this.moveDirections[2]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
if (par[i].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.getVoxelMessage().custom(ChatColor.GOLD + this.getName() + " Parameters:");
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "/b mv x[int] -- set the x direction (positive => east)");
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "/b mv y[int] -- set the y direction (positive => up)");
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "/b mv z[int] -- set the z direction (positive => south)");
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "/b mv reset -- reset the brush (x:0 y:0 z:0)");
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "Use arrow and gunpowder to define two points.");
|
||||
}
|
||||
if (par[i].equalsIgnoreCase("reset"))
|
||||
{
|
||||
this.moveDirections[0] = 0;
|
||||
this.moveDirections[1] = 0;
|
||||
this.moveDirections[2] = 0;
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "X direction set to: " + this.moveDirections[0]);
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "Y direction set to: " + this.moveDirections[1]);
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "Z direction set to: " + this.moveDirections[2]);
|
||||
}
|
||||
if (par[i].toLowerCase().startsWith("x"))
|
||||
{
|
||||
this.moveDirections[0] = Integer.valueOf(par[i].substring(1));
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "X direction set to: " + this.moveDirections[0]);
|
||||
}
|
||||
else if (par[i].toLowerCase().startsWith("y"))
|
||||
{
|
||||
this.moveDirections[1] = Integer.valueOf(par[i].substring(1));
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "Y direction set to: " + this.moveDirections[1]);
|
||||
}
|
||||
else if (par[i].toLowerCase().startsWith("z"))
|
||||
{
|
||||
this.moveDirections[2] = Integer.valueOf(par[i].substring(1));
|
||||
v.getVoxelMessage().custom(ChatColor.AQUA + "Z direction set to: " + this.moveDirections[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selection Helper class.
|
||||
*
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
private class Selection
|
||||
{
|
||||
/**
|
||||
* Maximum amount of Blocks allowed blockPositionY the Selection.
|
||||
*/
|
||||
private static final int MAX_BLOCK_COUNT = 5000000;
|
||||
/**
|
||||
* Calculated BlockStates of the selection.
|
||||
*/
|
||||
private final ArrayList<AsyncBlockState> blockStates = new ArrayList<AsyncBlockState>();
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Location location1 = null;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Location location2 = null;
|
||||
|
||||
/**
|
||||
* Calculates region, then saves all Blocks as BlockState.
|
||||
*
|
||||
* @return boolean success.
|
||||
* @throws Exception Message to be sent to the player.
|
||||
*/
|
||||
public boolean calculateRegion() throws Exception
|
||||
{
|
||||
if (this.location1 != null && this.location2 != null)
|
||||
{
|
||||
if (this.location1.getWorld().equals(this.location2.getWorld()))
|
||||
{
|
||||
final int lowX = ((this.location1.getBlockX() <= this.location2.getBlockX()) ? this.location1.getBlockX() : this.location2.getBlockX());
|
||||
final int lowY = (this.location1.getBlockY() <= this.location2.getBlockY()) ? this.location1.getBlockY() : this.location2.getBlockY();
|
||||
final int lowZ = (this.location1.getBlockZ() <= this.location2.getBlockZ()) ? this.location1.getBlockZ() : this.location2.getBlockZ();
|
||||
final int highX = (this.location1.getBlockX() >= this.location2.getBlockX()) ? this.location1.getBlockX() : this.location2.getBlockX();
|
||||
final int highY = (this.location1.getBlockY() >= this.location2.getBlockY()) ? this.location1.getBlockY() : this.location2.getBlockY();
|
||||
final int highZ = (this.location1.getBlockZ() >= this.location2.getBlockZ()) ? this.location1.getBlockZ() : this.location2.getBlockZ();
|
||||
if (Math.abs(highX - lowX) * Math.abs(highZ - lowZ) * Math.abs(highY - lowY) > Selection.MAX_BLOCK_COUNT)
|
||||
{
|
||||
throw new Exception(ChatColor.RED + "Selection size above hardcoded limit, please use a smaller selection.");
|
||||
}
|
||||
final AsyncWorld world = (AsyncWorld) this.location1.getWorld();
|
||||
for (int y = lowY; y <= highY; y++)
|
||||
{
|
||||
for (int x = lowX; x <= highX; x++)
|
||||
{
|
||||
for (int z = lowZ; z <= highZ; z++)
|
||||
{
|
||||
this.blockStates.add(world.getBlockAt(x, y, z).getState());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayList<BlockState> calculated BlockStates of defined region.
|
||||
*/
|
||||
public ArrayList<AsyncBlockState> getBlockStates()
|
||||
{
|
||||
return this.blockStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Location
|
||||
*/
|
||||
public Location getLocation1()
|
||||
{
|
||||
return this.location1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param location1
|
||||
*/
|
||||
public void setLocation1(final Location location1)
|
||||
{
|
||||
this.location1 = location1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Location
|
||||
*/
|
||||
public Location getLocation2()
|
||||
{
|
||||
return this.location2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param location2
|
||||
*/
|
||||
public void setLocation2(final Location location2)
|
||||
{
|
||||
this.location2 = location2;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.move";
|
||||
}
|
||||
}
|
191
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OceanBrush.java
Normale Datei
191
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OceanBrush.java
Normale Datei
@ -0,0 +1,191 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncWorld;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_OCEANATOR_5000
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class OceanBrush extends Brush
|
||||
{
|
||||
private static final int WATER_LEVEL_DEFAULT = 62; // y=63 -- we are using array indices here
|
||||
private static final int WATER_LEVEL_MIN = 12;
|
||||
private static final int LOW_CUT_LEVEL = 12;
|
||||
|
||||
private int waterLevel = WATER_LEVEL_DEFAULT;
|
||||
private boolean coverFloor = false;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public OceanBrush()
|
||||
{
|
||||
this.setName("OCEANATOR 5000(tm)");
|
||||
}
|
||||
|
||||
private int getHeight(final int bx, final int bz)
|
||||
{
|
||||
for (int y = this.getWorld().getHighestBlockYAt(bx, bz); y > 0; y--)
|
||||
{
|
||||
final Material material = this.clampY(bx, y, bz).getType();
|
||||
if (material.isSolid())
|
||||
{
|
||||
return y;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v
|
||||
* @param undo
|
||||
*/
|
||||
protected final void oceanator(final SnipeData v, final Undo undo)
|
||||
{
|
||||
final AsyncWorld world = this.getWorld();
|
||||
|
||||
final int minX = (int) Math.floor((this.getTargetBlock().getX() - v.getBrushSize()));
|
||||
final int minZ = (int) Math.floor((this.getTargetBlock().getZ() - v.getBrushSize()));
|
||||
final int maxX = (int) Math.floor((this.getTargetBlock().getX() + v.getBrushSize()));
|
||||
final int maxZ = (int) Math.floor((this.getTargetBlock().getZ() + v.getBrushSize()));
|
||||
|
||||
for (int x = minX; x <= maxX; x++)
|
||||
{
|
||||
for (int z = minZ; z <= maxZ; z++)
|
||||
{
|
||||
final int currentHeight = getHeight(x, z);
|
||||
final int wLevelDiff = currentHeight - (this.waterLevel - 1);
|
||||
final int newSeaFloorLevel = ((this.waterLevel - wLevelDiff) >= LOW_CUT_LEVEL) ? this.waterLevel - wLevelDiff : LOW_CUT_LEVEL;
|
||||
|
||||
final int highestY = this.getWorld().getHighestBlockYAt(x, z);
|
||||
|
||||
// go down from highest Y block down to new sea floor
|
||||
for (int y = highestY; y > newSeaFloorLevel; y--)
|
||||
{
|
||||
final Block block = world.getBlockAt(x, y, z);
|
||||
if (!block.getType().equals(Material.AIR))
|
||||
{
|
||||
undo.put(block);
|
||||
block.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
// go down from water level to new sea level
|
||||
for (int y = this.waterLevel; y > newSeaFloorLevel; y--)
|
||||
{
|
||||
final Block block = world.getBlockAt(x, y, z);
|
||||
if (!block.getType().equals(Material.WATER))
|
||||
{
|
||||
// do not put blocks into the undo we already put into
|
||||
if (!block.getType().equals(Material.AIR))
|
||||
{
|
||||
undo.put(block);
|
||||
}
|
||||
block.setType(Material.WATER);
|
||||
}
|
||||
}
|
||||
|
||||
// cover the sea floor of required
|
||||
if (this.coverFloor && (newSeaFloorLevel < this.waterLevel))
|
||||
{
|
||||
AsyncBlock block = world.getBlockAt(x, newSeaFloorLevel, z);
|
||||
if (block.getTypeId() != v.getVoxelId())
|
||||
{
|
||||
undo.put(block);
|
||||
block.setTypeId(v.getVoxelId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
Undo undo = new Undo();
|
||||
this.oceanator(v, undo);
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
arrow(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 0; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
try
|
||||
{
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Parameters:");
|
||||
v.sendMessage(ChatColor.GREEN + "-wlevel # " + ChatColor.BLUE + "-- Sets the water level (e.g. -wlevel 64)");
|
||||
v.sendMessage(ChatColor.GREEN + "-cfloor [y|n] " + ChatColor.BLUE + "-- Enables or disables sea floor cover (e.g. -cfloor y) (Cover material will be your voxel material)");
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("-wlevel"))
|
||||
{
|
||||
if ((i + 1) >= par.length)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Missing parameter. Correct syntax: -wlevel [#] (e.g. -wlevel 64)");
|
||||
continue;
|
||||
}
|
||||
|
||||
int temp = Integer.parseInt(par[++i]);
|
||||
|
||||
if (temp <= WATER_LEVEL_MIN)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Error: Your specified water level was below 12.");
|
||||
continue;
|
||||
}
|
||||
|
||||
this.waterLevel = temp - 1;
|
||||
v.sendMessage(ChatColor.BLUE + "Water level set to " + ChatColor.GREEN + (waterLevel + 1)); // +1 since we are working with 0-based array indices
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("-cfloor") || parameter.equalsIgnoreCase("-coverfloor"))
|
||||
{
|
||||
if ((i + 1) >= par.length)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Missing parameter. Correct syntax: -cfloor [y|n] (e.g. -cfloor y)");
|
||||
continue;
|
||||
}
|
||||
|
||||
this.coverFloor = par[++i].equalsIgnoreCase("y");
|
||||
v.sendMessage(ChatColor.BLUE + String.format("Floor cover %s.", ChatColor.GREEN + (this.coverFloor ? "enabled" : "disabled")));
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + String.format("Error while parsing parameter: %s", parameter));
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.BLUE + "Water level set to " + ChatColor.GREEN + (waterLevel + 1)); // +1 since we are working with 0-based array indices
|
||||
vm.custom(ChatColor.BLUE + String.format("Floor cover %s.", ChatColor.GREEN + (this.coverFloor ? "enabled" : "disabled")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.ocean";
|
||||
}
|
||||
}
|
233
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OverlayBrush.java
Normale Datei
233
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/OverlayBrush.java
Normale Datei
@ -0,0 +1,233 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.sk89q.worldedit.blocks.BlockMaterial;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Overlay_.2F_Topsoil_Brush
|
||||
*
|
||||
* @author Gavjenks
|
||||
*/
|
||||
public class OverlayBrush extends PerformBrush
|
||||
{
|
||||
private static final int DEFAULT_DEPTH = 3;
|
||||
private int depth = DEFAULT_DEPTH;
|
||||
private boolean allBlocks = false;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public OverlayBrush()
|
||||
{
|
||||
this.setName("Overlay (Topsoil Filling)");
|
||||
}
|
||||
|
||||
private void overlay(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + 0.5, 2);
|
||||
|
||||
|
||||
for (int z = brushSize; z >= -brushSize; z--)
|
||||
{
|
||||
for (int x = brushSize; x >= -brushSize; x--)
|
||||
{
|
||||
// check if column is valid
|
||||
// column is valid if it has no solid block right above the clicked layer
|
||||
final int materialId = this.getBlockIdAt(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + 1, this.getTargetBlock().getZ() + z);
|
||||
if (isIgnoredBlock(materialId))
|
||||
{
|
||||
if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared)
|
||||
{
|
||||
for (int y = this.getTargetBlock().getY(); y > 0; y--)
|
||||
{
|
||||
// check for surface
|
||||
final int layerBlockId = this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z);
|
||||
if (!isIgnoredBlock(layerBlockId))
|
||||
{
|
||||
for (int currentDepth = y; y - currentDepth < depth; currentDepth--)
|
||||
{
|
||||
final int currentBlockId = this.getBlockIdAt(this.getTargetBlock().getX() + x, currentDepth, this.getTargetBlock().getZ() + z);
|
||||
if (isOverrideableMaterial(currentBlockId))
|
||||
{
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, currentDepth, this.getTargetBlock().getZ() + z));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private boolean isIgnoredBlock(int materialId)
|
||||
{
|
||||
BlockTypes type = BlockTypes.getFromStateId(materialId);
|
||||
switch (type) {
|
||||
case WATER:
|
||||
case LAVA:
|
||||
case CACTUS:
|
||||
return true;
|
||||
}
|
||||
BlockMaterial mat = type.getMaterial();
|
||||
return mat.isTranslucent();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private boolean isOverrideableMaterial(int materialId)
|
||||
{
|
||||
BlockMaterial mat = BlockTypes.getFromStateId(materialId).getMaterial();
|
||||
if (allBlocks && !(mat.isAir()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mat.isFragileWhenPushed() && mat.isFullCube()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void overlayTwo(final SnipeData v)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double brushSizeSquared = Math.pow(brushSize + 0.5, 2);
|
||||
final int[][] memory = new int[brushSize * 2 + 1][brushSize * 2 + 1];
|
||||
|
||||
for (int z = brushSize; z >= -brushSize; z--)
|
||||
{
|
||||
for (int x = brushSize; x >= -brushSize; x--)
|
||||
{
|
||||
boolean surfaceFound = false;
|
||||
for (int y = this.getTargetBlock().getY(); y > 0 && !surfaceFound; y--)
|
||||
{ // start scanning from the height you clicked at
|
||||
if (memory[x + brushSize][z + brushSize] != 1)
|
||||
{ // if haven't already found the surface in this column
|
||||
if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared)
|
||||
{ // if inside of the column...
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() + x, y - 1, this.getTargetBlock().getZ() + z) != 0)
|
||||
{ // if not a floating block (like one of Notch'world pools)
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() + x, y + 1, this.getTargetBlock().getZ() + z) == 0)
|
||||
{ // must start at surface... this prevents it filling stuff in if
|
||||
// you click in a wall and it starts out below surface.
|
||||
if (!this.allBlocks)
|
||||
{ // if the override parameter has not been activated, go to the switch that filters out manmade stuff.
|
||||
|
||||
BlockTypes type = BlockTypes.get(this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z));
|
||||
BlockMaterial mat = type.getMaterial();
|
||||
if (mat.isSolid() && mat.isFullCube() && !mat.hasContainer()) {
|
||||
for (int d = 1; (d < this.depth + 1); d++) {
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify
|
||||
// in parameters
|
||||
memory[x + brushSize][z + brushSize] = 1; // stop it from checking any other blocks in this vertical 1x1 column.
|
||||
}
|
||||
surfaceFound = true;
|
||||
continue;
|
||||
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int d = 1; (d < this.depth + 1); d++)
|
||||
{
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in
|
||||
// parameters
|
||||
memory[x + brushSize][z + brushSize] = 1; // stop it from checking any other blocks in this vertical 1x1 column.
|
||||
}
|
||||
surfaceFound = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.overlay(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.overlayTwo(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Overlay brush parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "d[number] (ex: d3) How many blocks deep you want to replace from the surface.");
|
||||
v.sendMessage(ChatColor.BLUE + "all (ex: /b over all) Sets the brush to overlay over ALL materials, not just natural surface ones (will no longer ignore trees and buildings). The parameter /some will set it back to default.");
|
||||
return;
|
||||
}
|
||||
if (parameter.startsWith("d"))
|
||||
{
|
||||
try {
|
||||
this.depth = Integer.parseInt(parameter.replace("d", ""));
|
||||
|
||||
if (this.depth < 1)
|
||||
{
|
||||
this.depth = 1;
|
||||
}
|
||||
|
||||
v.sendMessage(ChatColor.AQUA + "Depth set to " + this.depth);
|
||||
} catch (NumberFormatException e) {
|
||||
v.sendMessage(ChatColor.RED + "Depth isn't a number.");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("all"))
|
||||
{
|
||||
this.allBlocks = true;
|
||||
v.sendMessage(ChatColor.BLUE + "Will overlay over any block." + this.depth);
|
||||
}
|
||||
else if (parameter.startsWith("some"))
|
||||
{
|
||||
this.allBlocks = false;
|
||||
v.sendMessage(ChatColor.BLUE + "Will overlay only natural block types." + this.depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.overlay";
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.PaintingWrapper;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
|
||||
/**
|
||||
* Painting scrolling Brush.
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Painting_Picker_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class PaintingBrush extends Brush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public PaintingBrush()
|
||||
{
|
||||
this.setName("Painting");
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll painting forward.
|
||||
*
|
||||
* @param v Sniper caller
|
||||
*/
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
PaintingWrapper.paint(v.owner().getPlayer(), true, false, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll painting backwards.
|
||||
*
|
||||
* @param v Sniper caller
|
||||
*/
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
PaintingWrapper.paint(v.owner().getPlayer(), true, true, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.painting";
|
||||
}
|
||||
}
|
371
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PullBrush.java
Normale Datei
371
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PullBrush.java
Normale Datei
@ -0,0 +1,371 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* @author Piotr
|
||||
*/
|
||||
public class PullBrush extends Brush
|
||||
{
|
||||
private final HashSet<BlockWrapper> surface = new HashSet<BlockWrapper>();
|
||||
private int vh;
|
||||
private double c1 = 1;
|
||||
private double c2 = 0;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
public PullBrush()
|
||||
{
|
||||
this.setName("Soft Selection");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.height();
|
||||
vm.custom(ChatColor.AQUA + "Pinch " + (-this.c1 + 1));
|
||||
vm.custom(ChatColor.AQUA + "Bubble " + this.c2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
try
|
||||
{
|
||||
final double pinch = Double.parseDouble(par[1]);
|
||||
final double bubble = Double.parseDouble(par[2]);
|
||||
this.c1 = 1 - pinch;
|
||||
this.c2 = bubble;
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param t
|
||||
* @return double
|
||||
*/
|
||||
private double getStr(final double t)
|
||||
{
|
||||
final double lt = 1 - t;
|
||||
return (lt * lt * lt) + 3 * (lt * lt) * t * this.c1 + 3 * lt * (t * t) * this.c2; // My + (t * ((By + (t * ((c2 + (t * (0 - c2))) - By))) - My));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v
|
||||
*/
|
||||
private void getSurface(final SnipeData v)
|
||||
{
|
||||
this.surface.clear();
|
||||
|
||||
final double bSquared = Math.pow(v.getBrushSize() + 0.5, 2);
|
||||
for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++)
|
||||
{
|
||||
final double zSquared = Math.pow(z, 2);
|
||||
final int actualZ = this.getTargetBlock().getZ() + z;
|
||||
for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
final int actualX = this.getTargetBlock().getX() + x;
|
||||
for (int y = -v.getBrushSize(); y <= v.getBrushSize(); y++)
|
||||
{
|
||||
final double volume = (xSquared + Math.pow(y, 2) + zSquared);
|
||||
if (volume <= bSquared)
|
||||
{
|
||||
if (this.isSurface(actualX, this.getTargetBlock().getY() + y, actualZ))
|
||||
{
|
||||
this.surface.add(new BlockWrapper(this.clampY(actualX, this.getTargetBlock().getY() + y, actualZ), this.getStr(((volume / bSquared)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return boolean
|
||||
*/
|
||||
private boolean isSurface(final int x, final int y, final int z)
|
||||
{
|
||||
return this.getBlockIdAt(x, y, z) != 0 && ((this.getBlockIdAt(x, y - 1, z) == 0) || (this.getBlockIdAt(x, y + 1, z) == 0) || (this.getBlockIdAt(x + 1, y, z) == 0) || (this.getBlockIdAt(x - 1, y, z) == 0) || (this.getBlockIdAt(x, y, z + 1) == 0) || (this.getBlockIdAt(x, y, z - 1) == 0));
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void setBlock(final BlockWrapper block)
|
||||
{
|
||||
final AsyncBlock currentBlock = this.clampY(block.getX(), block.getY() + (int) (this.vh * block.getStr()), block.getZ());
|
||||
if (this.getBlockIdAt(block.getX(), block.getY() - 1, block.getZ()) == 0)
|
||||
{
|
||||
currentBlock.setTypeId(block.getId());
|
||||
currentBlock.setPropertyId(block.getD());
|
||||
for (int y = block.getY(); y < currentBlock.getY(); y++)
|
||||
{
|
||||
this.setBlockIdAt(block.getZ(), block.getX(), y, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentBlock.setTypeId(block.getId());
|
||||
currentBlock.setPropertyId(block.getD());
|
||||
for (int y = block.getY() - 1; y < currentBlock.getY(); y++)
|
||||
{
|
||||
final AsyncBlock current = this.clampY(block.getX(), y, block.getZ());
|
||||
current.setTypeId(block.getId());
|
||||
current.setPropertyId(block.getD());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void setBlockDown(final BlockWrapper block)
|
||||
{
|
||||
final AsyncBlock currentBlock = this.clampY(block.getX(), block.getY() + (int) (this.vh * block.getStr()), block.getZ());
|
||||
currentBlock.setTypeId(block.getId());
|
||||
currentBlock.setPropertyId(block.getD());
|
||||
for (int y = block.getY(); y > currentBlock.getY(); y--)
|
||||
{
|
||||
this.setBlockIdAt(block.getZ(), block.getX(), y, 0);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.vh = v.getVoxelHeight();
|
||||
this.getSurface(v);
|
||||
|
||||
if (this.vh > 0)
|
||||
{
|
||||
for (final BlockWrapper block : this.surface)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
}
|
||||
else if (this.vh < 0)
|
||||
{
|
||||
for (final BlockWrapper block : this.surface)
|
||||
{
|
||||
this.setBlockDown(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.vh = v.getVoxelHeight();
|
||||
|
||||
this.surface.clear();
|
||||
|
||||
int lastY;
|
||||
int newY;
|
||||
int lastStr;
|
||||
double str;
|
||||
final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2);
|
||||
|
||||
int id;
|
||||
|
||||
// Are we pulling up ?
|
||||
if (this.vh > 0)
|
||||
{
|
||||
|
||||
// Z - Axis
|
||||
for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++)
|
||||
{
|
||||
|
||||
final int zSquared = z * z;
|
||||
final int actualZ = this.getTargetBlock().getZ() + z;
|
||||
|
||||
// X - Axis
|
||||
for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++)
|
||||
{
|
||||
|
||||
final int xSquared = x * x;
|
||||
final int actualX = this.getTargetBlock().getX() + x;
|
||||
|
||||
// Down the Y - Axis
|
||||
for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--)
|
||||
{
|
||||
|
||||
final double volume = zSquared + xSquared + (y * y);
|
||||
|
||||
// Is this in the range of the brush?
|
||||
if (volume <= brushSizeSquared && !this.getWorld().getBlockAt(actualX, this.getTargetBlock().getY() + y, actualZ).isEmpty())
|
||||
{
|
||||
|
||||
int actualY = this.getTargetBlock().getY() + y;
|
||||
|
||||
// Starting strength and new Position
|
||||
str = this.getStr(volume / brushSizeSquared);
|
||||
lastStr = (int) (this.vh * str);
|
||||
lastY = actualY + lastStr;
|
||||
|
||||
this.clampY(actualX, lastY, actualZ).setTypeId(this.getWorld().getBlockAt(actualX, actualY, actualZ).getTypeId());
|
||||
|
||||
if (str == 1)
|
||||
{
|
||||
str = 0.8;
|
||||
}
|
||||
|
||||
while (lastStr > 0)
|
||||
{
|
||||
if (actualY < this.getTargetBlock().getY())
|
||||
{
|
||||
str = str * str;
|
||||
}
|
||||
lastStr = (int) (this.vh * str);
|
||||
newY = actualY + lastStr;
|
||||
id = this.getWorld().getBlockAt(actualX, actualY, actualZ).getTypeId();
|
||||
for (int i = newY; i < lastY; i++)
|
||||
{
|
||||
this.clampY(actualX, i, actualZ).setTypeId(id);
|
||||
}
|
||||
lastY = newY;
|
||||
actualY--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int z = -v.getBrushSize(); z <= v.getBrushSize(); z++)
|
||||
{
|
||||
final double zSquared = Math.pow(z, 2);
|
||||
final int actualZ = this.getTargetBlock().getZ() + z;
|
||||
for (int x = -v.getBrushSize(); x <= v.getBrushSize(); x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
final int actualX = this.getTargetBlock().getX() + x;
|
||||
for (int y = -v.getBrushSize(); y <= v.getBrushSize(); y++)
|
||||
{
|
||||
double volume = (xSquared + Math.pow(y, 2) + zSquared);
|
||||
if (volume <= brushSizeSquared && !this.getWorld().getBlockAt(actualX, this.getTargetBlock().getY() + y, actualZ).isEmpty())
|
||||
{
|
||||
final int actualY = this.getTargetBlock().getY() + y;
|
||||
lastY = actualY + (int) (this.vh * this.getStr(volume / brushSizeSquared));
|
||||
this.clampY(actualX, lastY, actualZ).setTypeId(this.getWorld().getBlockAt(actualX, actualY, actualZ).getTypeId());
|
||||
y++;
|
||||
volume = (xSquared + Math.pow(y, 2) + zSquared);
|
||||
while (volume <= brushSizeSquared)
|
||||
{
|
||||
final int blockY = this.getTargetBlock().getY() + y + (int) (this.vh * this.getStr(volume / brushSizeSquared));
|
||||
final int blockId = this.getWorld().getBlockAt(actualX, this.getTargetBlock().getY() + y, actualZ).getTypeId();
|
||||
for (int i = blockY; i < lastY; i++)
|
||||
{
|
||||
this.clampY(actualX, i, actualZ).setTypeId(blockId);
|
||||
}
|
||||
lastY = blockY;
|
||||
y++;
|
||||
volume = (xSquared + Math.pow(y, 2) + zSquared);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Piotr
|
||||
*/
|
||||
private final class BlockWrapper
|
||||
{
|
||||
|
||||
private final int id;
|
||||
private final int d;
|
||||
private final double str;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
|
||||
/**
|
||||
* @param block
|
||||
* @param st
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public BlockWrapper(final AsyncBlock block, final double st)
|
||||
{
|
||||
this.id = block.getTypeId();
|
||||
this.d = block.getPropertyId();
|
||||
this.x = block.getX();
|
||||
this.y = block.getY();
|
||||
this.z = block.getZ();
|
||||
this.str = st;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the d
|
||||
*/
|
||||
public int getD()
|
||||
{
|
||||
return this.d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
public int getId()
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the str
|
||||
*/
|
||||
public double getStr()
|
||||
{
|
||||
return this.str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the x
|
||||
*/
|
||||
public int getX()
|
||||
{
|
||||
return this.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the y
|
||||
*/
|
||||
public int getY()
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the z
|
||||
*/
|
||||
public int getZ()
|
||||
{
|
||||
return this.z;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.pull";
|
||||
}
|
||||
}
|
383
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PunishBrush.java
Normale Datei
383
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/PunishBrush.java
Normale Datei
@ -0,0 +1,383 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Punish_Brush
|
||||
*
|
||||
* @author Monofraps
|
||||
* @author Deamon
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
public class PunishBrush extends PerformBrush
|
||||
{
|
||||
private static final int MAXIMAL_RANDOM_TELEPORTATION_RANGE = 400;
|
||||
private static final int TICKS_PER_SECOND = 20;
|
||||
private static final int INFINIPUNISH_SIZE = -3;
|
||||
private static final int DEFAULT_PUNISH_LEVEL = 10;
|
||||
private static final int DEFAULT_PUSNIH_DURATION = 60;
|
||||
private Punishment punishment = Punishment.FIRE;
|
||||
private int punishLevel = DEFAULT_PUNISH_LEVEL;
|
||||
private int punishDuration = DEFAULT_PUSNIH_DURATION;
|
||||
private boolean specificPlayer = false;
|
||||
private String punishPlayerName = "";
|
||||
private boolean hypnoAffectLandscape = false;
|
||||
private boolean hitsSelf = false;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
public PunishBrush()
|
||||
{
|
||||
this.setName("Punish");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void applyPunishment(final LivingEntity entity, final SnipeData v)
|
||||
{
|
||||
switch (this.punishment)
|
||||
{
|
||||
case FIRE:
|
||||
entity.setFireTicks(PunishBrush.TICKS_PER_SECOND * this.punishDuration);
|
||||
break;
|
||||
case LIGHTNING:
|
||||
entity.getWorld().strikeLightning(entity.getLocation());
|
||||
break;
|
||||
case BLINDNESS:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case DRUNK:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case SLOW:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case JUMP:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case ABSORPTION:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case DAMAGE_RESISTANCE:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case FAST_DIGGING:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.FAST_DIGGING, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case FIRE_RESISTANCE:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case HEAL:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.HEAL, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case HEALTH_BOOST:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.HEALTH_BOOST, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case HUNGER:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.HUNGER, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case INCREASE_DAMAGE:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case INVISIBILITY:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case NIGHT_VISION:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.NIGHT_VISION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case POISON:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.POISON, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case REGENERATION:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case SATURATION:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.SATURATION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case SLOW_DIGGING:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_DIGGING, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case SPEED:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case WATER_BREATHING:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case WEAKNESS:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case WITHER:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.WITHER, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case KILL:
|
||||
entity.setHealth(0d);
|
||||
break;
|
||||
case RANDOMTP:
|
||||
final Random random = new Random();
|
||||
final Location targetLocation = entity.getLocation();
|
||||
targetLocation.setX(targetLocation.getX() + (random.nextInt(MAXIMAL_RANDOM_TELEPORTATION_RANGE) - (MAXIMAL_RANDOM_TELEPORTATION_RANGE / 2)));
|
||||
targetLocation.setZ(targetLocation.getZ() + (random.nextInt(PunishBrush.MAXIMAL_RANDOM_TELEPORTATION_RANGE) - PunishBrush.MAXIMAL_RANDOM_TELEPORTATION_RANGE / 2));
|
||||
entity.teleport(targetLocation);
|
||||
break;
|
||||
case ALL_POTION:
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
entity.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, PunishBrush.TICKS_PER_SECOND * this.punishDuration, this.punishLevel), true);
|
||||
break;
|
||||
case FORCE:
|
||||
final Vector playerVector = this.getTargetBlock().getLocation().toVector();
|
||||
final Vector direction = entity.getLocation().toVector().clone();
|
||||
direction.subtract(playerVector);
|
||||
final double length = direction.length();
|
||||
final double stregth = (1 - (length / v.getBrushSize())) * this.punishLevel;
|
||||
direction.normalize();
|
||||
direction.multiply(stregth);
|
||||
entity.setVelocity(direction);
|
||||
break;
|
||||
case HYPNO:
|
||||
if (entity instanceof Player)
|
||||
{
|
||||
final Location location = entity.getLocation();
|
||||
Location target = location.clone();
|
||||
for (int z = this.punishLevel; z >= -this.punishLevel; z--)
|
||||
{
|
||||
for (int x = this.punishLevel; x >= -this.punishLevel; x--)
|
||||
{
|
||||
for (int y = this.punishLevel; y >= -this.punishLevel; y--)
|
||||
{
|
||||
target.setX(location.getX() + x);
|
||||
target.setY(location.getY() + y);
|
||||
target.setZ(location.getZ() + z);
|
||||
if (this.hypnoAffectLandscape && target.getBlock().isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
target = location.clone();
|
||||
target.add(x, y, z);
|
||||
Player plr = ((Player) entity);
|
||||
BlockData bd = BukkitAdapter.adapt(BlockState.get(v.getVoxelId() + (v.getPropertyId() << BlockTypes.BIT_OFFSET)));
|
||||
plr.sendBlockChange(target, bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Bukkit.getLogger().warning("Could not determine the punishment of punish brush!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
if (!v.owner().getPlayer().hasPermission("voxelsniper.punish"))
|
||||
{
|
||||
v.sendMessage("The server says no!");
|
||||
return;
|
||||
}
|
||||
|
||||
this.punishDuration = v.getVoxelHeight();
|
||||
this.punishLevel = v.getcCen();
|
||||
|
||||
if (this.specificPlayer)
|
||||
{
|
||||
final Player punishedPlayer = Bukkit.getPlayer(this.punishPlayerName);
|
||||
if (punishedPlayer == null)
|
||||
{
|
||||
v.sendMessage("No player " + this.punishPlayerName + " found.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.applyPunishment(punishedPlayer, v);
|
||||
return;
|
||||
}
|
||||
|
||||
final int brushSizeSquare = v.getBrushSize() * v.getBrushSize();
|
||||
final Location targetLocation = new Location(v.getWorld(), this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ());
|
||||
|
||||
final List<LivingEntity> entities = v.getWorld().getLivingEntities();
|
||||
int numPunishApps = 0;
|
||||
for (final LivingEntity entity : entities)
|
||||
{
|
||||
if (v.owner().getPlayer() != entity || hitsSelf)
|
||||
{
|
||||
if (v.getBrushSize() >= 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (entity.getLocation().distanceSquared(targetLocation) <= brushSizeSquare)
|
||||
{
|
||||
numPunishApps++;
|
||||
this.applyPunishment(entity, v);
|
||||
}
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
exception.printStackTrace();
|
||||
v.sendMessage("An error occured.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (v.getBrushSize() == PunishBrush.INFINIPUNISH_SIZE)
|
||||
{
|
||||
numPunishApps++;
|
||||
this.applyPunishment(entity, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
v.sendMessage(ChatColor.DARK_RED + "Punishment applied to " + numPunishApps + " living entities.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (!v.owner().getPlayer().hasPermission("voxelsniper.punish"))
|
||||
{
|
||||
v.sendMessage("The server says no!");
|
||||
return;
|
||||
}
|
||||
|
||||
final int brushSizeSquare = v.getBrushSize() * v.getBrushSize();
|
||||
final Location targetLocation = new Location(v.getWorld(), this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ());
|
||||
|
||||
final List<LivingEntity> entities = v.getWorld().getLivingEntities();
|
||||
|
||||
for (final LivingEntity entity : entities)
|
||||
{
|
||||
if (entity.getLocation().distanceSquared(targetLocation) < brushSizeSquare)
|
||||
{
|
||||
entity.setFireTicks(0);
|
||||
entity.removePotionEffect(PotionEffectType.BLINDNESS);
|
||||
entity.removePotionEffect(PotionEffectType.CONFUSION);
|
||||
entity.removePotionEffect(PotionEffectType.SLOW);
|
||||
entity.removePotionEffect(PotionEffectType.JUMP);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.GREEN + "Punishment: " + this.punishment.toString());
|
||||
vm.size();
|
||||
vm.center();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i].toLowerCase();
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Punish Brush Options:");
|
||||
v.sendMessage(ChatColor.AQUA + "Punishments can be set via /b p [punishment]");
|
||||
v.sendMessage(ChatColor.AQUA + "Punishment level can be set with /vc [level]");
|
||||
v.sendMessage(ChatColor.AQUA + "Punishment duration in seconds can be set with /vh [duration]");
|
||||
v.sendMessage(ChatColor.AQUA + "Parameter -toggleHypnoLandscape will make Hypno punishment only affect landscape.");
|
||||
v.sendMessage(ChatColor.AQUA + "Parameter -toggleSM [playername] will make punishbrush only affect that player.");
|
||||
v.sendMessage(ChatColor.AQUA + "Parameter -toggleSelf will toggle whether you get hit as well.");
|
||||
v.sendMessage(ChatColor.AQUA + "Available Punishment Options:");
|
||||
final StringBuilder punishmentOptions = new StringBuilder();
|
||||
for (final Punishment punishment : Punishment.values())
|
||||
{
|
||||
if (punishmentOptions.length() != 0)
|
||||
{
|
||||
punishmentOptions.append(" | ");
|
||||
}
|
||||
punishmentOptions.append(punishment.name());
|
||||
}
|
||||
v.sendMessage(ChatColor.GOLD + punishmentOptions.toString());
|
||||
return;
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("-toggleSM"))
|
||||
{
|
||||
this.specificPlayer = !this.specificPlayer;
|
||||
if (this.specificPlayer)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.punishPlayerName = par[++i];
|
||||
}
|
||||
catch (final IndexOutOfBoundsException exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "You have to specify a player name after -toggleSM if you want to turn the specific player feature on.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("-toggleSelf"))
|
||||
{
|
||||
this.hitsSelf = !this.hitsSelf;
|
||||
if (hitsSelf)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Your punishments will now affect you too!");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Your punishments will no longer affect you!");
|
||||
}
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("-toggleHypnoLandscape"))
|
||||
{
|
||||
this.hypnoAffectLandscape = !this.hypnoAffectLandscape;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
this.punishment = Punishment.valueOf(parameter.toUpperCase());
|
||||
v.sendMessage(ChatColor.AQUA + this.punishment.name().toLowerCase() + " punishment selected.");
|
||||
}
|
||||
catch (final IllegalArgumentException exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "No such Punishment.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Monofraps
|
||||
*/
|
||||
private enum Punishment
|
||||
{
|
||||
// Monofraps
|
||||
FIRE, LIGHTNING, BLINDNESS, DRUNK, KILL, RANDOMTP, ALL_POTION,
|
||||
// Deamon
|
||||
SLOW, JUMP, ABSORPTION, DAMAGE_RESISTANCE, FAST_DIGGING, FIRE_RESISTANCE, HEAL, HEALTH_BOOST, HUNGER, INCREASE_DAMAGE, INVISIBILITY, NIGHT_VISION, POISON, REGENERATION,
|
||||
SATURATION, SLOW_DIGGING, SPEED, WATER_BREATHING, WEAKNESS, WITHER,
|
||||
// MikeMatrix
|
||||
FORCE, HYPNO
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.punish";
|
||||
}
|
||||
}
|
@ -0,0 +1,470 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Random-Erode_Brush
|
||||
*
|
||||
* @author Piotr
|
||||
* @author Giltwist (Randomized blockPositionY)
|
||||
*/
|
||||
public class RandomErodeBrush extends Brush
|
||||
{
|
||||
private final double trueCircle = 0.5;
|
||||
private BlockWrapper[][][] snap;
|
||||
private BlockWrapper[][][] firstSnap;
|
||||
private int bsize;
|
||||
private int erodeFace;
|
||||
private int fillFace;
|
||||
private int brushSize;
|
||||
private int erodeRecursion = 1;
|
||||
private int fillRecursion = 1;
|
||||
private Random generator = new Random();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public RandomErodeBrush()
|
||||
{
|
||||
this.setName("RandomErode");
|
||||
}
|
||||
|
||||
private boolean erode(final int x, final int y, final int z)
|
||||
{
|
||||
if (this.snap[x][y][z].isSolid())
|
||||
{
|
||||
int d = 0;
|
||||
if (!this.snap[x + 1][y][z].isSolid())
|
||||
{
|
||||
d++;
|
||||
}
|
||||
if (!this.snap[x - 1][y][z].isSolid())
|
||||
{
|
||||
d++;
|
||||
}
|
||||
if (!this.snap[x][y + 1][z].isSolid())
|
||||
{
|
||||
d++;
|
||||
}
|
||||
if (!this.snap[x][y - 1][z].isSolid())
|
||||
{
|
||||
d++;
|
||||
}
|
||||
if (!this.snap[x][y][z + 1].isSolid())
|
||||
{
|
||||
d++;
|
||||
}
|
||||
if (!this.snap[x][y][z - 1].isSolid())
|
||||
{
|
||||
d++;
|
||||
}
|
||||
return (d >= this.erodeFace);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private boolean fill(final int x, final int y, final int z)
|
||||
{
|
||||
if (this.snap[x][y][z].isSolid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int d = 0;
|
||||
if (this.snap[x + 1][y][z].isSolid())
|
||||
{
|
||||
this.snap[x][y][z].setId(this.snap[x + 1][y][z].getNativeBlock().getTypeId());
|
||||
d++;
|
||||
}
|
||||
if (this.snap[x - 1][y][z].isSolid())
|
||||
{
|
||||
this.snap[x][y][z].setId(this.snap[x - 1][y][z].getNativeBlock().getTypeId());
|
||||
d++;
|
||||
}
|
||||
if (this.snap[x][y + 1][z].isSolid())
|
||||
{
|
||||
this.snap[x][y][z].setId(this.snap[x][y + 1][z].getNativeBlock().getTypeId());
|
||||
d++;
|
||||
}
|
||||
if (this.snap[x][y - 1][z].isSolid())
|
||||
{
|
||||
this.snap[x][y][z].setId(this.snap[x][y - 1][z].getNativeBlock().getTypeId());
|
||||
d++;
|
||||
}
|
||||
if (this.snap[x][y][z + 1].isSolid())
|
||||
{
|
||||
this.snap[x][y][z].setId(this.snap[x][y][z + 1].getNativeBlock().getTypeId());
|
||||
d++;
|
||||
}
|
||||
if (this.snap[x][y][z - 1].isSolid())
|
||||
{
|
||||
this.snap[x][y][z].setId(this.snap[x][y][z - 1].getNativeBlock().getTypeId());
|
||||
d++;
|
||||
}
|
||||
return (d >= this.fillFace);
|
||||
}
|
||||
}
|
||||
|
||||
private void getMatrix()
|
||||
{
|
||||
this.brushSize = ((this.bsize + 1) * 2) + 1;
|
||||
|
||||
if (this.snap.length == 0)
|
||||
{
|
||||
this.snap = new BlockWrapper[this.brushSize][this.brushSize][this.brushSize];
|
||||
|
||||
int sx = this.getTargetBlock().getX() - (this.bsize + 1);
|
||||
int sy = this.getTargetBlock().getY() - (this.bsize + 1);
|
||||
int sz = this.getTargetBlock().getZ() - (this.bsize + 1);
|
||||
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
sz = this.getTargetBlock().getZ() - (this.bsize + 1);
|
||||
for (int z = 0; z < this.snap.length; z++)
|
||||
{
|
||||
sy = this.getTargetBlock().getY() - (this.bsize + 1);
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
this.snap[x][y][z] = new BlockWrapper(this.clampY(sx, sy, sz));
|
||||
sy++;
|
||||
}
|
||||
sz++;
|
||||
}
|
||||
sx++;
|
||||
}
|
||||
this.firstSnap = this.snap.clone();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.snap = new BlockWrapper[this.brushSize][this.brushSize][this.brushSize];
|
||||
|
||||
int sx = this.getTargetBlock().getX() - (this.bsize + 1);
|
||||
int sy = this.getTargetBlock().getY() - (this.bsize + 1);
|
||||
int sz = this.getTargetBlock().getZ() - (this.bsize + 1);
|
||||
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
sz = this.getTargetBlock().getZ() - (this.bsize + 1);
|
||||
for (int z = 0; z < this.snap.length; z++)
|
||||
{
|
||||
sy = this.getTargetBlock().getY() - (this.bsize + 1);
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
this.snap[x][y][z] = new BlockWrapper(this.clampY(sx, sy, sz));
|
||||
sy++;
|
||||
}
|
||||
sz++;
|
||||
}
|
||||
sx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void rerosion(final SnipeData v)
|
||||
{
|
||||
final Undo undo = new Undo();
|
||||
|
||||
if (this.erodeFace >= 0 && this.erodeFace <= 6)
|
||||
{
|
||||
for (int currentErodeRecursion = 0; currentErodeRecursion < this.erodeRecursion; currentErodeRecursion++)
|
||||
{
|
||||
this.getMatrix();
|
||||
|
||||
final double brushSizeSquared = Math.pow(this.bsize + this.trueCircle, 2);
|
||||
for (int z = 1; z < this.snap.length - 1; z++)
|
||||
{
|
||||
|
||||
final double zSquared = Math.pow(z - (this.bsize + 1), 2);
|
||||
for (int x = 1; x < this.snap.length - 1; x++)
|
||||
{
|
||||
|
||||
final double xSquared = Math.pow(x - (this.bsize + 1), 2);
|
||||
for (int y = 1; y < this.snap.length - 1; y++)
|
||||
{
|
||||
|
||||
if (((xSquared + Math.pow(y - (this.bsize + 1), 2) + zSquared) <= brushSizeSquared))
|
||||
{
|
||||
if (this.erode(x, y, z))
|
||||
{
|
||||
this.snap[x][y][z].getNativeBlock().setTypeId(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.fillFace >= 0 && this.fillFace <= 6)
|
||||
{
|
||||
final double brushSizeSquared = Math.pow(this.bsize + 0.5, 2);
|
||||
|
||||
for (int currentFillRecursion = 0; currentFillRecursion < this.fillRecursion; currentFillRecursion++)
|
||||
{
|
||||
this.getMatrix();
|
||||
|
||||
for (int z = 1; z < this.snap.length - 1; z++)
|
||||
{
|
||||
|
||||
final double zSquared = Math.pow(z - (this.bsize + 1), 2);
|
||||
for (int x = 1; x < this.snap.length - 1; x++)
|
||||
{
|
||||
|
||||
final double xSquared = Math.pow(x - (this.bsize + 1), 2);
|
||||
for (int y = 1; y < this.snap.length - 1; y++)
|
||||
{
|
||||
|
||||
if (((xSquared + Math.pow(y - (this.bsize + 1), 2) + zSquared) <= brushSizeSquared))
|
||||
{
|
||||
if (this.fill(x, y, z))
|
||||
{
|
||||
this.snap[x][y][z].getNativeBlock().setTypeId(this.snap[x][y][z].getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (BlockWrapper[][] firstSnapSlice : this.firstSnap)
|
||||
{
|
||||
for (BlockWrapper[] firstSnapString : firstSnapSlice)
|
||||
{
|
||||
for (final BlockWrapper block : firstSnapString)
|
||||
{
|
||||
if (block.getI() != block.getNativeBlock().getTypeId())
|
||||
{
|
||||
undo.put(block.getNativeBlock());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void rfilling(final SnipeData v)
|
||||
{
|
||||
final Undo undo = new Undo();
|
||||
|
||||
if (this.fillFace >= 0 && this.fillFace <= 6)
|
||||
{
|
||||
final double bSquared = Math.pow(this.bsize + 0.5, 2);
|
||||
|
||||
for (int currentFillRecursion = 0; currentFillRecursion < this.fillRecursion; currentFillRecursion++)
|
||||
{
|
||||
this.getMatrix();
|
||||
|
||||
for (int z = 1; z < this.snap.length - 1; z++)
|
||||
{
|
||||
final double zSquared = Math.pow(z - (this.bsize + 1), 2);
|
||||
for (int x = 1; x < this.snap.length - 1; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x - (this.bsize + 1), 2);
|
||||
for (int y = 1; y < this.snap.length - 1; y++)
|
||||
{
|
||||
if (((xSquared + Math.pow(y - (this.bsize + 1), 2) + zSquared) <= bSquared))
|
||||
{
|
||||
if (this.fill(x, y, z))
|
||||
{
|
||||
this.snap[x][y][z].getNativeBlock().setTypeId(this.snap[x][y][z].getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.erodeFace >= 0 && this.erodeFace <= 6)
|
||||
{
|
||||
final double bSquared = Math.pow(this.bsize + this.trueCircle, 2);
|
||||
|
||||
for (int currentErodeRecursion = 0; currentErodeRecursion < this.erodeRecursion; currentErodeRecursion++)
|
||||
{
|
||||
this.getMatrix();
|
||||
|
||||
for (int z = 1; z < this.snap.length - 1; z++)
|
||||
{
|
||||
|
||||
final double zSquared = Math.pow(z - (this.bsize + 1), 2);
|
||||
for (int x = 1; x < this.snap.length - 1; x++)
|
||||
{
|
||||
|
||||
final double xSquared = Math.pow(x - (this.bsize + 1), 2);
|
||||
for (int y = 1; y < this.snap.length - 1; y++)
|
||||
{
|
||||
|
||||
if (((xSquared + Math.pow(y - (this.bsize + 1), 2) + zSquared) <= bSquared))
|
||||
{
|
||||
if (this.erode(x, y, z))
|
||||
{
|
||||
this.snap[x][y][z].getNativeBlock().setTypeId(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (BlockWrapper[][] firstSnapSlice : this.firstSnap)
|
||||
{
|
||||
for (BlockWrapper[] firstSnapString : firstSnapSlice)
|
||||
{
|
||||
for (final BlockWrapper block : firstSnapString)
|
||||
{
|
||||
if (block.getI() != block.getNativeBlock().getTypeId())
|
||||
{
|
||||
undo.put(block.getNativeBlock());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.bsize = v.getBrushSize();
|
||||
|
||||
this.snap = new BlockWrapper[0][0][0];
|
||||
|
||||
this.erodeFace = this.generator.nextInt(5) + 1;
|
||||
this.fillFace = this.generator.nextInt(3) + 3;
|
||||
this.erodeRecursion = this.generator.nextInt(3);
|
||||
this.fillRecursion = this.generator.nextInt(3);
|
||||
|
||||
if (this.fillRecursion == 0 && this.erodeRecursion == 0)
|
||||
{ // if they are both zero, it will lead to a null pointer exception. Still want to give them a
|
||||
// chance to be zero though, for more interestingness -Gav
|
||||
this.erodeRecursion = this.generator.nextInt(2) + 1;
|
||||
this.fillRecursion = this.generator.nextInt(2) + 1;
|
||||
}
|
||||
|
||||
this.rerosion(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.bsize = v.getBrushSize();
|
||||
|
||||
this.snap = new BlockWrapper[0][0][0];
|
||||
|
||||
this.erodeFace = this.generator.nextInt(3) + 3;
|
||||
this.fillFace = this.generator.nextInt(5) + 1;
|
||||
this.erodeRecursion = this.generator.nextInt(3);
|
||||
this.fillRecursion = this.generator.nextInt(3);
|
||||
if (this.fillRecursion == 0 && this.erodeRecursion == 0)
|
||||
{ // if they are both zero, it will lead to a null pointer exception. Still want to give them a
|
||||
// chance to be zero though, for more interestingness -Gav
|
||||
this.erodeRecursion = this.generator.nextInt(2) + 1;
|
||||
this.fillRecursion = this.generator.nextInt(2) + 1;
|
||||
}
|
||||
|
||||
this.rfilling(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @author unknown
|
||||
*/
|
||||
private class BlockWrapper
|
||||
{
|
||||
private boolean solid;
|
||||
private AsyncBlock nativeBlock;
|
||||
private int id;
|
||||
private int i;
|
||||
|
||||
/**
|
||||
* @param bl
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public BlockWrapper(final AsyncBlock bl)
|
||||
{
|
||||
this.setNativeBlock(bl);
|
||||
this.setI(bl.getTypeId());
|
||||
switch (bl.getType())
|
||||
{
|
||||
case AIR:
|
||||
this.setSolid(false);
|
||||
break;
|
||||
case WATER:
|
||||
this.setSolid(false);
|
||||
break;
|
||||
case LAVA:
|
||||
this.setSolid(false);
|
||||
break;
|
||||
default:
|
||||
this.setSolid(true);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSolid()
|
||||
{
|
||||
return solid;
|
||||
}
|
||||
|
||||
public void setSolid(boolean solid)
|
||||
{
|
||||
this.solid = solid;
|
||||
}
|
||||
|
||||
public AsyncBlock getNativeBlock()
|
||||
{
|
||||
return nativeBlock;
|
||||
}
|
||||
|
||||
public void setNativeBlock(AsyncBlock nativeBlock)
|
||||
{
|
||||
this.nativeBlock = nativeBlock;
|
||||
}
|
||||
|
||||
public int getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getI()
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
public void setI(int i)
|
||||
{
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.randomerode";
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.Chunk;
|
||||
|
||||
/**
|
||||
* Regenerates the target chunk.
|
||||
*
|
||||
* @author Mick
|
||||
*/
|
||||
public class RegenerateChunkBrush extends Brush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public RegenerateChunkBrush()
|
||||
{
|
||||
this.setName("Chunk Generator 40k");
|
||||
}
|
||||
|
||||
private void generateChunk(final SnipeData v)
|
||||
{
|
||||
final Chunk chunk = this.getTargetBlock().getChunk();
|
||||
final Undo undo = new Undo();
|
||||
|
||||
for (int z = CHUNK_SIZE; z >= 0; z--)
|
||||
{
|
||||
for (int x = CHUNK_SIZE; x >= 0; x--)
|
||||
{
|
||||
for (int y = this.getWorld().getMaxHeight(); y >= 0; y--)
|
||||
{
|
||||
undo.put(chunk.getBlock(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
|
||||
v.sendMessage("Generate that chunk! " + chunk.getX() + " " + chunk.getZ());
|
||||
this.getWorld().regenerateChunk(chunk.getX(), chunk.getZ());
|
||||
this.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.generateChunk(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.generateChunk(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.brushMessage("Tread lightly.");
|
||||
vm.brushMessage("This brush will melt your spleen and sell your kidneys.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.regeneratechunk";
|
||||
}
|
||||
}
|
120
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RingBrush.java
Normale Datei
120
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RingBrush.java
Normale Datei
@ -0,0 +1,120 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Ring_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class RingBrush extends PerformBrush
|
||||
{
|
||||
private double trueCircle = 0;
|
||||
private double innerSize = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public RingBrush()
|
||||
{
|
||||
this.setName("Ring");
|
||||
}
|
||||
|
||||
private void ring(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final double outerSquared = Math.pow(brushSize + this.trueCircle, 2);
|
||||
final double innerSquared = Math.pow(this.innerSize, 2);
|
||||
|
||||
for (int x = brushSize; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x, 2);
|
||||
for (int z = brushSize; z >= 0; z--)
|
||||
{
|
||||
final double ySquared = Math.pow(z, 2);
|
||||
if ((xSquared + ySquared) <= outerSquared && (xSquared + ySquared) >= innerSquared)
|
||||
{
|
||||
current.perform(targetBlock.getRelative(x, 0, z));
|
||||
current.perform(targetBlock.getRelative(x, 0, -z));
|
||||
current.perform(targetBlock.getRelative(-x, 0, z));
|
||||
current.perform(targetBlock.getRelative(-x, 0, -z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.ring(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.ring(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.custom(ChatColor.AQUA + "The inner radius is " + ChatColor.RED + this.innerSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
if (par[i].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Ring Brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b ri true -- will use a true circle algorithm instead of the skinnier version with classic sniper nubs. /b ri false will switch back. (false is default)");
|
||||
v.sendMessage(ChatColor.AQUA + "/b ri ir2.5 -- will set the inner radius to 2.5 units");
|
||||
return;
|
||||
}
|
||||
else if (par[i].startsWith("true"))
|
||||
{
|
||||
this.trueCircle = 0.5;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode ON.");
|
||||
}
|
||||
else if (par[i].startsWith("false"))
|
||||
{
|
||||
this.trueCircle = 0;
|
||||
v.sendMessage(ChatColor.AQUA + "True circle mode OFF.");
|
||||
}
|
||||
else if (par[i].startsWith("ir"))
|
||||
{
|
||||
try
|
||||
{
|
||||
final double d = Double.parseDouble(par[i].replace("ir", ""));
|
||||
this.innerSize = d;
|
||||
v.sendMessage(ChatColor.AQUA + "The inner radius has been set to " + ChatColor.RED + this.innerSize);
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "The parameters included are invalid.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.ring";
|
||||
}
|
||||
}
|
214
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DBrush.java
Normale Datei
214
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DBrush.java
Normale Datei
@ -0,0 +1,214 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.util.BlockWrapper;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
/**
|
||||
* @author Piotr
|
||||
*/
|
||||
public class Rot2DBrush extends Brush
|
||||
{
|
||||
private int mode = 0;
|
||||
private int bSize;
|
||||
private int brushSize;
|
||||
private BlockWrapper[][][] snap;
|
||||
private double se;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public Rot2DBrush()
|
||||
{
|
||||
this.setName("2D Rotation");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void getMatrix()
|
||||
{
|
||||
this.brushSize = (this.bSize * 2) + 1;
|
||||
|
||||
this.snap = new BlockWrapper[this.brushSize][this.brushSize][this.brushSize];
|
||||
|
||||
final double brushSizeSquared = Math.pow(this.bSize + 0.5, 2);
|
||||
int sx = this.getTargetBlock().getX() - this.bSize;
|
||||
int sy = this.getTargetBlock().getY() - this.bSize;
|
||||
int sz = this.getTargetBlock().getZ() - this.bSize;
|
||||
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
sz = this.getTargetBlock().getZ() - this.bSize;
|
||||
final double xSquared = Math.pow(x - this.bSize, 2);
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
sy = this.getTargetBlock().getY() - this.bSize;
|
||||
if (xSquared + Math.pow(y - this.bSize, 2) <= brushSizeSquared)
|
||||
{
|
||||
for (int z = 0; z < this.snap.length; z++)
|
||||
{
|
||||
final AsyncBlock block = this.clampY(sx, sy, sz); // why is this not sx + x, sy + y sz + z?
|
||||
this.snap[x][z][y] = new BlockWrapper(block);
|
||||
block.setTypeId(0);
|
||||
sy++;
|
||||
}
|
||||
}
|
||||
sz++;
|
||||
}
|
||||
sx++;
|
||||
}
|
||||
}
|
||||
|
||||
private void rotate(final SnipeData v)
|
||||
{
|
||||
final double brushSiyeSquared = Math.pow(this.bSize + 0.5, 2);
|
||||
final double cos = Math.cos(this.se);
|
||||
final double sin = Math.sin(this.se);
|
||||
final boolean[][] doNotFill = new boolean[this.snap.length][this.snap.length];
|
||||
// I put y in the inside loop, since it doesn't have any power functions, should be much faster.
|
||||
// Also, new array keeps track of which x and z coords are being assigned in the rotated space so that we can
|
||||
// do a targeted filling of only those columns later that were left out.
|
||||
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
final int xx = x - this.bSize;
|
||||
final double xSquared = Math.pow(xx, 2);
|
||||
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
final int zz = y - this.bSize;
|
||||
|
||||
if (xSquared + Math.pow(zz, 2) <= brushSiyeSquared)
|
||||
{
|
||||
final double newX = (xx * cos) - (zz * sin);
|
||||
final double newZ = (xx * sin) + (zz * cos);
|
||||
|
||||
doNotFill[(int) newX + this.bSize][(int) newZ + this.bSize] = true;
|
||||
|
||||
for (int currentY = 0; currentY < this.snap.length; currentY++)
|
||||
{
|
||||
final int yy = currentY - this.bSize;
|
||||
final BlockWrapper block = this.snap[x][currentY][y];
|
||||
|
||||
if (block.getId() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
this.setBlockIdAndDataAt(this.getTargetBlock().getX() + (int) newX, this.getTargetBlock().getY() + yy, this.getTargetBlock().getZ() + (int) newZ, block.getId(), block.getPropertyId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x - this.bSize, 2);
|
||||
final int fx = x + this.getTargetBlock().getX() - this.bSize;
|
||||
|
||||
for (int z = 0; z < this.snap.length; z++)
|
||||
{
|
||||
if (xSquared + Math.pow(z - this.bSize, 2) <= brushSiyeSquared)
|
||||
{
|
||||
final int fz = z + this.getTargetBlock().getZ() - this.bSize;
|
||||
|
||||
if (!doNotFill[x][z])
|
||||
{
|
||||
// smart fill stuff
|
||||
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
final int fy = y + this.getTargetBlock().getY() - this.bSize;
|
||||
|
||||
final int a = this.getBlockIdAt(fx + 1, fy, fz);
|
||||
final int aData = this.getBlockDataAt(fx + 1, fy, fz);
|
||||
final int d = this.getBlockIdAt(fx - 1, fy, fz);
|
||||
final int dData = this.getBlockDataAt(fx - 1, fy, fz);
|
||||
final int c = this.getBlockIdAt(fx, fy, fz + 1);
|
||||
final int b = this.getBlockIdAt(fx, fy, fz - 1);
|
||||
final int bData = this.getBlockDataAt(fx, fy, fz - 1);
|
||||
|
||||
int winner;
|
||||
int winnerData;
|
||||
|
||||
if (a == b || a == c || a == d)
|
||||
{ // I figure that since we are already narrowing it down to ONLY the holes left behind, it
|
||||
// should
|
||||
// be fine to do all 5 checks needed to be legit about it.
|
||||
winner = a;
|
||||
winnerData = aData;
|
||||
}
|
||||
else if (b == d || c == d)
|
||||
{
|
||||
winner = d;
|
||||
winnerData = dData;
|
||||
}
|
||||
else
|
||||
{
|
||||
winner = b; // blockPositionY making this default, it will also automatically cover situations where B = C;
|
||||
winnerData = bData;
|
||||
}
|
||||
|
||||
this.setBlockIdAndDataAt(fx, fy, fz, winner, winnerData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.bSize = v.getBrushSize();
|
||||
|
||||
switch (this.mode)
|
||||
{
|
||||
case 0:
|
||||
this.getMatrix();
|
||||
this.rotate(v);
|
||||
break;
|
||||
|
||||
default:
|
||||
v.sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.bSize = v.getBrushSize();
|
||||
|
||||
switch (this.mode)
|
||||
{
|
||||
case 0:
|
||||
this.getMatrix();
|
||||
this.rotate(v);
|
||||
break;
|
||||
|
||||
default:
|
||||
v.sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
this.se = Math.toRadians(Double.parseDouble(par[1]));
|
||||
v.sendMessage(ChatColor.GREEN + "Angle set to " + this.se);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.rot2d";
|
||||
}
|
||||
}
|
223
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DvertBrush.java
Normale Datei
223
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot2DvertBrush.java
Normale Datei
@ -0,0 +1,223 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.util.BlockWrapper;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
/**
|
||||
* @author Gavjenks, hack job from the other 2d rotation brush blockPositionY piotr
|
||||
*/
|
||||
// The X Y and Z variable names in this file do NOT MAKE ANY SENSE. Do not attempt to actually figure out what on earth is going on here. Just go to the
|
||||
// original 2d horizontal brush if you wish to make anything similar to this, and start there. I didn't bother renaming everything.
|
||||
public class Rot2DvertBrush extends Brush
|
||||
{
|
||||
private int mode = 0;
|
||||
private int bSize;
|
||||
private int brushSize;
|
||||
private BlockWrapper[][][] snap;
|
||||
private double se;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public Rot2DvertBrush()
|
||||
{
|
||||
this.setName("2D Rotation");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void getMatrix()
|
||||
{
|
||||
this.brushSize = (this.bSize * 2) + 1;
|
||||
|
||||
this.snap = new BlockWrapper[this.brushSize][this.brushSize][this.brushSize];
|
||||
|
||||
int sx = this.getTargetBlock().getX() - this.bSize;
|
||||
int sy = this.getTargetBlock().getY() - this.bSize;
|
||||
int sz = this.getTargetBlock().getZ() - this.bSize;
|
||||
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
sz = this.getTargetBlock().getZ() - this.bSize;
|
||||
|
||||
for (int z = 0; z < this.snap.length; z++)
|
||||
{
|
||||
sy = this.getTargetBlock().getY() - this.bSize;
|
||||
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
final AsyncBlock block = this.clampY(sx, sy, sz); // why is this not sx + x, sy + y sz + z?
|
||||
this.snap[x][y][z] = new BlockWrapper(block);
|
||||
block.setTypeId(0);
|
||||
sy++;
|
||||
}
|
||||
|
||||
sz++;
|
||||
}
|
||||
sx++;
|
||||
}
|
||||
}
|
||||
|
||||
private void rotate(final SnipeData v)
|
||||
{
|
||||
final double brushSizeSquared = Math.pow(this.bSize + 0.5, 2);
|
||||
final double cos = Math.cos(this.se);
|
||||
final double sin = Math.sin(this.se);
|
||||
final boolean[][] doNotFill = new boolean[this.snap.length][this.snap.length];
|
||||
// I put y in the inside loop, since it doesn't have any power functions, should be much faster.
|
||||
// Also, new array keeps track of which x and z coords are being assigned in the rotated space so that we can
|
||||
// do a targeted filling of only those columns later that were left out.
|
||||
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
final int xx = x - this.bSize;
|
||||
final double xSquared = Math.pow(xx, 2);
|
||||
|
||||
for (int z = 0; z < this.snap.length; z++)
|
||||
{
|
||||
final int zz = z - this.bSize;
|
||||
|
||||
if (xSquared + Math.pow(zz, 2) <= brushSizeSquared)
|
||||
{
|
||||
final double newX = (xx * cos) - (zz * sin);
|
||||
final double newZ = (xx * sin) + (zz * cos);
|
||||
|
||||
doNotFill[(int) newX + this.bSize][(int) newZ + this.bSize] = true;
|
||||
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
final int yy = y - this.bSize;
|
||||
|
||||
final BlockWrapper block = this.snap[y][x][z];
|
||||
if (block.getId() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
this.setBlockIdAndDataAt(this.getTargetBlock().getX() + yy, this.getTargetBlock().getY() + (int) newX, this.getTargetBlock().getZ() + (int) newZ, block.getId(), block.getPropertyId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x - this.bSize, 2);
|
||||
final int fx = x + this.getTargetBlock().getX() - this.bSize;
|
||||
|
||||
for (int z = 0; z < this.snap.length; z++)
|
||||
{
|
||||
if (xSquared + Math.pow(z - this.bSize, 2) <= brushSizeSquared)
|
||||
{
|
||||
final int fz = z + this.getTargetBlock().getZ() - this.bSize;
|
||||
|
||||
if (!doNotFill[x][z])
|
||||
{
|
||||
// smart fill stuff
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
final int fy = y + this.getTargetBlock().getY() - this.bSize;
|
||||
|
||||
final int a = this.getBlockIdAt(fy, fx + 1, fz);
|
||||
final int aData = this.getBlockDataAt(fy, fx + 1, fz);
|
||||
final int d = this.getBlockIdAt(fy, fx - 1, fz);
|
||||
final int dData = this.getBlockDataAt(fy, fx - 1, fz);
|
||||
final int c = this.getBlockIdAt(fy, fx, fz + 1);
|
||||
final int b = this.getBlockIdAt(fy, fx, fz - 1);
|
||||
final int bData = this.getBlockDataAt(fy, fx, fz - 1);
|
||||
|
||||
int winner;
|
||||
int winnerData;
|
||||
|
||||
if (a == b || a == c || a == d)
|
||||
{ // I figure that since we are already narrowing it down to ONLY the holes left behind, it
|
||||
// should
|
||||
// be fine to do all 5 checks needed to be legit about it.
|
||||
winner = a;
|
||||
winnerData = aData;
|
||||
}
|
||||
else if (b == d || c == d)
|
||||
{
|
||||
winner = d;
|
||||
winnerData = dData;
|
||||
}
|
||||
else
|
||||
{
|
||||
winner = b; // blockPositionY making this default, it will also automatically cover situations where B = C;
|
||||
winnerData = bData;
|
||||
}
|
||||
|
||||
this.setBlockIdAndDataAt(fy, fx, fz, winner, winnerData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.bSize = v.getBrushSize();
|
||||
|
||||
switch (this.mode)
|
||||
{
|
||||
case 0:
|
||||
this.getMatrix();
|
||||
this.rotate(v);
|
||||
break;
|
||||
|
||||
default:
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.bSize = v.getBrushSize();
|
||||
|
||||
switch (this.mode)
|
||||
{
|
||||
case 0:
|
||||
this.getMatrix();
|
||||
this.rotate(v);
|
||||
break;
|
||||
|
||||
default:
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.se = Math.toRadians(Double.parseDouble(par[1]));
|
||||
v.sendMessage(ChatColor.GREEN + "Angle set to " + this.se);
|
||||
}
|
||||
catch (Exception _ex)
|
||||
{
|
||||
v.sendMessage("Exception while parsing parameter: " + par[1]);
|
||||
Bukkit.getLogger().severe(_ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.rot2dvert";
|
||||
}
|
||||
}
|
286
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot3DBrush.java
Normale Datei
286
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/Rot3DBrush.java
Normale Datei
@ -0,0 +1,286 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import com.thevoxelbox.voxelsniper.util.BlockWrapper;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Rot3DBrush extends Brush
|
||||
{
|
||||
private final int mode = 0;
|
||||
private int bSize;
|
||||
private int brushSize;
|
||||
private BlockWrapper[][][] snap;
|
||||
private double seYaw;
|
||||
private double sePitch;
|
||||
private double seRoll;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public Rot3DBrush()
|
||||
{
|
||||
this.setName("3D Rotation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.brushMessage("Rotates Yaw (XZ), then Pitch(XY), then Roll(ZY), in order.");
|
||||
}
|
||||
|
||||
// after all rotations, compare snapshot to new state of world, and store changed blocks to undo?
|
||||
// --> agreed. Do what erode does and store one snapshot with Block pointers and int id of what the block started with, afterwards simply go thru that
|
||||
// matrix and compare Block.getId with 'id' if different undo.add( new BlockWrapper ( Block, oldId ) )
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
// which way is clockwise is less obvious for roll and pitch... should probably fix that / make it clear
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Rotate brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "p[0-359] -- set degrees of pitch rotation (rotation about the Z axis).");
|
||||
v.sendMessage(ChatColor.BLUE + "r[0-359] -- set degrees of roll rotation (rotation about the X axis).");
|
||||
v.sendMessage(ChatColor.LIGHT_PURPLE + "y[0-359] -- set degrees of yaw rotation (Rotation about the Y axis).");
|
||||
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("p"))
|
||||
{
|
||||
this.sePitch = Math.toRadians(Double.parseDouble(parameter.replace("p", "")));
|
||||
v.sendMessage(ChatColor.AQUA + "Around Z-axis degrees set to " + this.sePitch);
|
||||
if (this.sePitch < 0 || this.sePitch > 359)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! Angles must be from 1-359");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("r"))
|
||||
{
|
||||
this.seRoll = Math.toRadians(Double.parseDouble(parameter.replace("r", "")));
|
||||
v.sendMessage(ChatColor.AQUA + "Around X-axis degrees set to " + this.seRoll);
|
||||
if (this.seRoll < 0 || this.seRoll > 359)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! Angles must be from 1-359");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("y"))
|
||||
{
|
||||
this.seYaw = Math.toRadians(Double.parseDouble(parameter.replace("y", "")));
|
||||
v.sendMessage(ChatColor.AQUA + "Around Y-axis degrees set to " + this.seYaw);
|
||||
if (this.seYaw < 0 || this.seYaw > 359)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! Angles must be from 1-359");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void getMatrix()
|
||||
{ // only need to do once. But y needs to change + sphere
|
||||
final double brushSizeSquared = Math.pow(this.bSize + 0.5, 2);
|
||||
this.brushSize = (this.bSize * 2) + 1;
|
||||
|
||||
this.snap = new BlockWrapper[this.brushSize][this.brushSize][this.brushSize];
|
||||
|
||||
int sx = this.getTargetBlock().getX() - this.bSize;
|
||||
//int sy = this.getTargetBlock().getY() - this.bSize; Not used
|
||||
int sz = this.getTargetBlock().getZ() - this.bSize;
|
||||
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x - this.bSize, 2);
|
||||
sz = this.getTargetBlock().getZ() - this.bSize;
|
||||
|
||||
for (int z = 0; z < this.snap.length; z++)
|
||||
{
|
||||
final double zSquared = Math.pow(z - this.bSize, 2);
|
||||
sz = this.getTargetBlock().getY() - this.bSize;
|
||||
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
if (xSquared + zSquared + Math.pow(y - this.bSize, 2) <= brushSizeSquared)
|
||||
{
|
||||
final AsyncBlock block = this.clampY(sx, sz, sz);
|
||||
this.snap[x][y][z] = new BlockWrapper(block);
|
||||
block.setTypeId(0);
|
||||
sz++;
|
||||
}
|
||||
}
|
||||
|
||||
sz++;
|
||||
}
|
||||
sx++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void rotate(final SnipeData v)
|
||||
{
|
||||
// basically 1) make it a sphere we are rotating in, not a cylinder
|
||||
// 2) do three rotations in a row, one in each dimension, unless some dimensions are set to zero or udnefined or whatever, then skip those.
|
||||
// --> Why not utilize Sniper'world new oportunities and have arrow rotate all 3, powder rotate x, goldsisc y, otherdisc z. Or something like that. Or
|
||||
// we
|
||||
// could just use arrow and powder and just differenciate between left and right click that gis 4 different situations
|
||||
// --> Well, there would be 7 different possibilities... X, Y, Z, XY, XZ, YZ, XYZ, and different numbers of parameters for each, so I think each having
|
||||
// and item is too confusing. How about this: arrow = rotate one dimension, based on the face you click, and takes 1 param... powder: rotates all three
|
||||
// at once, and takes 3 params.
|
||||
final double brushSizeSquared = Math.pow(this.bSize + 0.5, 2);
|
||||
final double cosYaw = Math.cos(this.seYaw);
|
||||
final double sinYaw = Math.sin(this.seYaw);
|
||||
final double cosPitch = Math.cos(this.sePitch);
|
||||
final double sinPitch = Math.sin(this.sePitch);
|
||||
final double cosRoll = Math.cos(this.seRoll);
|
||||
final double sinRoll = Math.sin(this.seRoll);
|
||||
final boolean[][][] doNotFill = new boolean[this.snap.length][this.snap.length][this.snap.length];
|
||||
final Undo undo = new Undo();
|
||||
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
final int xx = x - this.bSize;
|
||||
final double xSquared = Math.pow(xx, 2);
|
||||
|
||||
for (int z = 0; z < this.snap.length; z++)
|
||||
{
|
||||
final int zz = z - this.bSize;
|
||||
final double zSquared = Math.pow(zz, 2);
|
||||
final double newxzX = (xx * cosYaw) - (zz * sinYaw);
|
||||
final double newxzZ = (xx * sinYaw) + (zz * cosYaw);
|
||||
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
final int yy = y - this.bSize;
|
||||
if (xSquared + zSquared + Math.pow(yy, 2) <= brushSizeSquared)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + xx, this.getTargetBlock().getY() + yy, this.getTargetBlock().getZ() + zz)); // just store
|
||||
// whole sphere in undo, too complicated otherwise, since this brush both adds and remos things unpredictably.
|
||||
|
||||
final double newxyX = (newxzX * cosPitch) - (yy * sinPitch);
|
||||
final double newxyY = (newxzX * sinPitch) + (yy * cosPitch); // calculates all three in succession in precise math space
|
||||
final double newyzY = (newxyY * cosRoll) - (newxzZ * sinRoll);
|
||||
final double newyzZ = (newxyY * sinRoll) + (newxzZ * cosRoll);
|
||||
|
||||
doNotFill[(int) newxyX + this.bSize][(int) newyzY + this.bSize][(int) newyzZ + this.bSize] = true; // only rounds off to nearest
|
||||
// block
|
||||
// after all three, though.
|
||||
|
||||
final BlockWrapper block = this.snap[x][y][z];
|
||||
if (block.getId() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
this.setBlockIdAndDataAt(this.getTargetBlock().getX() + (int) newxyX, this.getTargetBlock().getY() + (int) newyzY, this.getTargetBlock().getZ() + (int) newyzZ, block.getId(), block.getPropertyId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < this.snap.length; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x - this.bSize, 2);
|
||||
final int fx = x + this.getTargetBlock().getX() - this.bSize;
|
||||
|
||||
for (int z = 0; z < this.snap.length; z++)
|
||||
{
|
||||
final double zSquared = Math.pow(z - this.bSize, 2);
|
||||
final int fz = z + this.getTargetBlock().getZ() - this.bSize;
|
||||
|
||||
for (int y = 0; y < this.snap.length; y++)
|
||||
{
|
||||
if (xSquared + zSquared + Math.pow(y - this.bSize, 2) <= brushSizeSquared)
|
||||
{
|
||||
if (!doNotFill[x][y][z])
|
||||
{
|
||||
// smart fill stuff
|
||||
final int fy = y + this.getTargetBlock().getY() - this.bSize;
|
||||
final int a = this.getBlockIdAt(fx + 1, fy, fz);
|
||||
final int aData = this.getBlockDataAt(fx + 1, fy, fz);
|
||||
final int d = this.getBlockIdAt(fx - 1, fy, fz);
|
||||
final int dData = this.getBlockDataAt(fx - 1, fy, fz);
|
||||
final int c = this.getBlockIdAt(fx, fy, fz + 1);
|
||||
final int b = this.getBlockIdAt(fx, fy, fz - 1);
|
||||
final int bData = this.getBlockDataAt(fx, fy, fz - 1);
|
||||
|
||||
int winner;
|
||||
int winnerData;
|
||||
|
||||
if (a == b || a == c || a == d)
|
||||
{ // I figure that since we are already narrowing it down to ONLY the holes left behind, it
|
||||
// should
|
||||
// be fine to do all 5 checks needed to be legit about it.
|
||||
winner = a;
|
||||
winnerData = aData;
|
||||
}
|
||||
else if (b == d || c == d)
|
||||
{
|
||||
winner = d;
|
||||
winnerData = dData;
|
||||
}
|
||||
else
|
||||
{
|
||||
winner = b; // blockPositionY making this default, it will also automatically cover situations where B = C;
|
||||
winnerData = bData;
|
||||
}
|
||||
|
||||
this.setBlockIdAndDataAt(fx, fy, fz, winner, winnerData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.bSize = v.getBrushSize();
|
||||
|
||||
switch (this.mode)
|
||||
{
|
||||
case 0:
|
||||
this.getMatrix();
|
||||
this.rotate(v);
|
||||
break;
|
||||
|
||||
default:
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.bSize = v.getBrushSize();
|
||||
|
||||
switch (this.mode)
|
||||
{
|
||||
case 0:
|
||||
this.getMatrix();
|
||||
this.rotate(v);
|
||||
break;
|
||||
|
||||
default:
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.rot3d";
|
||||
}
|
||||
}
|
129
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RulerBrush.java
Normale Datei
129
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/RulerBrush.java
Normale Datei
@ -0,0 +1,129 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Ruler_Brush
|
||||
*
|
||||
* @author Gavjenks
|
||||
*/
|
||||
public class RulerBrush extends Brush
|
||||
{
|
||||
private boolean first = true;
|
||||
private Vector coords = new Vector(0, 0, 0);
|
||||
|
||||
private int xOff = 0;
|
||||
private int yOff = 0;
|
||||
private int zOff = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public RulerBrush()
|
||||
{
|
||||
this.setName("Ruler");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
final int voxelMaterialId = v.getVoxelId();
|
||||
this.coords = this.getTargetBlock().getLocation().toVector();
|
||||
|
||||
if (this.xOff == 0 && this.yOff == 0 && this.zOff == 0)
|
||||
{
|
||||
v.sendMessage(ChatColor.DARK_PURPLE + "First point selected.");
|
||||
this.first = !this.first;
|
||||
}
|
||||
else
|
||||
{
|
||||
final Undo undo = new Undo();
|
||||
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + this.xOff, this.getTargetBlock().getY() + this.yOff, this.getTargetBlock().getZ() + this.zOff));
|
||||
this.setBlockIdAt(this.getTargetBlock().getZ() + this.zOff, this.getTargetBlock().getX() + this.xOff, this.getTargetBlock().getY() + this.yOff, voxelMaterialId);
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (this.coords == null || this.coords.lengthSquared() == 0)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Warning: You did not select a first coordinate with the arrow. Comparing to point 0,0,0 instead.");
|
||||
return;
|
||||
}
|
||||
|
||||
v.sendMessage(ChatColor.BLUE + "Format = (second coord - first coord)");
|
||||
v.sendMessage(ChatColor.AQUA + "X change: " + (this.getTargetBlock().getX() - this.coords.getX()));
|
||||
v.sendMessage(ChatColor.AQUA + "Y change: " + (this.getTargetBlock().getY() - this.coords.getY()));
|
||||
v.sendMessage(ChatColor.AQUA + "Z change: " + (this.getTargetBlock().getZ() - this.coords.getZ()));
|
||||
final double distance = (double) (Math.round(this.getTargetBlock().getLocation().toVector().subtract(this.coords).length() * 100) / 100);
|
||||
final double blockDistance = (double) (Math.round((Math.abs(Math.max(Math.max(Math.abs(this.getTargetBlock().getX() - coords.getX()), Math.abs(this.getTargetBlock().getY() - this.coords.getY())), Math.abs(this.getTargetBlock().getZ() - this.coords.getZ()))) + 1) * 100) / 100);
|
||||
|
||||
v.sendMessage(ChatColor.AQUA + "Euclidean distance = " + distance);
|
||||
v.sendMessage(ChatColor.AQUA + "Block distance = " + blockDistance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.voxel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Ruler Brush instructions: Right click first point with the arrow. Right click with powder for distances from that block (can repeat without getting a new first block.) For placing blocks, use arrow and input the desired coordinates with parameters.");
|
||||
v.sendMessage(ChatColor.LIGHT_PURPLE + "/b r x[x value] y[y value] z[z value] -- Will place blocks one at a time of the type you have set with /v at the location you click + this many units away. If you don't include a value, it will be zero. Don't include ANY values, and the brush will just measure distance.");
|
||||
v.sendMessage(ChatColor.BLUE + "/b r ruler -- will reset the tool to just measure distances, not layout blocks.");
|
||||
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("x"))
|
||||
{
|
||||
this.xOff = Integer.parseInt(parameter.replace("x", ""));
|
||||
v.sendMessage(ChatColor.AQUA + "X offset set to " + this.xOff);
|
||||
}
|
||||
else if (parameter.startsWith("y"))
|
||||
{
|
||||
this.yOff = Integer.parseInt(parameter.replace("y", ""));
|
||||
v.sendMessage(ChatColor.AQUA + "Y offset set to " + this.yOff);
|
||||
}
|
||||
else if (parameter.startsWith("z"))
|
||||
{
|
||||
this.zOff = Integer.parseInt(parameter.replace("z", ""));
|
||||
v.sendMessage(ChatColor.AQUA + "Z offset set to " + this.zOff);
|
||||
}
|
||||
else if (parameter.startsWith("ruler"))
|
||||
{
|
||||
this.zOff = 0;
|
||||
this.yOff = 0;
|
||||
this.xOff = 0;
|
||||
v.sendMessage(ChatColor.BLUE + "Ruler mode.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.ruler";
|
||||
}
|
||||
}
|
200
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ScannerBrush.java
Normale Datei
200
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ScannerBrush.java
Normale Datei
@ -0,0 +1,200 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
/**
|
||||
* @author DivineRage
|
||||
*/
|
||||
public class ScannerBrush extends Brush
|
||||
{
|
||||
private static final int DEPTH_MIN = 1;
|
||||
private static final int DEPTH_DEFAULT = 24;
|
||||
private static final int DEPTH_MAX = 64;
|
||||
|
||||
private int depth = DEPTH_DEFAULT;
|
||||
private Material checkFor = Material.AIR;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public ScannerBrush()
|
||||
{
|
||||
this.setName("Scanner");
|
||||
}
|
||||
|
||||
private int clamp(final int value, final int min, final int max)
|
||||
{
|
||||
if (value < min)
|
||||
{
|
||||
return min;
|
||||
}
|
||||
else if (value > max)
|
||||
{
|
||||
return max;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private void scan(final SnipeData v, final BlockFace bf)
|
||||
{
|
||||
if (bf == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (bf)
|
||||
{
|
||||
case NORTH:
|
||||
// Scan south
|
||||
for (int i = 1; i < this.depth + 1; i++)
|
||||
{
|
||||
if (this.clampY(this.getTargetBlock().getX() + i, this.getTargetBlock().getY(), this.getTargetBlock().getZ()).getType() == this.checkFor)
|
||||
{
|
||||
v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
v.sendMessage(ChatColor.GRAY + "Nope.");
|
||||
break;
|
||||
|
||||
case SOUTH:
|
||||
// Scan north
|
||||
for (int i = 1; i < this.depth + 1; i++)
|
||||
{
|
||||
if (this.clampY(this.getTargetBlock().getX() - i, this.getTargetBlock().getY(), this.getTargetBlock().getZ()).getType() == this.checkFor)
|
||||
{
|
||||
v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
v.sendMessage(ChatColor.GRAY + "Nope.");
|
||||
break;
|
||||
|
||||
case EAST:
|
||||
// Scan west
|
||||
for (int i = 1; i < this.depth + 1; i++)
|
||||
{
|
||||
if (this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ() + i).getType() == this.checkFor)
|
||||
{
|
||||
v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
v.sendMessage(ChatColor.GRAY + "Nope.");
|
||||
break;
|
||||
|
||||
case WEST:
|
||||
// Scan east
|
||||
for (int i = 1; i < this.depth + 1; i++)
|
||||
{
|
||||
if (this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ() - i).getType() == this.checkFor)
|
||||
{
|
||||
v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
v.sendMessage(ChatColor.GRAY + "Nope.");
|
||||
break;
|
||||
|
||||
case UP:
|
||||
// Scan down
|
||||
for (int i = 1; i < this.depth + 1; i++)
|
||||
{
|
||||
if ((this.getTargetBlock().getY() - i) <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY() - i, this.getTargetBlock().getZ()).getType() == this.checkFor)
|
||||
{
|
||||
v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
v.sendMessage(ChatColor.GRAY + "Nope.");
|
||||
break;
|
||||
|
||||
case DOWN:
|
||||
// Scan up
|
||||
for (int i = 1; i < this.depth + 1; i++)
|
||||
{
|
||||
if ((this.getTargetBlock().getY() + i) >= v.getWorld().getMaxHeight())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY() + i, this.getTargetBlock().getZ()).getType() == this.checkFor)
|
||||
{
|
||||
v.sendMessage(ChatColor.GREEN + "" + this.checkFor + " found after " + i + " blocks.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
v.sendMessage(ChatColor.GRAY + "Nope.");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.checkFor = BukkitAdapter.adapt(BlockTypes.get(v.getVoxelId()));
|
||||
this.scan(v, this.getTargetBlock().getFace(this.getLastBlock()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.checkFor = BukkitAdapter.adapt(BlockTypes.get(v.getVoxelId()));
|
||||
this.scan(v, this.getTargetBlock().getFace(this.getLastBlock()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom(ChatColor.GREEN + "Scanner depth set to " + this.depth);
|
||||
vm.custom(ChatColor.GREEN + "Scanner scans for " + this.checkFor + " (change with /v #)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
if (par[i].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Scanner brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sc d# -- will set the search depth to #. Clamps to 1 - 64.");
|
||||
return;
|
||||
}
|
||||
if (par[i].startsWith("d"))
|
||||
{
|
||||
this.depth = this.clamp(Integer.parseInt(par[i].substring(1)), DEPTH_MIN, DEPTH_MAX);
|
||||
v.sendMessage(ChatColor.AQUA + "Scanner depth set to " + this.depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.scanner";
|
||||
}
|
||||
}
|
116
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetBrush.java
Normale Datei
116
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SetBrush.java
Normale Datei
@ -0,0 +1,116 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Set_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class SetBrush extends PerformBrush
|
||||
{
|
||||
private static final int SELECTION_SIZE_MAX = 5000000;
|
||||
private Block block = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SetBrush()
|
||||
{
|
||||
this.setName("Set");
|
||||
}
|
||||
|
||||
private boolean set(final Block bl, final SnipeData v)
|
||||
{
|
||||
if (this.block == null)
|
||||
{
|
||||
this.block = bl;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.block.getWorld().getName().equals(bl.getWorld().getName()))
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "You selected points in different worlds!");
|
||||
this.block = null;
|
||||
return true;
|
||||
}
|
||||
final int lowX = (this.block.getX() <= bl.getX()) ? this.block.getX() : bl.getX();
|
||||
final int lowY = (this.block.getY() <= bl.getY()) ? this.block.getY() : bl.getY();
|
||||
final int lowZ = (this.block.getZ() <= bl.getZ()) ? this.block.getZ() : bl.getZ();
|
||||
final int highX = (this.block.getX() >= bl.getX()) ? this.block.getX() : bl.getX();
|
||||
final int highY = (this.block.getY() >= bl.getY()) ? this.block.getY() : bl.getY();
|
||||
final int highZ = (this.block.getZ() >= bl.getZ()) ? this.block.getZ() : bl.getZ();
|
||||
|
||||
if (Math.abs(highX - lowX) * Math.abs(highZ - lowZ) * Math.abs(highY - lowY) > SELECTION_SIZE_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Selection size above hardcoded limit, please use a smaller selection.");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = lowY; y <= highY; y++)
|
||||
{
|
||||
for (int x = lowX; x <= highX; x++)
|
||||
{
|
||||
for (int z = lowZ; z <= highZ; z++)
|
||||
{
|
||||
this.current.perform(this.clampY(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.block = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
if (this.set(this.getTargetBlock(), v))
|
||||
{
|
||||
v.sendMessage(ChatColor.GRAY + "Point one");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (this.set(this.getLastBlock(), v))
|
||||
{
|
||||
v.sendMessage(ChatColor.GRAY + "Point one");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
this.block = null;
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
super.parameters(par, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.set";
|
||||
}
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* @author Voxel
|
||||
*/
|
||||
public class SetRedstoneFlipBrush extends Brush
|
||||
{
|
||||
private Block block = null;
|
||||
private Undo undo;
|
||||
private boolean northSouth = true;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SetRedstoneFlipBrush()
|
||||
{
|
||||
this.setName("Set Redstone Flip");
|
||||
}
|
||||
|
||||
private boolean set(final Block bl)
|
||||
{
|
||||
if (this.block == null)
|
||||
{
|
||||
this.block = bl;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.undo = new Undo();
|
||||
final int lowX = (this.block.getX() <= bl.getX()) ? this.block.getX() : bl.getX();
|
||||
final int lowY = (this.block.getY() <= bl.getY()) ? this.block.getY() : bl.getY();
|
||||
final int lowZ = (this.block.getZ() <= bl.getZ()) ? this.block.getZ() : bl.getZ();
|
||||
final int highX = (this.block.getX() >= bl.getX()) ? this.block.getX() : bl.getX();
|
||||
final int highY = (this.block.getY() >= bl.getY()) ? this.block.getY() : bl.getY();
|
||||
final int highZ = (this.block.getZ() >= bl.getZ()) ? this.block.getZ() : bl.getZ();
|
||||
|
||||
for (int y = lowY; y <= highY; y++)
|
||||
{
|
||||
for (int x = lowX; x <= highX; x++)
|
||||
{
|
||||
for (int z = lowZ; z <= highZ; z++)
|
||||
{
|
||||
this.perform(this.clampY(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
this.block = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void perform(final AsyncBlock bl)
|
||||
{
|
||||
if (bl.getType() == Material.REPEATER)
|
||||
{
|
||||
if (this.northSouth)
|
||||
{
|
||||
if ((bl.getPropertyId() % 4) == 1)
|
||||
{
|
||||
this.undo.put(bl);
|
||||
bl.setPropertyId((bl.getPropertyId() + 2));
|
||||
}
|
||||
else if ((bl.getPropertyId() % 4) == 3)
|
||||
{
|
||||
this.undo.put(bl);
|
||||
bl.setPropertyId((bl.getPropertyId() - 2));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((bl.getPropertyId() % 4) == 2)
|
||||
{
|
||||
this.undo.put(bl);
|
||||
bl.setPropertyId((bl.getPropertyId() - 2));
|
||||
}
|
||||
else if ((bl.getPropertyId() % 4) == 0)
|
||||
{
|
||||
this.undo.put(bl);
|
||||
bl.setPropertyId((bl.getPropertyId() + 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
if (this.set(this.getTargetBlock()))
|
||||
{
|
||||
v.sendMessage(ChatColor.GRAY + "Point one");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().storeUndo(this.undo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (this.set(this.getLastBlock()))
|
||||
{
|
||||
v.sendMessage(ChatColor.GRAY + "Point one");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().storeUndo(this.undo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
this.block = null;
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
if (par[i].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Set Repeater Flip Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b setrf <direction> -- valid direction inputs are(n,s,e,world), Set the direction that you wish to flip your repeaters, defaults to north/south.");
|
||||
return;
|
||||
}
|
||||
if (par[i].startsWith("n") || par[i].startsWith("s") || par[i].startsWith("ns"))
|
||||
{
|
||||
this.northSouth = true;
|
||||
v.sendMessage(ChatColor.AQUA + "Flip direction set to north/south");
|
||||
}
|
||||
else if (par[i].startsWith("e") || par[i].startsWith("world") || par[i].startsWith("ew"))
|
||||
{
|
||||
this.northSouth = false;
|
||||
v.sendMessage(ChatColor.AQUA + "Flip direction set to east/west.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.setredstoneflip";
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* @author Voxel
|
||||
*/
|
||||
public class SetRedstoneRotateBrush extends Brush
|
||||
{
|
||||
private Block block = null;
|
||||
private Undo undo;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SetRedstoneRotateBrush()
|
||||
{
|
||||
this.setName("Set Redstone Rotate");
|
||||
}
|
||||
|
||||
private boolean set(final Block bl)
|
||||
{
|
||||
if (this.block == null)
|
||||
{
|
||||
this.block = bl;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.undo = new Undo();
|
||||
final int lowX = (this.block.getX() <= bl.getX()) ? this.block.getX() : bl.getX();
|
||||
final int lowY = (this.block.getY() <= bl.getY()) ? this.block.getY() : bl.getY();
|
||||
final int lowZ = (this.block.getZ() <= bl.getZ()) ? this.block.getZ() : bl.getZ();
|
||||
final int highX = (this.block.getX() >= bl.getX()) ? this.block.getX() : bl.getX();
|
||||
final int highY = (this.block.getY() >= bl.getY()) ? this.block.getY() : bl.getY();
|
||||
final int highZ = (this.block.getZ() >= bl.getZ()) ? this.block.getZ() : bl.getZ();
|
||||
|
||||
for (int y = lowY; y <= highY; y++)
|
||||
{
|
||||
for (int x = lowX; x <= highX; x++)
|
||||
{
|
||||
for (int z = lowZ; z <= highZ; z++)
|
||||
{
|
||||
this.perform(this.clampY(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
this.block = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void perform(final AsyncBlock bl)
|
||||
{
|
||||
if (bl.getType() == Material.REPEATER)
|
||||
{
|
||||
this.undo.put(bl);
|
||||
bl.setPropertyId((((bl.getPropertyId() % 4) + 1 < 5) ? (bl.getPropertyId() + 1) : (bl.getPropertyId() - 4)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
if (this.set(this.getTargetBlock()))
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.GRAY + "Point one");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().storeUndo(this.undo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (this.set(this.getLastBlock()))
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.GRAY + "Point one");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().storeUndo(this.undo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
this.block = null;
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
super.parameters(par, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.setredstonerotate";
|
||||
}
|
||||
}
|
161
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellBallBrush.java
Normale Datei
161
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellBallBrush.java
Normale Datei
@ -0,0 +1,161 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* THIS BRUSH SHOULD NOT USE PERFORMERS.
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Shell_Brushes
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class ShellBallBrush extends Brush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public ShellBallBrush()
|
||||
{
|
||||
this.setName("Shell Ball");
|
||||
}
|
||||
|
||||
// parameters isn't an abstract method, gilt. You can just leave it out if there are none.
|
||||
private void bShell(final SnipeData v, Block targetBlock)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final int brushSizeDoubled = 2 * brushSize;
|
||||
final int[][][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer
|
||||
final int[][][] newMaterials = new int[brushSizeDoubled + 1][brushSizeDoubled + 1][brushSizeDoubled + 1]; // Array that holds the hollowed materials
|
||||
|
||||
int blockPositionX = targetBlock.getX();
|
||||
int blockPositionY = targetBlock.getY();
|
||||
int blockPositionZ = targetBlock.getZ();
|
||||
// Log current materials into oldmats
|
||||
for (int x = 0; x <= 2 * (brushSize + 1); x++)
|
||||
{
|
||||
for (int y = 0; y <= 2 * (brushSize + 1); y++)
|
||||
{
|
||||
for (int z = 0; z <= 2 * (brushSize + 1); z++)
|
||||
{
|
||||
oldMaterials[x][y][z] = this.getBlockIdAt(blockPositionX - brushSize - 1 + x, blockPositionY - brushSize - 1 + y, blockPositionZ - brushSize - 1 + z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log current materials into newmats
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int y = 0; y <= brushSizeDoubled; y++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
newMaterials[x][y][z] = oldMaterials[x + 1][y + 1][z + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int temp;
|
||||
|
||||
// Hollow Brush Area
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int y = 0; y <= brushSizeDoubled; y++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
temp = 0;
|
||||
|
||||
if (oldMaterials[x + 1 + 1][y + 1][z + 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
if (oldMaterials[x + 1 - 1][y + 1][z + 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
if (oldMaterials[x + 1][y + 1 + 1][z + 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
if (oldMaterials[x + 1][y + 1 - 1][z + 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
if (oldMaterials[x + 1][y + 1][z + 1 + 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
if (oldMaterials[x + 1][y + 1][z + 1 - 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
|
||||
if (temp == 0)
|
||||
{
|
||||
newMaterials[x][y][z] = v.getVoxelId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the changes
|
||||
final Undo undo = new Undo();
|
||||
final double rSquared = Math.pow(brushSize + 0.5, 2);
|
||||
|
||||
for (int x = brushSizeDoubled; x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x - brushSize, 2);
|
||||
|
||||
for (int y = 0; y <= 2 * brushSize; y++)
|
||||
{
|
||||
final double ySquared = Math.pow(y - brushSize, 2);
|
||||
|
||||
for (int z = 2 * brushSize; z >= 0; z--)
|
||||
{
|
||||
if (xSquared + ySquared + Math.pow(z - brushSize, 2) <= rSquared)
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - brushSize + y, blockPositionZ - brushSize + z) != newMaterials[x][y][z])
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - brushSize + x, blockPositionY - brushSize + y, blockPositionZ - brushSize + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - brushSize + z, blockPositionX - brushSize + x, blockPositionY - brushSize + y, newMaterials[x][y][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
|
||||
// This is needed because most uses of this brush will not be sible to the sniper.
|
||||
v.owner().getPlayer().sendMessage(ChatColor.AQUA + "Shell complete.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.bShell(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.bShell(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.voxel();
|
||||
vm.replace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.shellball";
|
||||
}
|
||||
}
|
153
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellSetBrush.java
Normale Datei
153
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/ShellSetBrush.java
Normale Datei
@ -0,0 +1,153 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Shell_Brushes
|
||||
*
|
||||
* @author Piotr
|
||||
*/
|
||||
public class ShellSetBrush extends Brush
|
||||
{
|
||||
private static final int MAX_SIZE = 5000000;
|
||||
private Block block = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public ShellSetBrush()
|
||||
{
|
||||
this.setName("Shell Set");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private boolean set(final Block bl, final SnipeData v)
|
||||
{
|
||||
if (this.block == null)
|
||||
{
|
||||
this.block = bl;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.block.getWorld().getName().equals(bl.getWorld().getName()))
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "You selected points in different worlds!");
|
||||
this.block = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
final int lowX = (this.block.getX() <= bl.getX()) ? this.block.getX() : bl.getX();
|
||||
final int lowY = (this.block.getY() <= bl.getY()) ? this.block.getY() : bl.getY();
|
||||
final int lowZ = (this.block.getZ() <= bl.getZ()) ? this.block.getZ() : bl.getZ();
|
||||
final int highX = (this.block.getX() >= bl.getX()) ? this.block.getX() : bl.getX();
|
||||
final int highY = (this.block.getY() >= bl.getY()) ? this.block.getY() : bl.getY();
|
||||
final int highZ = (this.block.getZ() >= bl.getZ()) ? this.block.getZ() : bl.getZ();
|
||||
|
||||
if (Math.abs(highX - lowX) * Math.abs(highZ - lowZ) * Math.abs(highY - lowY) > MAX_SIZE)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Selection size above hardcoded limit, please use a smaller selection.");
|
||||
}
|
||||
else
|
||||
{
|
||||
final ArrayList<AsyncBlock> blocks = new ArrayList<AsyncBlock>(((Math.abs(highX - lowX) * Math.abs(highZ - lowZ) * Math.abs(highY - lowY)) / 2));
|
||||
for (int y = lowY; y <= highY; y++)
|
||||
{
|
||||
for (int x = lowX; x <= highX; x++)
|
||||
{
|
||||
for (int z = lowZ; z <= highZ; z++)
|
||||
{
|
||||
if (this.getWorld().getBlockAt(x, y, z).getTypeId() == v.getReplaceId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (this.getWorld().getBlockAt(x + 1, y, z).getTypeId() == v.getReplaceId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (this.getWorld().getBlockAt(x - 1, y, z).getTypeId() == v.getReplaceId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (this.getWorld().getBlockAt(x, y, z + 1).getTypeId() == v.getReplaceId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (this.getWorld().getBlockAt(x, y, z - 1).getTypeId() == v.getReplaceId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (this.getWorld().getBlockAt(x, y + 1, z).getTypeId() == v.getReplaceId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (this.getWorld().getBlockAt(x, y - 1, z).getTypeId() == v.getReplaceId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
blocks.add(this.getWorld().getBlockAt(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Undo undo = new Undo();
|
||||
for (final AsyncBlock currentBlock : blocks)
|
||||
{
|
||||
if (currentBlock.getTypeId() != v.getVoxelId())
|
||||
{
|
||||
undo.put(currentBlock);
|
||||
currentBlock.setTypeId(v.getVoxelId());
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
v.sendMessage(ChatColor.AQUA + "Shell complete.");
|
||||
}
|
||||
|
||||
this.block = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
if (this.set(this.getTargetBlock(), v))
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.GRAY + "Point one");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (this.set(this.getLastBlock(), v))
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.GRAY + "Point one");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.voxel();
|
||||
vm.replace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.shellset";
|
||||
}
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* THIS BRUSH SHOULD NOT USE PERFORMERS.
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Shell_Brushes
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class ShellVoxelBrush extends Brush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public ShellVoxelBrush()
|
||||
{
|
||||
this.setName("Shell Voxel");
|
||||
}
|
||||
|
||||
private void vShell(final SnipeData v, Block targetBlock)
|
||||
{
|
||||
final int brushSize = v.getBrushSize();
|
||||
final int brushSizeSquared = 2 * brushSize;
|
||||
final int[][][] oldMaterials = new int[2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1][2 * (brushSize + 1) + 1]; // Array that holds the original materials plus a buffer
|
||||
final int[][][] newMaterials = new int[2 * brushSize + 1][2 * brushSize + 1][2 * brushSize + 1]; // Array that holds the hollowed materials
|
||||
|
||||
int blockPositionX = targetBlock.getX();
|
||||
int blockPositionY = targetBlock.getY();
|
||||
int blockPositionZ = targetBlock.getZ();
|
||||
// Log current materials into oldmats
|
||||
for (int x = 0; x <= 2 * (brushSize + 1); x++)
|
||||
{
|
||||
for (int y = 0; y <= 2 * (brushSize + 1); y++)
|
||||
{
|
||||
for (int z = 0; z <= 2 * (brushSize + 1); z++)
|
||||
{
|
||||
oldMaterials[x][y][z] = this.getBlockIdAt(blockPositionX - brushSize - 1 + x, blockPositionY - brushSize - 1 + y, blockPositionZ - brushSize - 1 + z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log current materials into newmats
|
||||
for (int x = 0; x <= brushSizeSquared; x++)
|
||||
{
|
||||
for (int y = 0; y <= brushSizeSquared; y++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeSquared; z++)
|
||||
{
|
||||
newMaterials[x][y][z] = oldMaterials[x + 1][y + 1][z + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
int temp;
|
||||
|
||||
// Hollow Brush Area
|
||||
for (int x = 0; x <= brushSizeSquared; x++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeSquared; z++)
|
||||
{
|
||||
for (int y = 0; y <= brushSizeSquared; y++)
|
||||
{
|
||||
temp = 0;
|
||||
|
||||
if (oldMaterials[x + 1 + 1][z + 1][y + 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
if (oldMaterials[x + 1 - 1][z + 1][y + 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
if (oldMaterials[x + 1][z + 1 + 1][y + 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
if (oldMaterials[x + 1][z + 1 - 1][y + 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
if (oldMaterials[x + 1][z + 1][y + 1 + 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
if (oldMaterials[x + 1][z + 1][y + 1 - 1] == v.getReplaceId())
|
||||
{
|
||||
temp++;
|
||||
}
|
||||
|
||||
if (temp == 0)
|
||||
{
|
||||
newMaterials[x][z][y] = v.getVoxelId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the changes
|
||||
final Undo undo = new Undo();
|
||||
|
||||
for (int x = brushSizeSquared; x >= 0; x--)
|
||||
{
|
||||
for (int y = 0; y <= brushSizeSquared; y++)
|
||||
{
|
||||
for (int z = brushSizeSquared; z >= 0; z--)
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - brushSize + y, blockPositionZ - brushSize + z) != newMaterials[x][y][z])
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - brushSize + x, blockPositionY - brushSize + y, blockPositionZ - brushSize + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - brushSize + z, blockPositionX - brushSize + x, blockPositionY - brushSize + y, newMaterials[x][y][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
|
||||
v.owner().getPlayer().sendMessage(ChatColor.AQUA + "Shell complete.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.vShell(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.vShell(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.voxel();
|
||||
vm.replace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Shell Voxel Parameters:");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid parameter - see the info message for help.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.shellvoxel";
|
||||
}
|
||||
}
|
@ -0,0 +1,484 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.VoxelSniper;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Sign;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Overwrites signs. (Wiki:
|
||||
* http://www.voxelwiki.com/minecraft/VoxelSniper#Sign_Overwrite_Brush)
|
||||
*
|
||||
* @author Monofraps
|
||||
*/
|
||||
public class SignOverwriteBrush extends Brush
|
||||
{
|
||||
private static final int MAX_SIGN_LINE_LENGTH = 15;
|
||||
private static final int NUM_SIGN_LINES = 4;
|
||||
// these are no array indices
|
||||
private static final int SIGN_LINE_1 = 1;
|
||||
private static final int SIGN_LINE_2 = 2;
|
||||
private static final int SIGN_LINE_3 = 3;
|
||||
private static final int SIGN_LINE_4 = 4;
|
||||
private String[] signTextLines = new String[NUM_SIGN_LINES];
|
||||
private boolean[] signLinesEnabled = new boolean[NUM_SIGN_LINES];
|
||||
private boolean rangedMode = false;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SignOverwriteBrush()
|
||||
{
|
||||
this.setName("Sign Overwrite Brush");
|
||||
|
||||
clearBuffer();
|
||||
resetStates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text of a given sign.
|
||||
*
|
||||
* @param sign
|
||||
*/
|
||||
private void setSignText(final Sign sign)
|
||||
{
|
||||
for (int i = 0; i < this.signTextLines.length; i++)
|
||||
{
|
||||
if (this.signLinesEnabled[i])
|
||||
{
|
||||
sign.setLine(i, this.signTextLines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
sign.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text of the target sign if the target block is a sign.
|
||||
*
|
||||
* @param v
|
||||
*/
|
||||
private void setSingle(final SnipeData v)
|
||||
{
|
||||
if (this.getTargetBlock().getState() instanceof Sign)
|
||||
{
|
||||
setSignText((Sign) this.getTargetBlock().getState());
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Target block is not a sign.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all signs in a range of box{x=z=brushSize*2+1 ; z=voxelHeight*2+1}.
|
||||
*
|
||||
* @param v
|
||||
*/
|
||||
private void setRanged(final SnipeData v)
|
||||
{
|
||||
final int minX = getTargetBlock().getX() - v.getBrushSize();
|
||||
final int maxX = getTargetBlock().getX() + v.getBrushSize();
|
||||
final int minY = getTargetBlock().getY() - v.getVoxelHeight();
|
||||
final int maxY = getTargetBlock().getY() + v.getVoxelHeight();
|
||||
final int minZ = getTargetBlock().getZ() - v.getBrushSize();
|
||||
final int maxZ = getTargetBlock().getZ() + v.getBrushSize();
|
||||
|
||||
boolean signFound = false; // indicates whether or not a sign was set
|
||||
|
||||
for (int x = minX; x <= maxX; x++)
|
||||
{
|
||||
for (int y = minY; y <= maxY; y++)
|
||||
{
|
||||
for (int z = minZ; z <= maxZ; z++)
|
||||
{
|
||||
BlockState blockState = this.getWorld().getBlockAt(x, y, z).getState();
|
||||
if (blockState instanceof Sign)
|
||||
{
|
||||
setSignText((Sign) blockState);
|
||||
signFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!signFound)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Did not found any sign in selection box.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
if (this.rangedMode)
|
||||
{
|
||||
setRanged(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSingle(v);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (this.getTargetBlock().getState() instanceof Sign)
|
||||
{
|
||||
Sign sign = (Sign) this.getTargetBlock().getState();
|
||||
|
||||
for (int i = 0; i < this.signTextLines.length; i++)
|
||||
{
|
||||
if (this.signLinesEnabled[i])
|
||||
{
|
||||
this.signTextLines[i] = sign.getLine(i);
|
||||
}
|
||||
}
|
||||
|
||||
displayBuffer(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Target block is not a sign.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
boolean textChanged = false;
|
||||
|
||||
for (int i = 0; i < par.length; i++)
|
||||
{
|
||||
String parameter = par[i];
|
||||
|
||||
try
|
||||
{
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Sign Overwrite Brush Powder/Arrow:");
|
||||
v.sendMessage(ChatColor.BLUE + "The arrow writes the internal line buffer to the tearget sign.");
|
||||
v.sendMessage(ChatColor.BLUE + "The powder reads the text of the target sign into the internal buffer.");
|
||||
v.sendMessage(ChatColor.AQUA + "Sign Overwrite Brush Parameters:");
|
||||
v.sendMessage(ChatColor.GREEN + "-1[:(enabled|disabled)] ... " + ChatColor.BLUE + "-- Sets the text of the first sign line. (e.g. -1 Blah Blah)");
|
||||
v.sendMessage(ChatColor.GREEN + "-2[:(enabled|disabled)] ... " + ChatColor.BLUE + "-- Sets the text of the second sign line. (e.g. -2 Blah Blah)");
|
||||
v.sendMessage(ChatColor.GREEN + "-3[:(enabled|disabled)] ... " + ChatColor.BLUE + "-- Sets the text of the third sign line. (e.g. -3 Blah Blah)");
|
||||
v.sendMessage(ChatColor.GREEN + "-4[:(enabled|disabled)] ... " + ChatColor.BLUE + "-- Sets the text of the fourth sign line. (e.g. -4 Blah Blah)");
|
||||
v.sendMessage(ChatColor.GREEN + "-clear " + ChatColor.BLUE + "-- Clears the line buffer. (Alias: -c)");
|
||||
v.sendMessage(ChatColor.GREEN + "-clearall " + ChatColor.BLUE + "-- Clears the line buffer and sets all lines back to enabled. (Alias: -ca)");
|
||||
v.sendMessage(ChatColor.GREEN + "-multiple [on|off] " + ChatColor.BLUE + "-- Enables or disables ranged mode. (Alias: -m) (see Wiki for more information)");
|
||||
v.sendMessage(ChatColor.GREEN + "-save (name) " + ChatColor.BLUE + "-- Save you buffer to a file named [name]. (Alias: -s)");
|
||||
v.sendMessage(ChatColor.GREEN + "-open (name) " + ChatColor.BLUE + "-- Loads a buffer from a file named [name]. (Alias: -o)");
|
||||
}
|
||||
else if (parameter.startsWith("-1"))
|
||||
{
|
||||
textChanged = true;
|
||||
i = parseSignLineFromParam(par, SIGN_LINE_1, v, i);
|
||||
}
|
||||
else if (parameter.startsWith("-2"))
|
||||
{
|
||||
textChanged = true;
|
||||
i = parseSignLineFromParam(par, SIGN_LINE_2, v, i);
|
||||
}
|
||||
else if (parameter.startsWith("-3"))
|
||||
{
|
||||
textChanged = true;
|
||||
i = parseSignLineFromParam(par, SIGN_LINE_3, v, i);
|
||||
}
|
||||
else if (parameter.startsWith("-4"))
|
||||
{
|
||||
textChanged = true;
|
||||
i = parseSignLineFromParam(par, SIGN_LINE_4, v, i);
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("-clear") || parameter.equalsIgnoreCase("-c"))
|
||||
{
|
||||
clearBuffer();
|
||||
v.sendMessage(ChatColor.BLUE + "Internal text buffer cleard.");
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("-clearall") || parameter.equalsIgnoreCase("-ca"))
|
||||
{
|
||||
clearBuffer();
|
||||
resetStates();
|
||||
v.sendMessage(ChatColor.BLUE + "Internal text buffer cleard and states back to enabled.");
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("-multiple") || parameter.equalsIgnoreCase("-m"))
|
||||
{
|
||||
if ((i + 1) >= par.length)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + String.format("Missing parameter after %s.", parameter));
|
||||
continue;
|
||||
}
|
||||
|
||||
rangedMode = (par[++i].equalsIgnoreCase("on") || par[++i].equalsIgnoreCase("yes"));
|
||||
v.sendMessage(ChatColor.BLUE + String.format("Ranged mode is %s", ChatColor.GREEN + (rangedMode ? "enabled" : "disabled")));
|
||||
if (this.rangedMode)
|
||||
{
|
||||
v.sendMessage(ChatColor.GREEN + "Brush size set to " + ChatColor.RED + v.getBrushSize());
|
||||
v.sendMessage(ChatColor.AQUA + "Brush height set to " + ChatColor.RED + v.getVoxelHeight());
|
||||
}
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("-save") || parameter.equalsIgnoreCase("-s"))
|
||||
{
|
||||
if ((i + 1) >= par.length)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + String.format("Missing parameter after %s.", parameter));
|
||||
continue;
|
||||
}
|
||||
|
||||
String fileName = par[++i];
|
||||
saveBufferToFile(fileName, v);
|
||||
}
|
||||
else if (parameter.equalsIgnoreCase("-open") || parameter.equalsIgnoreCase("-o"))
|
||||
{
|
||||
if ((i + 1) >= par.length)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + String.format("Missing parameter after %s.", parameter));
|
||||
continue;
|
||||
}
|
||||
|
||||
String fileName = par[++i];
|
||||
loadBufferFromFile(fileName, "", v);
|
||||
textChanged = true;
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + String.format("Error while parsing parameter %s", parameter));
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (textChanged)
|
||||
{
|
||||
displayBuffer(v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses parameter input text of line [param:lineNumber].
|
||||
* Iterates though the given array until the next top level param (a parameter which starts
|
||||
* with a dash -) is found.
|
||||
*
|
||||
* @param params
|
||||
* @param lineNumber
|
||||
* @param v
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
private int parseSignLineFromParam(final String[] params, final int lineNumber, final SnipeData v, int i)
|
||||
{
|
||||
final int lineIndex = lineNumber - 1;
|
||||
final String parameter = params[i];
|
||||
|
||||
boolean statusSet = false;
|
||||
|
||||
if (parameter.contains(":"))
|
||||
{
|
||||
this.signLinesEnabled[lineIndex] = parameter.substring(parameter.indexOf(":")).equalsIgnoreCase(":enabled");
|
||||
v.sendMessage(ChatColor.BLUE + "Line " + lineNumber + " is " + ChatColor.GREEN + (this.signLinesEnabled[lineIndex] ? "enabled" : "disabled"));
|
||||
statusSet = true;
|
||||
}
|
||||
|
||||
if ((i + 1) >= params.length)
|
||||
{
|
||||
// return if the user just wanted to set the status
|
||||
if (statusSet)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
v.sendMessage(ChatColor.RED + "Warning: No text after -" + lineNumber + ". Setting buffer text to \"\" (empty string)");
|
||||
signTextLines[lineIndex] = "";
|
||||
return i;
|
||||
}
|
||||
|
||||
String newText = "";
|
||||
|
||||
// go through the array until the next top level parameter is found
|
||||
for (i++; i < params.length; i++)
|
||||
{
|
||||
final String currentParameter = params[i];
|
||||
|
||||
if (currentParameter.startsWith("-"))
|
||||
{
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
newText += currentParameter + " ";
|
||||
}
|
||||
}
|
||||
|
||||
newText = ChatColor.translateAlternateColorCodes('&', newText);
|
||||
|
||||
// remove last space or return if the string is empty and the user just wanted to set the status
|
||||
if (!newText.isEmpty() && newText.endsWith(" "))
|
||||
{
|
||||
newText = newText.substring(0, newText.length() - 1);
|
||||
}
|
||||
else if (newText.isEmpty())
|
||||
{
|
||||
if (statusSet)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
v.sendMessage(ChatColor.RED + "Warning: No text after -" + lineNumber + ". Setting buffer text to \"\" (empty string)");
|
||||
}
|
||||
|
||||
// check the line length and cut the text if needed
|
||||
if (newText.length() > MAX_SIGN_LINE_LENGTH)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Warning: Text on line " + lineNumber + " exceeds the maximum line length of " + MAX_SIGN_LINE_LENGTH + " characters. Your text will be cut.");
|
||||
newText = newText.substring(0, MAX_SIGN_LINE_LENGTH);
|
||||
}
|
||||
|
||||
this.signTextLines[lineIndex] = newText;
|
||||
return i;
|
||||
}
|
||||
|
||||
private void displayBuffer(final SnipeData v)
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Buffer text set to: ");
|
||||
for (int i = 0; i < this.signTextLines.length; i++)
|
||||
{
|
||||
v.sendMessage((this.signLinesEnabled[i] ? ChatColor.GREEN + "(E): " : ChatColor.RED + "(D): ") + ChatColor.BLACK + this.signTextLines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the buffer to file.
|
||||
*
|
||||
* @param fileName
|
||||
* @param v
|
||||
*/
|
||||
private void saveBufferToFile(final String fileName, final SnipeData v)
|
||||
{
|
||||
final File store = new File(VoxelSniper.getInstance().getDataFolder() + "/" + fileName + ".vsign");
|
||||
if (store.exists())
|
||||
{
|
||||
v.sendMessage("This file already exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
store.createNewFile();
|
||||
FileWriter outFile = new FileWriter(store);
|
||||
BufferedWriter outStream = new BufferedWriter(outFile);
|
||||
|
||||
for (int i = 0; i < this.signTextLines.length; i++)
|
||||
{
|
||||
outStream.write(String.valueOf(this.signLinesEnabled[i]) + "\n");
|
||||
outStream.write(this.signTextLines[i] + "\n");
|
||||
}
|
||||
|
||||
outStream.close();
|
||||
outFile.close();
|
||||
|
||||
v.sendMessage(ChatColor.BLUE + "File saved successfully.");
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Failed to save file. " + exception.getMessage());
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a buffer from a file.
|
||||
*
|
||||
* @param fileName
|
||||
* @param userDomain
|
||||
* @param v
|
||||
*/
|
||||
private void loadBufferFromFile(final String fileName, final String userDomain, final SnipeData v)
|
||||
{
|
||||
final File store = new File(VoxelSniper.getInstance().getDataFolder() + "/" + fileName + ".vsign");
|
||||
if (!store.exists())
|
||||
{
|
||||
v.sendMessage("This file does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
FileReader inFile = new FileReader(store);
|
||||
BufferedReader inStream = new BufferedReader(inFile);
|
||||
|
||||
for (int i = 0; i < this.signTextLines.length; i++)
|
||||
{
|
||||
this.signLinesEnabled[i] = Boolean.valueOf(inStream.readLine());
|
||||
this.signTextLines[i] = inStream.readLine();
|
||||
}
|
||||
|
||||
inStream.close();
|
||||
inFile.close();
|
||||
|
||||
v.sendMessage(ChatColor.BLUE + "File loaded successfully.");
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Failed to load file. " + exception.getMessage());
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the internal text buffer. (Sets it to empty strings)
|
||||
*/
|
||||
private void clearBuffer()
|
||||
{
|
||||
for (int i = 0; i < this.signTextLines.length; i++)
|
||||
{
|
||||
this.signTextLines[i] = "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets line enabled states to enabled.
|
||||
*/
|
||||
private void resetStates()
|
||||
{
|
||||
for (int i = 0; i < this.signLinesEnabled.length; i++)
|
||||
{
|
||||
this.signLinesEnabled[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName("Sign Overwrite Brush");
|
||||
|
||||
vm.custom(ChatColor.BLUE + "Buffer text: ");
|
||||
for (int i = 0; i < this.signTextLines.length; i++)
|
||||
{
|
||||
vm.custom((this.signLinesEnabled[i] ? ChatColor.GREEN + "(E): " : ChatColor.RED + "(D): ") + ChatColor.BLACK + this.signTextLines[i]);
|
||||
}
|
||||
|
||||
vm.custom(ChatColor.BLUE + String.format("Ranged mode is %s", ChatColor.GREEN + (rangedMode ? "enabled" : "disabled")));
|
||||
if (rangedMode)
|
||||
{
|
||||
vm.size();
|
||||
vm.height();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.signoverwrite";
|
||||
}
|
||||
}
|
47
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnipeBrush.java
Normale Datei
47
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnipeBrush.java
Normale Datei
@ -0,0 +1,47 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Snipe_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class SnipeBrush extends PerformBrush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SnipeBrush()
|
||||
{
|
||||
this.setName("Snipe");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.current.perform(this.getTargetBlock());
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.current.perform(this.getLastBlock());
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.snipe";
|
||||
}
|
||||
}
|
194
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnowConeBrush.java
Normale Datei
194
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SnowConeBrush.java
Normale Datei
@ -0,0 +1,194 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
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;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Snow_cone_brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class SnowConeBrush extends Brush
|
||||
{
|
||||
@SuppressWarnings("deprecation")
|
||||
private void addSnow(final SnipeData v, Block targetBlock)
|
||||
{
|
||||
int brushSize;
|
||||
int blockPositionX = targetBlock.getX();
|
||||
int blockPositionY = targetBlock.getY();
|
||||
int blockPositionZ = targetBlock.getZ();
|
||||
if (targetBlock.isEmpty())
|
||||
{
|
||||
brushSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
brushSize = this.clampY(blockPositionX, blockPositionY, blockPositionZ).getPropertyId() + 1;
|
||||
}
|
||||
|
||||
final int brushSizeDoubled = 2 * brushSize;
|
||||
final int[][] snowcone = new int[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Will hold block IDs
|
||||
final int[][] snowconeData = new int[brushSizeDoubled + 1][brushSizeDoubled + 1]; // Will hold data values for snowcone
|
||||
final int[][] yOffset = new int[brushSizeDoubled + 1][brushSizeDoubled + 1];
|
||||
// prime the arrays
|
||||
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
boolean flag = true;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{ // overlay
|
||||
if (flag)
|
||||
{
|
||||
if ((this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - i, blockPositionZ - brushSize + z) == 0 || this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - i, blockPositionZ - brushSize + z) == BlockTypes.SNOW.getInternalId()) && !this.getBlockAt(blockPositionX - brushSize + x, blockPositionY - i - 1, blockPositionZ - brushSize + z).isEmpty() && this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - i - 1, blockPositionZ - brushSize + z) != Material.SNOW.getId())
|
||||
{
|
||||
flag = false;
|
||||
yOffset[x][z] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
snowcone[x][z] = this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z);
|
||||
snowconeData[x][z] = this.clampY(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z).getPropertyId();
|
||||
}
|
||||
}
|
||||
|
||||
// figure out new snowheights
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
final double xSquared = Math.pow(x - brushSize, 2);
|
||||
|
||||
for (int z = 0; z <= 2 * brushSize; z++)
|
||||
{
|
||||
final double zSquared = Math.pow(z - brushSize, 2);
|
||||
final double dist = Math.pow(xSquared + zSquared, .5); // distance from center of array
|
||||
final int snowData = brushSize - (int) Math.ceil(dist);
|
||||
|
||||
if (snowData >= 0)
|
||||
{ // no funny business
|
||||
switch (snowData)
|
||||
{
|
||||
case 0:
|
||||
if (BlockTypes.get(snowcone[x][z]).getMaterial().isAir())
|
||||
{
|
||||
snowcone[x][z] = BlockTypes.SNOW.getInternalId();
|
||||
snowconeData[x][z] = 0;
|
||||
}
|
||||
break;
|
||||
case 7: // Turn largest snowtile into snowblock
|
||||
if (snowcone[x][z] == BlockTypes.SNOW.getInternalId())
|
||||
{
|
||||
snowcone[x][z] = BlockTypes.SNOW_BLOCK.getInternalId();
|
||||
snowconeData[x][z] = 0;
|
||||
}
|
||||
break;
|
||||
default: // Increase snowtile size, if smaller than target
|
||||
|
||||
if (snowData > snowconeData[x][z])
|
||||
{
|
||||
switch (BlockTypes.get(snowcone[x][z]))
|
||||
{
|
||||
case AIR:
|
||||
case CAVE_AIR:
|
||||
case VOID_AIR:
|
||||
snowconeData[x][z] = snowData;
|
||||
snowcone[x][z] = BlockTypes.SNOW.getInternalId();
|
||||
case SNOW_BLOCK:
|
||||
snowconeData[x][z] = snowData;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else if (yOffset[x][z] > 0 && snowcone[x][z] == BlockTypes.SNOW.getInternalId())
|
||||
{
|
||||
snowconeData[x][z]++;
|
||||
if (snowconeData[x][z] == 7)
|
||||
{
|
||||
snowconeData[x][z] = 0;
|
||||
snowcone[x][z] = BlockTypes.SNOW_BLOCK.getInternalId();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Undo undo = new Undo();
|
||||
|
||||
for (int x = 0; x <= brushSizeDoubled; x++)
|
||||
{
|
||||
for (int z = 0; z <= brushSizeDoubled; z++)
|
||||
{
|
||||
|
||||
if (this.getBlockIdAt(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z) != snowcone[x][z] || this.clampY(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z).getPropertyId() != snowconeData[x][z])
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - brushSize + z, blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], snowcone[x][z]);
|
||||
this.clampY(blockPositionX - brushSize + x, blockPositionY - yOffset[x][z], blockPositionZ - brushSize + z).setPropertyId(snowconeData[x][z]);
|
||||
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
switch (getTargetBlock().getType())
|
||||
{
|
||||
case SNOW:
|
||||
this.addSnow(v, this.getTargetBlock());
|
||||
break;
|
||||
default:
|
||||
Block blockAbove = getTargetBlock().getRelative(BlockFace.UP);
|
||||
if (blockAbove != null && BukkitAdapter.adapt(blockAbove.getType()).getMaterial().isAir())
|
||||
{
|
||||
addSnow(v, blockAbove);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "Error: Center block neither snow nor air.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName("Snow Cone");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Snow Cone Parameters:");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.snowcone";
|
||||
}
|
||||
}
|
@ -0,0 +1,830 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Spiral_Staircase_Brush
|
||||
*
|
||||
* @author giltwist
|
||||
*/
|
||||
public class SpiralStaircaseBrush extends Brush
|
||||
{
|
||||
private String stairtype = "block"; // "block" 1x1 blocks (default), "step" alternating step double step, "stair" staircase with blocks on corners
|
||||
private String sdirect = "c"; // "c" clockwise (default), "cc" counter-clockwise
|
||||
private String sopen = "n"; // "n" north (default), "e" east, "world" south, "world" west
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SpiralStaircaseBrush()
|
||||
{
|
||||
this.setName("Spiral Staircase");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void buildStairWell(final SnipeData v, Block targetBlock)
|
||||
{
|
||||
if (v.getVoxelHeight() < 1)
|
||||
{
|
||||
v.setVoxelHeight(1);
|
||||
v.sendMessage(ChatColor.RED + "VoxelHeight must be a natural number! Set to 1.");
|
||||
}
|
||||
|
||||
final int[][][] spiral = new int[2 * v.getBrushSize() + 1][v.getVoxelHeight()][2 * v.getBrushSize() + 1];
|
||||
|
||||
// locate first block in staircase
|
||||
// Note to self, fix these
|
||||
int startX = 0;
|
||||
int startZ = 0;
|
||||
int y = 0;
|
||||
int xOffset = 0;
|
||||
int zOffset = 0;
|
||||
int toggle = 0;
|
||||
|
||||
if (this.sdirect.equalsIgnoreCase("cc"))
|
||||
{
|
||||
if (this.sopen.equalsIgnoreCase("n"))
|
||||
{
|
||||
startX = 0;
|
||||
startZ = 2 * v.getBrushSize();
|
||||
}
|
||||
else if (this.sopen.equalsIgnoreCase("e"))
|
||||
{
|
||||
startX = 0;
|
||||
startZ = 0;
|
||||
}
|
||||
else if (this.sopen.equalsIgnoreCase("s"))
|
||||
{
|
||||
startX = 2 * v.getBrushSize();
|
||||
startZ = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
startX = 2 * v.getBrushSize();
|
||||
startZ = 2 * v.getBrushSize();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.sopen.equalsIgnoreCase("n"))
|
||||
{
|
||||
startX = 0;
|
||||
startZ = 0;
|
||||
}
|
||||
else if (this.sopen.equalsIgnoreCase("e"))
|
||||
{
|
||||
startX = 2 * v.getBrushSize();
|
||||
startZ = 0;
|
||||
}
|
||||
else if (this.sopen.equalsIgnoreCase("s"))
|
||||
{
|
||||
startX = 2 * v.getBrushSize();
|
||||
startZ = 2 * v.getBrushSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
startX = 0;
|
||||
startZ = 2 * v.getBrushSize();
|
||||
}
|
||||
}
|
||||
|
||||
while (y < v.getVoxelHeight())
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("block"))
|
||||
{
|
||||
// 1x1x1 voxel material steps
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
y++;
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("step"))
|
||||
{
|
||||
// alternating step-doublestep, uses data value to determine type
|
||||
switch (toggle)
|
||||
{
|
||||
case 0:
|
||||
toggle = 2;
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
break;
|
||||
case 1:
|
||||
toggle = 2;
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
break;
|
||||
case 2:
|
||||
toggle = 1;
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 2;
|
||||
y++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Adjust horizontal position and do stair-option array stuff
|
||||
if (startX + xOffset == 0)
|
||||
{ // All North
|
||||
if (startZ + zOffset == 0)
|
||||
{ // NORTHEAST
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
}
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
xOffset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
zOffset++;
|
||||
}
|
||||
}
|
||||
else if (startZ + zOffset == 2 * v.getBrushSize())
|
||||
{ // NORTHWEST
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
}
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
zOffset--;
|
||||
}
|
||||
else
|
||||
{
|
||||
xOffset++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // JUST PLAIN NORTH
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 5;
|
||||
y++;
|
||||
}
|
||||
zOffset--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 4;
|
||||
y++;
|
||||
}
|
||||
zOffset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (startX + xOffset == 2 * v.getBrushSize())
|
||||
{ // ALL SOUTH
|
||||
if (startZ + zOffset == 0)
|
||||
{ // SOUTHEAST
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
}
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
zOffset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
xOffset--;
|
||||
}
|
||||
}
|
||||
else if (startZ + zOffset == 2 * v.getBrushSize())
|
||||
{ // SOUTHWEST
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
}
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
xOffset--;
|
||||
}
|
||||
else
|
||||
{
|
||||
zOffset--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // JUST PLAIN SOUTH
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 4;
|
||||
y++;
|
||||
}
|
||||
zOffset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 5;
|
||||
y++;
|
||||
}
|
||||
zOffset--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (startZ + zOffset == 0)
|
||||
{ // JUST PLAIN EAST
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 2;
|
||||
y++;
|
||||
}
|
||||
xOffset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 3;
|
||||
y++;
|
||||
}
|
||||
xOffset--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // JUST PLAIN WEST
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 3;
|
||||
y++;
|
||||
}
|
||||
xOffset--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 2;
|
||||
y++;
|
||||
}
|
||||
xOffset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Undo undo = new Undo();
|
||||
// Make the changes
|
||||
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int i = v.getVoxelHeight() - 1; i >= 0; i--)
|
||||
{
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
int blockPositionX = targetBlock.getX();
|
||||
int blockPositionY = targetBlock.getY();
|
||||
int blockPositionZ = targetBlock.getZ();
|
||||
switch (spiral[x][i][z])
|
||||
{
|
||||
case 0:
|
||||
if (i != v.getVoxelHeight() - 1)
|
||||
{
|
||||
if (!((this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair")) && spiral[x][i + 1][z] == 1))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 0)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 0);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 0)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
if (this.stairtype.equalsIgnoreCase("block"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != v.getVoxelId())
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, v.getVoxelId());
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("step"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 44)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 44);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId(v.getPropertyId());
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i - 1, blockPositionZ - v.getBrushSize() + z) != v.getVoxelId())
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i - 1, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i - 1, v.getVoxelId());
|
||||
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (this.stairtype.equalsIgnoreCase("step"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 43)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 43);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId(v.getPropertyId());
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("woodstair"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 53)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 53);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId( 0);
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 67)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 67);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId( 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 53)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 53);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId((spiral[x][i][z] - 2));
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z) != 67)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY + i, 67);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z).setPropertyId((spiral[x][i][z] - 2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void digStairWell(final SnipeData v, Block targetBlock)
|
||||
{
|
||||
if (v.getVoxelHeight() < 1)
|
||||
{
|
||||
v.setVoxelHeight(1);
|
||||
v.sendMessage(ChatColor.RED + "VoxelHeight must be a natural number! Set to 1.");
|
||||
}
|
||||
|
||||
// initialize array
|
||||
final int[][][] spiral = new int[2 * v.getBrushSize() + 1][v.getVoxelHeight()][2 * v.getBrushSize() + 1];
|
||||
|
||||
// locate first block in staircase
|
||||
// Note to self, fix these
|
||||
int startX = 0;
|
||||
int startZ = 0;
|
||||
int y = 0;
|
||||
int xOffset = 0;
|
||||
int zOffset = 0;
|
||||
int toggle = 0;
|
||||
|
||||
if (this.sdirect.equalsIgnoreCase("cc"))
|
||||
{
|
||||
if (this.sopen.equalsIgnoreCase("n"))
|
||||
{
|
||||
startX = 0;
|
||||
startZ = 2 * v.getBrushSize();
|
||||
}
|
||||
else if (this.sopen.equalsIgnoreCase("e"))
|
||||
{
|
||||
startX = 0;
|
||||
startZ = 0;
|
||||
}
|
||||
else if (this.sopen.equalsIgnoreCase("s"))
|
||||
{
|
||||
startX = 2 * v.getBrushSize();
|
||||
startZ = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
startX = 2 * v.getBrushSize();
|
||||
startZ = 2 * v.getBrushSize();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.sopen.equalsIgnoreCase("n"))
|
||||
{
|
||||
startX = 0;
|
||||
startZ = 0;
|
||||
}
|
||||
else if (this.sopen.equalsIgnoreCase("e"))
|
||||
{
|
||||
startX = 2 * v.getBrushSize();
|
||||
startZ = 0;
|
||||
}
|
||||
else if (this.sopen.equalsIgnoreCase("s"))
|
||||
{
|
||||
startX = 2 * v.getBrushSize();
|
||||
startZ = 2 * v.getBrushSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
startX = 0;
|
||||
startZ = 2 * v.getBrushSize();
|
||||
}
|
||||
}
|
||||
|
||||
while (y < v.getVoxelHeight())
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("block"))
|
||||
{
|
||||
// 1x1x1 voxel material steps
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
y++;
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("step"))
|
||||
{
|
||||
// alternating step-doublestep, uses data value to determine type
|
||||
switch (toggle)
|
||||
{
|
||||
case 0:
|
||||
toggle = 2;
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 2;
|
||||
break;
|
||||
case 1:
|
||||
toggle = 2;
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 2;
|
||||
break;
|
||||
case 2:
|
||||
toggle = 1;
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
y++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Adjust horizontal position and do stair-option array stuff
|
||||
if (startX + xOffset == 0)
|
||||
{ // All North
|
||||
if (startZ + zOffset == 0)
|
||||
{ // NORTHEAST
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
}
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
xOffset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
zOffset++;
|
||||
}
|
||||
}
|
||||
else if (startZ + zOffset == 2 * v.getBrushSize())
|
||||
{ // NORTHWEST
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
}
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
zOffset--;
|
||||
}
|
||||
else
|
||||
{
|
||||
xOffset++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // JUST PLAIN NORTH
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 4;
|
||||
y++;
|
||||
}
|
||||
zOffset--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 5;
|
||||
y++;
|
||||
}
|
||||
zOffset++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (startX + xOffset == 2 * v.getBrushSize())
|
||||
{ // ALL SOUTH
|
||||
if (startZ + zOffset == 0)
|
||||
{ // SOUTHEAST
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
}
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
zOffset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
xOffset--;
|
||||
}
|
||||
}
|
||||
else if (startZ + zOffset == 2 * v.getBrushSize())
|
||||
{ // SOUTHWEST
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 1;
|
||||
}
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
xOffset--;
|
||||
}
|
||||
else
|
||||
{
|
||||
zOffset--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // JUST PLAIN SOUTH
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 5;
|
||||
y++;
|
||||
}
|
||||
zOffset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 4;
|
||||
y++;
|
||||
}
|
||||
zOffset--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (startZ + zOffset == 0)
|
||||
{ // JUST PLAIN EAST
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 3;
|
||||
y++;
|
||||
}
|
||||
xOffset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 2;
|
||||
y++;
|
||||
}
|
||||
xOffset--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // JUST PLAIN WEST
|
||||
if (this.sdirect.equalsIgnoreCase("c"))
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 2;
|
||||
y++;
|
||||
}
|
||||
xOffset--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
spiral[startX + xOffset][y][startZ + zOffset] = 3;
|
||||
y++;
|
||||
}
|
||||
xOffset++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final Undo undo = new Undo();
|
||||
// Make the changes
|
||||
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
|
||||
for (int i = v.getVoxelHeight() - 1; i >= 0; i--)
|
||||
{
|
||||
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
|
||||
int blockPositionX = targetBlock.getX();
|
||||
int blockPositionY = targetBlock.getY();
|
||||
int blockPositionZ = targetBlock.getZ();
|
||||
switch (spiral[x][i][z])
|
||||
{
|
||||
case 0:
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 0)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 0);
|
||||
break;
|
||||
case 1:
|
||||
if (this.stairtype.equalsIgnoreCase("block"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != v.getVoxelId())
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, v.getVoxelId());
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("step"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 44)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 44);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId(v.getPropertyId());
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("woodstair") || this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != v.getVoxelId())
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, v.getVoxelId());
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (this.stairtype.equalsIgnoreCase("step"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 43)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 43);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId(v.getPropertyId());
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("woodstair"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 53)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() - x, blockPositionY + i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 53);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId( 0);
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 67)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 67);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId( 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (this.stairtype.equalsIgnoreCase("woodstair"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 53)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 53);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId((spiral[x][i][z] - 2));
|
||||
}
|
||||
else if (this.stairtype.equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
if (this.getBlockIdAt(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z) != 67)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z));
|
||||
}
|
||||
this.setBlockIdAt(blockPositionZ - v.getBrushSize() + z, blockPositionX - v.getBrushSize() + x, blockPositionY - i, 67);
|
||||
this.clampY(blockPositionX - v.getBrushSize() + x, blockPositionY - i, blockPositionZ - v.getBrushSize() + z).setPropertyId((spiral[x][i][z] - 2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.digStairWell(v, this.getTargetBlock()); // make stairwell below target
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.buildStairWell(v, this.getLastBlock()); // make stairwell above target
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName("Spiral Staircase");
|
||||
vm.size();
|
||||
vm.voxel();
|
||||
vm.height();
|
||||
vm.data();
|
||||
vm.custom(ChatColor.BLUE + "Staircase type: " + this.stairtype);
|
||||
vm.custom(ChatColor.BLUE + "Staircase turns: " + this.sdirect);
|
||||
vm.custom(ChatColor.BLUE + "Staircase opens: " + this.sopen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Spiral Staircase Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sstair 'block' (default) | 'step' | 'woodstair' | 'cobblestair' -- set the type of staircase");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sstair 'c' (default) | 'cc' -- set the turning direction of staircase");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sstair 'n' (default) | 'e' | 's' | 'world' -- set the opening direction of staircase");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
if (par[i].equalsIgnoreCase("block") || par[i].equalsIgnoreCase("step") || par[i].equalsIgnoreCase("woodstair") || par[i].equalsIgnoreCase("cobblestair"))
|
||||
{
|
||||
this.stairtype = par[i];
|
||||
v.sendMessage(ChatColor.BLUE + "Staircase type: " + this.stairtype);
|
||||
}
|
||||
else if (par[i].equalsIgnoreCase("c") || par[i].equalsIgnoreCase("cc"))
|
||||
{
|
||||
this.sdirect = par[i];
|
||||
v.sendMessage(ChatColor.BLUE + "Staircase turns: " + this.sdirect);
|
||||
}
|
||||
else if (par[i].equalsIgnoreCase("n") || par[i].equalsIgnoreCase("e") || par[i].equalsIgnoreCase("s") || par[i].equalsIgnoreCase("world"))
|
||||
{
|
||||
this.sopen = par[i];
|
||||
v.sendMessage(ChatColor.BLUE + "Staircase opens: " + this.sopen);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.spiralstaircase";
|
||||
}
|
||||
}
|
@ -0,0 +1,284 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class SplatterBallBrush extends PerformBrush
|
||||
{
|
||||
private static final int GROW_PERCENT_MIN = 1;
|
||||
private static final int GROW_PERCENT_DEFAULT = 1000;
|
||||
private static final int GROW_PERCENT_MAX = 9999;
|
||||
private static final int SEED_PERCENT_MIN = 1;
|
||||
private static final int SEED_PERCENT_DEFAULT = 1000;
|
||||
private static final int SEED_PERCENT_MAX = 9999;
|
||||
private static final int SPLATREC_PERCENT_MIN = 1;
|
||||
private static final int SPLATREC_PERCENT_DEFAULT = 3;
|
||||
private static final int SPLATREC_PERCENT_MAX = 10;
|
||||
private int seedPercent; // Chance block on first pass is made active
|
||||
private int growPercent; // chance block on recursion pass is made active
|
||||
private int splatterRecursions; // How many times you grow the seeds
|
||||
private Random generator = new Random();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SplatterBallBrush()
|
||||
{
|
||||
this.setName("Splatter Ball");
|
||||
}
|
||||
|
||||
private void splatterBall(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX)
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.BLUE + "Seed percent set to: 10%");
|
||||
this.seedPercent = SEED_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX)
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.BLUE + "Growth percent set to: 10%");
|
||||
this.growPercent = GROW_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.BLUE + "Recursions set to: 3");
|
||||
this.splatterRecursions = SPLATREC_PERCENT_DEFAULT;
|
||||
}
|
||||
|
||||
final int[][][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
|
||||
// Seed the array
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent)
|
||||
{
|
||||
splat[x][y][z] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Grow the seeds
|
||||
final int gref = this.growPercent;
|
||||
final int[][][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
int growcheck;
|
||||
|
||||
for (int r = 0; r < this.splatterRecursions; r++)
|
||||
{
|
||||
this.growPercent = gref - ((gref / this.splatterRecursions) * (r));
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
tempSplat[x][y][z] = splat[x][y][z]; // prime tempsplat
|
||||
|
||||
growcheck = 0;
|
||||
if (splat[x][y][z] == 0)
|
||||
{
|
||||
if (x != 0 && splat[x - 1][y][z] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 0 && splat[x][y - 1][z] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (z != 0 && splat[x][y][z - 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (x != 2 * v.getBrushSize() && splat[x + 1][y][z] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 2 * v.getBrushSize() && splat[x][y + 1][z] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (z != 2 * v.getBrushSize() && splat[x][y][z + 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
}
|
||||
|
||||
if (growcheck >= GROW_PERCENT_MIN && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent)
|
||||
{
|
||||
tempSplat[x][y][z] = 1; // prevent bleed into splat
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// integrate tempsplat back into splat at end of iteration
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
splat[x][y][z] = tempSplat[x][y][z];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.growPercent = gref;
|
||||
// Fill 1x1x1 holes
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
if (splat[Math.max(x - 1, 0)][y][z] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y][z] == 1 && splat[x][Math.max(0, y - 1)][z] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)][z] == 1)
|
||||
{
|
||||
splat[x][y][z] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the changes
|
||||
final double rSquared = Math.pow(v.getBrushSize() + 1, 2);
|
||||
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x - v.getBrushSize() - 1, 2);
|
||||
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
final double ySquared = Math.pow(y - v.getBrushSize() - 1, 2);
|
||||
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
if (splat[x][y][z] == 1 && xSquared + ySquared + Math.pow(z - v.getBrushSize() - 1, 2) <= rSquared)
|
||||
{
|
||||
current.perform(targetBlock.getRelative(-v.getBrushSize() + x, -v.getBrushSize() + y, -v.getBrushSize() + z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.splatterBall(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.splatterBall(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX)
|
||||
{
|
||||
this.seedPercent = SEED_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX)
|
||||
{
|
||||
this.growPercent = GROW_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
this.splatterRecursions = SPLATREC_PERCENT_DEFAULT;
|
||||
}
|
||||
vm.brushName("Splatter Ball");
|
||||
vm.size();
|
||||
vm.custom(ChatColor.BLUE + "Seed percent set to: " + this.seedPercent / 100 + "%");
|
||||
vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%");
|
||||
vm.custom(ChatColor.BLUE + "Recursions set to: " + this.splatterRecursions);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Splatter Ball brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sb s[int] -- set a seed percentage (1-9999). 100 = 1% Default is 1000");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sb g[int] -- set a growth percentage (1-9999). Default is 1000");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sb r[int] -- set a recursion (1-10). Default is 3");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("s"))
|
||||
{
|
||||
final double temp = Integer.parseInt(parameter.replace("s", ""));
|
||||
|
||||
if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Seed percent set to: " + temp / 100 + "%");
|
||||
this.seedPercent = (int) temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Seed percent must be an integer 1-9999!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("g"))
|
||||
{
|
||||
final double temp = Integer.parseInt(parameter.replace("g", ""));
|
||||
|
||||
if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + temp / 100 + "%");
|
||||
this.growPercent = (int) temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Growth percent must be an integer 1-9999!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("r"))
|
||||
{
|
||||
final int temp = Integer.parseInt(parameter.replace("r", ""));
|
||||
|
||||
if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Recursions set to: " + temp);
|
||||
this.splatterRecursions = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.splatterball";
|
||||
}
|
||||
}
|
@ -0,0 +1,253 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class SplatterDiscBrush extends PerformBrush
|
||||
{
|
||||
private static final int GROW_PERCENT_MIN = 1;
|
||||
private static final int GROW_PERCENT_DEFAULT = 1000;
|
||||
private static final int GROW_PERCENT_MAX = 9999;
|
||||
private static final int SEED_PERCENT_MIN = 1;
|
||||
private static final int SEED_PERCENT_DEFAULT = 1000;
|
||||
private static final int SEED_PERCENT_MAX = 9999;
|
||||
private static final int SPLATREC_PERCENT_MIN = 1;
|
||||
private static final int SPLATREC_PERCENT_DEFAULT = 3;
|
||||
private static final int SPLATREC_PERCENT_MAX = 10;
|
||||
private int seedPercent; // Chance block on first pass is made active
|
||||
private int growPercent; // chance block on recursion pass is made active
|
||||
private int splatterRecursions; // How many times you grow the seeds
|
||||
private Random generator = new Random();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SplatterDiscBrush()
|
||||
{
|
||||
this.setName("Splatter Disc");
|
||||
}
|
||||
|
||||
private void splatterDisc(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Seed percent set to: 10%");
|
||||
this.seedPercent = SEED_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Growth percent set to: 10%");
|
||||
this.growPercent = GROW_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Recursions set to: 3");
|
||||
this.splatterRecursions = SPLATREC_PERCENT_DEFAULT;
|
||||
}
|
||||
final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
|
||||
// Seed the array
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
|
||||
if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent)
|
||||
{
|
||||
splat[x][y] = 1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// Grow the seeds
|
||||
final int gref = this.growPercent;
|
||||
int growcheck;
|
||||
final int[][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
for (int r = 0; r < this.splatterRecursions; r++)
|
||||
{
|
||||
|
||||
this.growPercent = gref - ((gref / this.splatterRecursions) * (r));
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
tempSplat[x][y] = splat[x][y]; // prime tempsplat
|
||||
|
||||
growcheck = 0;
|
||||
if (splat[x][y] == 0)
|
||||
{
|
||||
if (x != 0 && splat[x - 1][y] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 0 && splat[x][y - 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
}
|
||||
|
||||
if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent)
|
||||
{
|
||||
tempSplat[x][y] = 1; // prevent bleed into splat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// integrate tempsplat back into splat at end of iteration
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
splat[x][y] = tempSplat[x][y];
|
||||
}
|
||||
}
|
||||
}
|
||||
this.growPercent = gref;
|
||||
// Fill 1x1 holes
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
if (splat[Math.max(x - 1, 0)][y] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y] == 1 && splat[x][Math.max(0, y - 1)] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)] == 1)
|
||||
{
|
||||
splat[x][y] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the changes
|
||||
final double rSquared = Math.pow(v.getBrushSize() + 1, 2);
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
final double xSquared = Math.pow(x - v.getBrushSize() - 1, 2);
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
if (splat[x][y] == 1 && xSquared + Math.pow(y - v.getBrushSize() - 1, 2) <= rSquared)
|
||||
{
|
||||
current.perform(targetBlock.getRelative(x - v.getBrushSize(), 0, y - v.getBrushSize()));
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.splatterDisc(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.splatterDisc(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX)
|
||||
{
|
||||
this.seedPercent = SEED_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX)
|
||||
{
|
||||
this.growPercent = GROW_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
this.splatterRecursions = SPLATREC_PERCENT_DEFAULT;
|
||||
}
|
||||
vm.brushName("Splatter Disc");
|
||||
vm.size();
|
||||
vm.custom(ChatColor.BLUE + "Seed percent set to: " + this.seedPercent / 100 + "%");
|
||||
vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%");
|
||||
vm.custom(ChatColor.BLUE + "Recursions set to: " + this.splatterRecursions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Splatter Disc brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sd s[int] -- set a seed percentage (1-9999). 100 = 1% Default is 1000");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sd g[int] -- set a growth percentage (1-9999). Default is 1000");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sd r[int] -- set a recursion (1-10). Default is 3");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("s"))
|
||||
{
|
||||
final double temp = Integer.parseInt(parameter.replace("s", ""));
|
||||
if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Seed percent set to: " + temp / 100 + "%");
|
||||
this.seedPercent = (int) temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Seed percent must be an integer 1-9999!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("g"))
|
||||
{
|
||||
final double temp = Integer.parseInt(parameter.replace("g", ""));
|
||||
if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + temp / 100 + "%");
|
||||
this.growPercent = (int) temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Growth percent must be an integer 1-9999!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("r"))
|
||||
{
|
||||
final int temp = Integer.parseInt(parameter.replace("r", ""));
|
||||
if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Recursions set to: " + temp);
|
||||
this.splatterRecursions = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.splatterdisc";
|
||||
}
|
||||
}
|
@ -0,0 +1,453 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.sk89q.worldedit.blocks.BlockMaterial;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Overlay_Brush
|
||||
*
|
||||
* @author Gavjenks Splatterized blockPositionY Giltwist
|
||||
*/
|
||||
public class SplatterOverlayBrush extends PerformBrush
|
||||
{
|
||||
private static final int GROW_PERCENT_MIN = 1;
|
||||
private static final int GROW_PERCENT_DEFAULT = 1000;
|
||||
private static final int GROW_PERCENT_MAX = 9999;
|
||||
private static final int SEED_PERCENT_MIN = 1;
|
||||
private static final int SEED_PERCENT_DEFAULT = 1000;
|
||||
private static final int SEED_PERCENT_MAX = 9999;
|
||||
private static final int SPLATREC_PERCENT_MIN = 1;
|
||||
private static final int SPLATREC_PERCENT_DEFAULT = 3;
|
||||
private static final int SPLATREC_PERCENT_MAX = 10;
|
||||
private int seedPercent; // Chance block on first pass is made active
|
||||
private int growPercent; // chance block on recursion pass is made active
|
||||
private int splatterRecursions; // How many times you grow the seeds
|
||||
private int yOffset = 0;
|
||||
private boolean randomizeHeight = false;
|
||||
private Random generator = new Random();
|
||||
private int depth = 3;
|
||||
private boolean allBlocks = false;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SplatterOverlayBrush()
|
||||
{
|
||||
this.setName("Splatter Overlay");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void sOverlay(final SnipeData v)
|
||||
{
|
||||
|
||||
// Splatter Time
|
||||
final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
// Seed the array
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent)
|
||||
{
|
||||
splat[x][y] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Grow the seeds
|
||||
final int gref = this.growPercent;
|
||||
final int[][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
int growcheck;
|
||||
|
||||
for (int r = 0; r < this.splatterRecursions; r++)
|
||||
{
|
||||
this.growPercent = gref - ((gref / this.splatterRecursions) * (r));
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
tempSplat[x][y] = splat[x][y]; // prime tempsplat
|
||||
|
||||
growcheck = 0;
|
||||
if (splat[x][y] == 0)
|
||||
{
|
||||
if (x != 0 && splat[x - 1][y] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 0 && splat[x][y - 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
}
|
||||
|
||||
if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent)
|
||||
{
|
||||
tempSplat[x][y] = 1; // prevent bleed into splat
|
||||
}
|
||||
}
|
||||
}
|
||||
// integrate tempsplat back into splat at end of iteration
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
splat[x][y] = tempSplat[x][y];
|
||||
}
|
||||
}
|
||||
}
|
||||
this.growPercent = gref;
|
||||
|
||||
final int[][] memory = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2);
|
||||
|
||||
for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int y = this.getTargetBlock().getY(); y > 0; y--)
|
||||
{
|
||||
// start scanning from the height you clicked at
|
||||
if (memory[x + v.getBrushSize()][z + v.getBrushSize()] != 1)
|
||||
{
|
||||
// if haven't already found the surface in this column
|
||||
if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared && splat[x + v.getBrushSize()][z + v.getBrushSize()] == 1)
|
||||
{
|
||||
// if inside of the column && if to be splattered
|
||||
final int check = this.getBlockIdAt(this.getTargetBlock().getX() + x, y + 1, this.getTargetBlock().getZ() + z);
|
||||
if (check == 0 || check == 8 || check == 9)
|
||||
{
|
||||
// must start at surface... this prevents it filling stuff in if you click in a wall
|
||||
// and it starts out below surface.
|
||||
if (!this.allBlocks)
|
||||
{
|
||||
// if the override parameter has not been activated, go to the switch that filters out manmade stuff.
|
||||
BlockTypes type = BlockTypes.get(this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z));
|
||||
BlockMaterial mat = type.getMaterial();
|
||||
if (mat.isSolid() && mat.isFullCube() && !mat.hasContainer()) {
|
||||
final int depth = randomizeHeight ? generator.nextInt(this.depth) : this.depth;
|
||||
|
||||
for (int d = this.depth - 1; ((this.depth - d) <= depth); d--) {
|
||||
if (this.clampY(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z).getTypeId() != 0) {
|
||||
// fills down as many layers as you specify in parameters
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y - d + yOffset, this.getTargetBlock().getZ() + z));
|
||||
// stop it from checking any other blocks in this vertical 1x1 column.
|
||||
memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final int depth = randomizeHeight ? generator.nextInt(this.depth) : this.depth;
|
||||
for (int d = this.depth - 1; ((this.depth - d) <= depth); d--)
|
||||
{
|
||||
if (this.clampY(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z).getTypeId() != 0)
|
||||
{
|
||||
// fills down as many layers as you specify in parameters
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y - d + yOffset, this.getTargetBlock().getZ() + z));
|
||||
// stop it from checking any other blocks in this vertical 1x1 column.
|
||||
memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void soverlayTwo(final SnipeData v)
|
||||
{
|
||||
// Splatter Time
|
||||
final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
// Seed the array
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent)
|
||||
{
|
||||
splat[x][y] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Grow the seeds
|
||||
final int gref = this.growPercent;
|
||||
final int[][] tempsplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
int growcheck;
|
||||
|
||||
for (int r = 0; r < this.splatterRecursions; r++)
|
||||
{
|
||||
this.growPercent = gref - ((gref / this.splatterRecursions) * (r));
|
||||
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
tempsplat[x][y] = splat[x][y]; // prime tempsplat
|
||||
|
||||
growcheck = 0;
|
||||
if (splat[x][y] == 0)
|
||||
{
|
||||
if (x != 0 && splat[x - 1][y] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 0 && splat[x][y - 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
}
|
||||
|
||||
if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent)
|
||||
{
|
||||
tempsplat[x][y] = 1; // prevent bleed into splat
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// integrate tempsplat back into splat at end of iteration
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
splat[x][y] = tempsplat[x][y];
|
||||
}
|
||||
}
|
||||
}
|
||||
this.growPercent = gref;
|
||||
|
||||
final int[][] memory = new int[v.getBrushSize() * 2 + 1][v.getBrushSize() * 2 + 1];
|
||||
final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2);
|
||||
|
||||
for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int y = this.getTargetBlock().getY(); y > 0; y--)
|
||||
{ // start scanning from the height you clicked at
|
||||
if (memory[x + v.getBrushSize()][z + v.getBrushSize()] != 1)
|
||||
{ // if haven't already found the surface in this column
|
||||
if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared && splat[x + v.getBrushSize()][z + v.getBrushSize()] == 1)
|
||||
{ // if inside of the column...&& if to be splattered
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() + x, y - 1, this.getTargetBlock().getZ() + z) != 0)
|
||||
{ // if not a floating block (like one of Notch'world pools)
|
||||
if (this.getBlockIdAt(this.getTargetBlock().getX() + x, y + 1, this.getTargetBlock().getZ() + z) == 0)
|
||||
{ // must start at surface... this prevents it filling stuff in if
|
||||
// you click in a wall and it starts out below surface.
|
||||
if (!this.allBlocks)
|
||||
{ // if the override parameter has not been activated, go to the switch that filters out manmade stuff.
|
||||
|
||||
BlockTypes type = BlockTypes.get(this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z));
|
||||
BlockMaterial mat = type.getMaterial();
|
||||
if (mat.isSolid() && mat.isFullCube() && !mat.hasContainer())
|
||||
{
|
||||
final int depth = randomizeHeight ? generator.nextInt(this.depth) : this.depth;
|
||||
for (int d = 1; (d < depth + 1); d++) {
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d + yOffset, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify
|
||||
// in parameters
|
||||
memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column.
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final int depth = randomizeHeight ? generator.nextInt(this.depth) : this.depth;
|
||||
for (int d = 1; (d < depth + 1); d++)
|
||||
{
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d + yOffset, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in
|
||||
// parameters
|
||||
memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.sOverlay(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.soverlayTwo(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX)
|
||||
{
|
||||
this.seedPercent = SEED_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX)
|
||||
{
|
||||
this.growPercent = GROW_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
this.splatterRecursions = SPLATREC_PERCENT_DEFAULT;
|
||||
}
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
vm.custom(ChatColor.BLUE + "Seed percent set to: " + this.seedPercent / 100 + "%");
|
||||
vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%");
|
||||
vm.custom(ChatColor.BLUE + "Recursions set to: " + this.splatterRecursions);
|
||||
vm.custom(ChatColor.BLUE + "Y-Offset set to: " + this.yOffset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
try
|
||||
{
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Splatter Overlay brush parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "d[number] (ex: d3) How many blocks deep you want to replace from the surface.");
|
||||
v.sendMessage(ChatColor.BLUE + "all (ex: /b over all) Sets the brush to overlay over ALL materials, not just natural surface ones (will no longer ignore trees and buildings). The parameter /some will set it back to default.");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sover s[int] -- set a seed percentage (1-9999). 100 = 1% Default is 1000");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sover g[int] -- set a growth percentage (1-9999). Default is 1000");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sover r[int] -- set a recursion (1-10). Default is 3");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("d"))
|
||||
{
|
||||
this.depth = Integer.parseInt(parameter.replace("d", ""));
|
||||
v.sendMessage(ChatColor.AQUA + "Depth set to " + this.depth);
|
||||
if (this.depth < 1)
|
||||
{
|
||||
this.depth = 1;
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("all"))
|
||||
{
|
||||
this.allBlocks = true;
|
||||
v.sendMessage(ChatColor.BLUE + "Will overlay over any block." + this.depth);
|
||||
}
|
||||
else if (parameter.startsWith("some"))
|
||||
{
|
||||
this.allBlocks = false;
|
||||
v.sendMessage(ChatColor.BLUE + "Will overlay only natural block types." + this.depth);
|
||||
}
|
||||
else if (par[i].startsWith("s"))
|
||||
{
|
||||
final double temp = Integer.parseInt(parameter.replace("s", ""));
|
||||
if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Seed percent set to: " + temp / 100 + "%");
|
||||
this.seedPercent = (int) temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Seed percent must be an integer 1-9999!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("g"))
|
||||
{
|
||||
final double temp = Integer.parseInt(parameter.replace("g", ""));
|
||||
if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + temp / 100 + "%");
|
||||
this.growPercent = (int) temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Growth percent must be an integer 1-9999!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("randh"))
|
||||
{
|
||||
randomizeHeight = !randomizeHeight;
|
||||
v.sendMessage(ChatColor.RED + "RandomizeHeight set to: " + randomizeHeight);
|
||||
}
|
||||
else if (parameter.startsWith("r"))
|
||||
{
|
||||
final int temp = Integer.parseInt(parameter.replace("r", ""));
|
||||
if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Recursions set to: " + temp);
|
||||
this.splatterRecursions = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("yoff"))
|
||||
{
|
||||
final int temp = Integer.parseInt(parameter.replace("yoff", ""));
|
||||
if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Y-Offset set to: " + temp);
|
||||
this.yOffset = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
v.sendMessage(String.format("An error occured while processing parameter %s.", parameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.splatteroverlay";
|
||||
}
|
||||
}
|
@ -0,0 +1,274 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class SplatterVoxelBrush extends PerformBrush
|
||||
{
|
||||
private static final int GROW_PERCENT_MIN = 1;
|
||||
private static final int GROW_PERCENT_DEFAULT = 1000;
|
||||
private static final int GROW_PERCENT_MAX = 9999;
|
||||
private static final int SEED_PERCENT_MIN = 1;
|
||||
private static final int SEED_PERCENT_DEFAULT = 1000;
|
||||
private static final int SEED_PERCENT_MAX = 9999;
|
||||
private static final int SPLATREC_PERCENT_MIN = 1;
|
||||
private static final int SPLATREC_PERCENT_DEFAULT = 3;
|
||||
private static final int SPLATREC_PERCENT_MAX = 10;
|
||||
private int seedPercent; // Chance block on first pass is made active
|
||||
private int growPercent; // chance block on recursion pass is made active
|
||||
private int splatterRecursions; // How many times you grow the seeds
|
||||
private Random generator = new Random();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SplatterVoxelBrush()
|
||||
{
|
||||
this.setName("Splatter Voxel");
|
||||
}
|
||||
|
||||
private void vSplatterBall(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Seed percent set to: 10%");
|
||||
this.seedPercent = SEED_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Growth percent set to: 10%");
|
||||
this.growPercent = GROW_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Recursions set to: 3");
|
||||
this.splatterRecursions = SPLATREC_PERCENT_DEFAULT;
|
||||
}
|
||||
final int[][][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
|
||||
// Seed the array
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent)
|
||||
{
|
||||
splat[x][y][z] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Grow the seeds
|
||||
final int gref = this.growPercent;
|
||||
final int[][][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
int growcheck;
|
||||
|
||||
for (int r = 0; r < this.splatterRecursions; r++)
|
||||
{
|
||||
this.growPercent = gref - ((gref / this.splatterRecursions) * (r));
|
||||
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
tempSplat[x][y][z] = splat[x][y][z]; // prime tempsplat
|
||||
|
||||
growcheck = 0;
|
||||
if (splat[x][y][z] == 0)
|
||||
{
|
||||
if (x != 0 && splat[x - 1][y][z] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 0 && splat[x][y - 1][z] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (z != 0 && splat[x][y][z - 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (x != 2 * v.getBrushSize() && splat[x + 1][y][z] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 2 * v.getBrushSize() && splat[x][y + 1][z] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (z != 2 * v.getBrushSize() && splat[x][y][z + 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
}
|
||||
|
||||
if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent)
|
||||
{
|
||||
tempSplat[x][y][z] = 1; // prevent bleed into splat
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// integrate tempsplat back into splat at end of iteration
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
splat[x][y][z] = tempSplat[x][y][z];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.growPercent = gref;
|
||||
// Fill 1x1x1 holes
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
if (splat[Math.max(x - 1, 0)][y][z] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y][z] == 1 && splat[x][Math.max(0, y - 1)][z] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)][z] == 1)
|
||||
{
|
||||
splat[x][y][z] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the changes
|
||||
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
for (int z = 2 * v.getBrushSize(); z >= 0; z--)
|
||||
{
|
||||
if (splat[x][y][z] == 1)
|
||||
{
|
||||
current.perform(targetBlock.getRelative(-v.getBrushSize() + x, -v.getBrushSize() + z, -v.getBrushSize() + y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.vSplatterBall(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.vSplatterBall(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX)
|
||||
{
|
||||
this.seedPercent = SEED_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX)
|
||||
{
|
||||
this.growPercent = GROW_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
this.splatterRecursions = SPLATREC_PERCENT_DEFAULT;
|
||||
}
|
||||
vm.brushName("Splatter Voxel");
|
||||
vm.size();
|
||||
vm.custom(ChatColor.BLUE + "Seed percent set to: " + this.seedPercent / 100 + "%");
|
||||
vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%");
|
||||
vm.custom(ChatColor.BLUE + "Recursions set to: " + this.splatterRecursions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Splatter Voxel brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sv s[int] -- set a seed percentage (1-9999). 100 = 1% Default is 1000");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sv g[int] -- set a growth percentage (1-9999). Default is 1000");
|
||||
v.sendMessage(ChatColor.AQUA + "/b sv r[int] -- set a recursion (1-10). Default is 3");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("s"))
|
||||
{
|
||||
final double temp = Integer.parseInt(parameter.replace("s", ""));
|
||||
if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Seed percent set to: " + temp / 100 + "%");
|
||||
this.seedPercent = (int) temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Seed percent must be an integer 1-9999!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("g"))
|
||||
{
|
||||
final double temp = Integer.parseInt(parameter.replace("g", ""));
|
||||
if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + temp / 100 + "%");
|
||||
this.growPercent = (int) temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Growth percent must be an integer 1-9999!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("r"))
|
||||
{
|
||||
final int temp = Integer.parseInt(parameter.replace("r", ""));
|
||||
if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Recursions set to: " + temp);
|
||||
this.splatterRecursions = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.splattervoxel";
|
||||
}
|
||||
}
|
@ -0,0 +1,250 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Splatter_Brushes
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class SplatterVoxelDiscBrush extends PerformBrush
|
||||
{
|
||||
private static final int GROW_PERCENT_MIN = 1;
|
||||
private static final int GROW_PERCENT_DEFAULT = 1000;
|
||||
private static final int GROW_PERCENT_MAX = 9999;
|
||||
private static final int SEED_PERCENT_MIN = 1;
|
||||
private static final int SEED_PERCENT_DEFAULT = 1000;
|
||||
private static final int SEED_PERCENT_MAX = 9999;
|
||||
private static final int SPLATREC_PERCENT_MIN = 1;
|
||||
private static final int SPLATREC_PERCENT_DEFAULT = 3;
|
||||
private static final int SPLATREC_PERCENT_MAX = 10;
|
||||
private int seedPercent; // Chance block on first pass is made active
|
||||
private int growPercent; // chance block on recursion pass is made active
|
||||
private int splatterRecursions; // How many times you grow the seeds
|
||||
private Random generator = new Random();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public SplatterVoxelDiscBrush()
|
||||
{
|
||||
this.setName("Splatter Voxel Disc");
|
||||
}
|
||||
|
||||
private void vSplatterDisc(final SnipeData v, Block targetBlock)
|
||||
{
|
||||
if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Seed percent set to: 10%");
|
||||
this.seedPercent = SEED_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Growth percent set to: 10%");
|
||||
this.growPercent = GROW_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.BLUE + "Recursions set to: 3");
|
||||
this.splatterRecursions = SPLATREC_PERCENT_DEFAULT;
|
||||
}
|
||||
final int[][] splat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
|
||||
// Seed the array
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
if (this.generator.nextInt(SEED_PERCENT_MAX + 1) <= this.seedPercent)
|
||||
{
|
||||
splat[x][y] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Grow the seeds
|
||||
final int gref = this.growPercent;
|
||||
final int[][] tempSplat = new int[2 * v.getBrushSize() + 1][2 * v.getBrushSize() + 1];
|
||||
int growcheck;
|
||||
|
||||
for (int r = 0; r < this.splatterRecursions; r++)
|
||||
{
|
||||
this.growPercent = gref - ((gref / this.splatterRecursions) * (r));
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
tempSplat[x][y] = splat[x][y]; // prime tempsplat
|
||||
|
||||
growcheck = 0;
|
||||
if (splat[x][y] == 0)
|
||||
{
|
||||
if (x != 0 && splat[x - 1][y] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 0 && splat[x][y - 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (x != 2 * v.getBrushSize() && splat[x + 1][y] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
if (y != 2 * v.getBrushSize() && splat[x][y + 1] == 1)
|
||||
{
|
||||
growcheck++;
|
||||
}
|
||||
}
|
||||
|
||||
if (growcheck >= 1 && this.generator.nextInt(GROW_PERCENT_MAX + 1) <= this.growPercent)
|
||||
{
|
||||
tempSplat[x][y] = 1; // prevent bleed into splat
|
||||
}
|
||||
}
|
||||
}
|
||||
// integrate tempsplat back into splat at end of iteration
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
splat[x][y] = tempSplat[x][y];
|
||||
}
|
||||
}
|
||||
}
|
||||
this.growPercent = gref;
|
||||
// Fill 1x1 holes
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
if (splat[Math.max(x - 1, 0)][y] == 1 && splat[Math.min(x + 1, 2 * v.getBrushSize())][y] == 1 && splat[x][Math.max(0, y - 1)] == 1 && splat[x][Math.min(2 * v.getBrushSize(), y + 1)] == 1)
|
||||
{
|
||||
splat[x][y] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the changes
|
||||
|
||||
for (int x = 2 * v.getBrushSize(); x >= 0; x--)
|
||||
{
|
||||
for (int y = 2 * v.getBrushSize(); y >= 0; y--)
|
||||
{
|
||||
if (splat[x][y] == 1)
|
||||
{
|
||||
this.current.perform(this.clampY(targetBlock.getX() - v.getBrushSize() + x, targetBlock.getY(), targetBlock.getZ() - v.getBrushSize() + y));
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.vSplatterDisc(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.vSplatterDisc(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
if (this.seedPercent < SEED_PERCENT_MIN || this.seedPercent > SEED_PERCENT_MAX)
|
||||
{
|
||||
this.seedPercent = SEED_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.growPercent < GROW_PERCENT_MIN || this.growPercent > GROW_PERCENT_MAX)
|
||||
{
|
||||
this.growPercent = GROW_PERCENT_DEFAULT;
|
||||
}
|
||||
if (this.splatterRecursions < SPLATREC_PERCENT_MIN || this.splatterRecursions > SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
this.splatterRecursions = SPLATREC_PERCENT_DEFAULT;
|
||||
}
|
||||
vm.brushName("Splatter Voxel Disc");
|
||||
vm.size();
|
||||
vm.custom(ChatColor.BLUE + "Seed percent set to: " + this.seedPercent / 100 + "%");
|
||||
vm.custom(ChatColor.BLUE + "Growth percent set to: " + this.growPercent / 100 + "%");
|
||||
vm.custom(ChatColor.BLUE + "Recursions set to: " + this.splatterRecursions);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i];
|
||||
|
||||
if (parameter.equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Splatter Voxel Disc brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b svd s[int] -- set a seed percentage (1-9999). 100 = 1% Default is 1000");
|
||||
v.sendMessage(ChatColor.AQUA + "/b svd g[int] -- set a growth percentage (1-9999). Default is 1000");
|
||||
v.sendMessage(ChatColor.AQUA + "/b svd r[int] -- set a recursion (1-10). Default is 3");
|
||||
return;
|
||||
}
|
||||
else if (parameter.startsWith("s"))
|
||||
{
|
||||
final double temp = Integer.parseInt(parameter.replace("s", ""));
|
||||
if (temp >= SEED_PERCENT_MIN && temp <= SEED_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Seed percent set to: " + temp / 100 + "%");
|
||||
this.seedPercent = (int) temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Seed percent must be an integer 1-9999!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("g"))
|
||||
{
|
||||
final double temp = Integer.parseInt(parameter.replace("g", ""));
|
||||
if (temp >= GROW_PERCENT_MIN && temp <= GROW_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Growth percent set to: " + temp / 100 + "%");
|
||||
this.growPercent = (int) temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Growth percent must be an integer 1-9999!");
|
||||
}
|
||||
}
|
||||
else if (parameter.startsWith("r"))
|
||||
{
|
||||
final int temp = Integer.parseInt(parameter.replace("r", ""));
|
||||
if (temp >= SPLATREC_PERCENT_MIN && temp <= SPLATREC_PERCENT_MAX)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Recursions set to: " + temp);
|
||||
this.splatterRecursions = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Recursions must be an integer 1-10!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.splattervoxeldisc";
|
||||
}
|
||||
}
|
313
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplineBrush.java
Normale Datei
313
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/SplineBrush.java
Normale Datei
@ -0,0 +1,313 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* FOR ANY BRUSH THAT USES A SPLINE, EXTEND THAT BRUSH FROM THIS BRUSH!!! That way, the spline calculations are already there. Also, the UI for
|
||||
* the splines will be included.
|
||||
*
|
||||
* @author psanker
|
||||
*/
|
||||
public class SplineBrush extends PerformBrush
|
||||
{
|
||||
private final ArrayList<Block> endPts = new ArrayList<Block>();
|
||||
private final ArrayList<Block> ctrlPts = new ArrayList<Block>();
|
||||
protected ArrayList<Point> spline = new ArrayList<Point>();
|
||||
protected boolean set;
|
||||
protected boolean ctrl;
|
||||
protected String[] sparams = {"ss", "sc", "clear"};
|
||||
|
||||
public SplineBrush()
|
||||
{
|
||||
this.setName("Spline");
|
||||
}
|
||||
|
||||
public final void addToSet(final SnipeData v, final boolean ep, Block targetBlock)
|
||||
{
|
||||
if (ep)
|
||||
{
|
||||
if (this.endPts.contains(targetBlock) || this.endPts.size() == 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.endPts.add(targetBlock);
|
||||
v.sendMessage(ChatColor.GRAY + "Added block " + ChatColor.RED + "(" + targetBlock.getX() + ", " + targetBlock.getY() + ", " + targetBlock.getZ() + ") " + ChatColor.GRAY + "to endpoint selection");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.ctrlPts.contains(targetBlock) || this.ctrlPts.size() == 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.ctrlPts.add(targetBlock);
|
||||
v.sendMessage(ChatColor.GRAY + "Added block " + ChatColor.RED + "(" + targetBlock.getX() + ", " + targetBlock.getY() + ", " + targetBlock.getZ() + ") " + ChatColor.GRAY
|
||||
+ "to control point selection");
|
||||
}
|
||||
|
||||
public final void removeFromSet(final SnipeData v, final boolean ep, Block targetBlock)
|
||||
{
|
||||
if (ep)
|
||||
{
|
||||
if (!this.endPts.contains(targetBlock))
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "That block is not in the endpoint selection set.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.endPts.add(targetBlock);
|
||||
v.sendMessage(ChatColor.GRAY + "Removed block " + ChatColor.RED + "(" + targetBlock.getX() + ", " + targetBlock.getY() + ", " + targetBlock.getZ() + ") " + ChatColor.GRAY
|
||||
+ "from endpoint selection");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.ctrlPts.contains(targetBlock))
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "That block is not in the control point selection set.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.ctrlPts.remove(targetBlock);
|
||||
v.sendMessage(ChatColor.GRAY + "Removed block " + ChatColor.RED + "(" + targetBlock.getX() + ", " + targetBlock.getY() + ", " + targetBlock.getZ() + ") " + ChatColor.GRAY
|
||||
+ "from control point selection");
|
||||
}
|
||||
|
||||
public final boolean spline(final Point start, final Point end, final Point c1, final Point c2, final SnipeData v)
|
||||
{
|
||||
this.spline.clear();
|
||||
|
||||
try
|
||||
{
|
||||
final Point c = (c1.subtract(start)).multiply(3);
|
||||
final Point b = ((c2.subtract(c1)).multiply(3)).subtract(c);
|
||||
final Point a = ((end.subtract(start)).subtract(c)).subtract(b);
|
||||
|
||||
for (double t = 0.0; t < 1.0; t += 0.01)
|
||||
{
|
||||
final int px = (int) Math.round((a.getX() * (t * t * t)) + (b.getX() * (t * t)) + (c.getX() * t) + this.endPts.get(0).getX());
|
||||
final int py = (int) Math.round((a.getY() * (t * t * t)) + (b.getY() * (t * t)) + (c.getY() * t) + this.endPts.get(0).getY());
|
||||
final int pz = (int) Math.round((a.getZ() * (t * t * t)) + (b.getZ() * (t * t)) + (c.getZ() * t) + this.endPts.get(0).getZ());
|
||||
|
||||
if (!this.spline.contains(new Point(px, py, pz)))
|
||||
{
|
||||
this.spline.add(new Point(px, py, pz));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Not enough points selected; " + this.endPts.size() + " endpoints, " + this.ctrlPts.size() + " control points");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected final void render(final SnipeData v)
|
||||
{
|
||||
if (this.spline.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Point point : this.spline)
|
||||
{
|
||||
this.current.perform(this.clampY(point.getX(), point.getY(), point.getZ()));
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
if (this.set)
|
||||
{
|
||||
this.removeFromSet(v, true, this.getTargetBlock());
|
||||
}
|
||||
else if (this.ctrl)
|
||||
{
|
||||
this.removeFromSet(v, false, this.getTargetBlock());
|
||||
}
|
||||
}
|
||||
|
||||
protected final void clear(final SnipeData v)
|
||||
{
|
||||
this.spline.clear();
|
||||
this.ctrlPts.clear();
|
||||
this.endPts.clear();
|
||||
v.sendMessage(ChatColor.GRAY + "Bezier curve cleared.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (this.set)
|
||||
{
|
||||
this.addToSet(v, true, this.getTargetBlock());
|
||||
}
|
||||
if (this.ctrl)
|
||||
{
|
||||
this.addToSet(v, false, this.getTargetBlock());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
|
||||
if (this.set)
|
||||
{
|
||||
vm.custom(ChatColor.GRAY + "Endpoint selection mode ENABLED.");
|
||||
}
|
||||
else if (this.ctrl)
|
||||
{
|
||||
vm.custom(ChatColor.GRAY + "Control point selection mode ENABLED.");
|
||||
}
|
||||
else
|
||||
{
|
||||
vm.custom(ChatColor.AQUA + "No selection mode enabled.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final com.thevoxelbox.voxelsniper.SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
if (par[i].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Spline brush parameters");
|
||||
v.sendMessage(ChatColor.AQUA + "ss: Enable endpoint selection mode for desired curve");
|
||||
v.sendMessage(ChatColor.AQUA + "sc: Enable control point selection mode for desired curve");
|
||||
v.sendMessage(ChatColor.AQUA + "clear: Clear out the curve selection");
|
||||
v.sendMessage(ChatColor.AQUA + "ren: Render curve from control points");
|
||||
return;
|
||||
}
|
||||
if (par[i].equalsIgnoreCase("sc"))
|
||||
{
|
||||
if (!this.ctrl)
|
||||
{
|
||||
this.set = false;
|
||||
this.ctrl = true;
|
||||
v.sendMessage(ChatColor.GRAY + "Control point selection mode ENABLED.");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ctrl = false;
|
||||
v.sendMessage(ChatColor.AQUA + "Control point selection mode disabled.");
|
||||
}
|
||||
}
|
||||
else if (par[i].equalsIgnoreCase("ss"))
|
||||
{
|
||||
if (!this.set)
|
||||
{
|
||||
this.set = true;
|
||||
this.ctrl = false;
|
||||
v.sendMessage(ChatColor.GRAY + "Endpoint selection mode ENABLED.");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.set = false;
|
||||
v.sendMessage(ChatColor.AQUA + "Endpoint selection mode disabled.");
|
||||
}
|
||||
}
|
||||
else if (par[i].equalsIgnoreCase("clear"))
|
||||
{
|
||||
this.clear(v);
|
||||
}
|
||||
else if (par[i].equalsIgnoreCase("ren"))
|
||||
{
|
||||
if (this.spline(new Point(this.endPts.get(0)), new Point(this.endPts.get(1)), new Point(this.ctrlPts.get(0)), new Point(this.ctrlPts.get(1)), v))
|
||||
{
|
||||
this.render(v);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Vector class for splines
|
||||
protected class Point
|
||||
{
|
||||
private int x;
|
||||
private int y;
|
||||
private int z;
|
||||
|
||||
public Point(final Block b)
|
||||
{
|
||||
this.setX(b.getX());
|
||||
this.setY(b.getY());
|
||||
this.setZ(b.getZ());
|
||||
}
|
||||
|
||||
public Point(final int x, final int y, final int z)
|
||||
{
|
||||
this.setX(x);
|
||||
this.setY(y);
|
||||
this.setZ(z);
|
||||
}
|
||||
|
||||
public final Point add(final Point p)
|
||||
{
|
||||
return new Point(this.getX() + p.getX(), this.getY() + p.getY(), this.getZ() + p.getZ());
|
||||
}
|
||||
|
||||
public final Point multiply(final int scalar)
|
||||
{
|
||||
return new Point(this.getX() * scalar, this.getY() * scalar, this.getZ() * scalar);
|
||||
}
|
||||
|
||||
public final Point subtract(final Point p)
|
||||
{
|
||||
return new Point(this.getX() - p.getX(), this.getY() - p.getY(), this.getZ() - p.getZ());
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(int x)
|
||||
{
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setY(int y)
|
||||
{
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getZ()
|
||||
{
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setZ(int z)
|
||||
{
|
||||
this.z = z;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.spline";
|
||||
}
|
||||
}
|
348
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StampBrush.java
Normale Datei
348
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StampBrush.java
Normale Datei
@ -0,0 +1,348 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
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;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class StampBrush extends Brush
|
||||
{
|
||||
/**
|
||||
* @author Voxel
|
||||
*/
|
||||
protected class BlockWrapper
|
||||
{
|
||||
public int id;
|
||||
public int x;
|
||||
public int y;
|
||||
public int z;
|
||||
public int d;
|
||||
|
||||
/**
|
||||
* @param b
|
||||
* @param blx
|
||||
* @param bly
|
||||
* @param blz
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public BlockWrapper(final AsyncBlock b, final int blx, final int bly, final int blz)
|
||||
{
|
||||
this.id = b.getTypeId();
|
||||
this.d = b.getPropertyId();
|
||||
this.x = blx;
|
||||
this.y = bly;
|
||||
this.z = blz;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Monofraps
|
||||
*/
|
||||
protected enum StampType
|
||||
{
|
||||
NO_AIR, FILL, DEFAULT
|
||||
}
|
||||
|
||||
protected HashSet<BlockWrapper> clone = new HashSet<BlockWrapper>();
|
||||
protected HashSet<BlockWrapper> fall = new HashSet<BlockWrapper>();
|
||||
protected HashSet<BlockWrapper> drop = new HashSet<BlockWrapper>();
|
||||
protected HashSet<BlockWrapper> solid = new HashSet<BlockWrapper>();
|
||||
protected Undo undo;
|
||||
protected boolean sorted = false;
|
||||
|
||||
protected StampType stamp = StampType.DEFAULT;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public StampBrush()
|
||||
{
|
||||
this.setName("Stamp");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public final void reSort()
|
||||
{
|
||||
this.sorted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected final boolean falling(final int id)
|
||||
{
|
||||
return (id > 7 && id < 14);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected final boolean fallsOff(final int id)
|
||||
{
|
||||
return (BlockTypes.get(id).getMaterial().isFragileWhenPushed());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cb
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected final void setBlock(final BlockWrapper cb)
|
||||
{
|
||||
final AsyncBlock block = this.clampY(this.getTargetBlock().getX() + cb.x, this.getTargetBlock().getY() + cb.y, this.getTargetBlock().getZ() + cb.z);
|
||||
this.undo.put(block);
|
||||
block.setTypeId(cb.id);
|
||||
block.setPropertyId(cb.d);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cb
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected final void setBlockFill(final BlockWrapper cb)
|
||||
{
|
||||
final AsyncBlock block = this.clampY(this.getTargetBlock().getX() + cb.x, this.getTargetBlock().getY() + cb.y, this.getTargetBlock().getZ() + cb.z);
|
||||
if (block.isEmpty())
|
||||
{
|
||||
this.undo.put(block);
|
||||
block.setTypeId(cb.id);
|
||||
block.setPropertyId(cb.d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
*/
|
||||
protected final void setStamp(final StampType type)
|
||||
{
|
||||
this.stamp = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v
|
||||
*/
|
||||
protected final void stamp(final SnipeData v)
|
||||
{
|
||||
this.undo = new Undo();
|
||||
|
||||
if (this.sorted)
|
||||
{
|
||||
for (final BlockWrapper block : this.solid)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
for (final BlockWrapper block : this.drop)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
for (final BlockWrapper block : this.fall)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.fall.clear();
|
||||
this.drop.clear();
|
||||
this.solid.clear();
|
||||
for (final BlockWrapper block : this.clone)
|
||||
{
|
||||
if (this.fallsOff(block.id))
|
||||
{
|
||||
this.fall.add(block);
|
||||
}
|
||||
else if (this.falling(block.id))
|
||||
{
|
||||
this.drop.add(block);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.solid.add(block);
|
||||
this.setBlock(block);
|
||||
}
|
||||
}
|
||||
for (final BlockWrapper block : this.drop)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
for (final BlockWrapper block : this.fall)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
this.sorted = true;
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.undo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v
|
||||
*/
|
||||
protected final void stampFill(final SnipeData v)
|
||||
{
|
||||
|
||||
this.undo = new Undo();
|
||||
|
||||
if (this.sorted)
|
||||
{
|
||||
for (final BlockWrapper block : this.solid)
|
||||
{
|
||||
this.setBlockFill(block);
|
||||
}
|
||||
for (final BlockWrapper block : this.drop)
|
||||
{
|
||||
this.setBlockFill(block);
|
||||
}
|
||||
for (final BlockWrapper block : this.fall)
|
||||
{
|
||||
this.setBlockFill(block);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.fall.clear();
|
||||
this.drop.clear();
|
||||
this.solid.clear();
|
||||
for (final BlockWrapper block : this.clone)
|
||||
{
|
||||
if (this.fallsOff(block.id))
|
||||
{
|
||||
this.fall.add(block);
|
||||
}
|
||||
else if (this.falling(block.id))
|
||||
{
|
||||
this.drop.add(block);
|
||||
}
|
||||
else if (block.id != 0)
|
||||
{
|
||||
this.solid.add(block);
|
||||
this.setBlockFill(block);
|
||||
}
|
||||
}
|
||||
for (final BlockWrapper block : this.drop)
|
||||
{
|
||||
this.setBlockFill(block);
|
||||
}
|
||||
for (final BlockWrapper block : this.fall)
|
||||
{
|
||||
this.setBlockFill(block);
|
||||
}
|
||||
this.sorted = true;
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.undo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param v
|
||||
*/
|
||||
protected final void stampNoAir(final SnipeData v)
|
||||
{
|
||||
|
||||
this.undo = new Undo();
|
||||
|
||||
if (this.sorted)
|
||||
{
|
||||
for (final BlockWrapper block : this.solid)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
for (final BlockWrapper block : this.drop)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
for (final BlockWrapper block : this.fall)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.fall.clear();
|
||||
this.drop.clear();
|
||||
this.solid.clear();
|
||||
for (final BlockWrapper block : this.clone)
|
||||
{
|
||||
if (this.fallsOff(block.id))
|
||||
{
|
||||
this.fall.add(block);
|
||||
}
|
||||
else if (this.falling(block.id))
|
||||
{
|
||||
this.drop.add(block);
|
||||
}
|
||||
else if (block.id != 0)
|
||||
{
|
||||
this.solid.add(block);
|
||||
this.setBlock(block);
|
||||
}
|
||||
}
|
||||
for (final BlockWrapper block : this.drop)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
for (final BlockWrapper block : this.fall)
|
||||
{
|
||||
this.setBlock(block);
|
||||
}
|
||||
this.sorted = true;
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.undo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
switch (this.stamp)
|
||||
{
|
||||
case DEFAULT:
|
||||
this.stamp(v);
|
||||
break;
|
||||
|
||||
case NO_AIR:
|
||||
this.stampNoAir(v);
|
||||
break;
|
||||
|
||||
case FILL:
|
||||
this.stampFill(v);
|
||||
break;
|
||||
|
||||
default:
|
||||
v.sendMessage(ChatColor.DARK_RED + "Error while stamping! Report");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void powder(final SnipeData v)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(final Message vm)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.stamp";
|
||||
}
|
||||
}
|
461
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StencilBrush.java
Normale Datei
461
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/StencilBrush.java
Normale Datei
@ -0,0 +1,461 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.object.FaweInputStream;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
import com.boydti.fawe.object.io.PGZIPOutputStream;
|
||||
import com.google.common.io.Files;
|
||||
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;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* This is paste only currently. Assumes files exist, and thus has no usefulness until I add in saving stencils later. Uses sniper-exclusive stencil format: 3
|
||||
* shorts for X,Z,Y size of cuboid 3 shorts for X,Z,Y offsets from the -X,-Z,-Y corner. This is the reference point for pasting, corresponding to where you
|
||||
* click your brush. 1 long integer saying how many runs of blocks are in the schematic (data is compressed into runs) 1 per run: ( 1 boolean: true = compressed
|
||||
* line ahead, false = locally unique block ahead. This wastes a bit instead of a byte, and overall saves space, as long as at least 1/8 of all RUNS are going
|
||||
* to be size 1, which in Minecraft is almost definitely true. IF boolean was true, next unsigned byte stores the number of consecutive blocks of the same type,
|
||||
* up to 256. IF boolean was false, there is no byte here, goes straight to ID and data instead, which applies to just one block. 2 bytes to identify type of
|
||||
* block. First byte is ID, second is data. This applies to every one of the line of consecutive blocks if boolean was true. )
|
||||
*
|
||||
* TODO: Make limit a config option
|
||||
*
|
||||
* @author Gavjenks
|
||||
*/
|
||||
public class StencilBrush extends Brush
|
||||
{
|
||||
private byte pasteOption = 1; // 0 = full, 1 = fill, 2 = replace
|
||||
private String filename = "NoFileLoaded";
|
||||
private short x;
|
||||
private short z;
|
||||
private short y;
|
||||
private short xRef;
|
||||
private short zRef;
|
||||
private short yRef;
|
||||
private byte pasteParam = 0;
|
||||
private int[] firstPoint = new int[3];
|
||||
private int[] secondPoint = new int[3];
|
||||
private int[] pastePoint = new int[3];
|
||||
private byte point = 1;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public StencilBrush()
|
||||
{
|
||||
this.setName("Stencil");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void stencilPaste(final SnipeData v)
|
||||
{
|
||||
if (this.filename.matches("NoFileLoaded"))
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "You did not specify a filename. This is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
final Undo undo = new Undo();
|
||||
final File file = new File("plugins/VoxelSniper/stencils/" + this.filename + ".vstencil");
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
final FaweInputStream in = new FaweInputStream(new DataInputStream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(file)))));
|
||||
|
||||
this.x = in.readShort();
|
||||
this.z = in.readShort();
|
||||
this.y = in.readShort();
|
||||
|
||||
this.xRef = in.readShort();
|
||||
this.zRef = in.readShort();
|
||||
this.yRef = in.readShort();
|
||||
|
||||
final int numRuns = in.readInt();
|
||||
|
||||
int currX = -this.xRef; // so if your ref point is +5 x, you want to start pasting -5 blocks from the clicked point (the reference) to get the
|
||||
// corner, for example.
|
||||
int currZ = -this.zRef;
|
||||
int currY = -this.yRef;
|
||||
int id;
|
||||
int blockPositionX = getTargetBlock().getX();
|
||||
int blockPositionY = getTargetBlock().getY();
|
||||
int blockPositionZ = getTargetBlock().getZ();
|
||||
if (this.pasteOption == 0)
|
||||
{
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = in.readVarInt();
|
||||
for (int j = 0; j < numLoops; j++)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ));
|
||||
this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(id);
|
||||
currX++;
|
||||
if (currX == this.x - this.xRef)
|
||||
{
|
||||
currX = -this.xRef;
|
||||
currZ++;
|
||||
if (currZ == this.z - this.zRef)
|
||||
{
|
||||
currZ = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ));
|
||||
int combined = in.readVarInt();
|
||||
this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(combined);
|
||||
currX++;
|
||||
if (currX == this.x - this.xRef)
|
||||
{
|
||||
currX = -this.xRef;
|
||||
currZ++;
|
||||
if (currZ == this.z - this.zRef)
|
||||
{
|
||||
currZ = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.pasteOption == 1)
|
||||
{
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readVarInt());
|
||||
for (int j = 0; j < numLoops; j++)
|
||||
{
|
||||
|
||||
if (!BlockTypes.getFromStateId(id).getMaterial().isAir() && this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).isEmpty())
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ));
|
||||
this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(id);
|
||||
}
|
||||
currX++;
|
||||
if (currX == this.x - this.xRef)
|
||||
{
|
||||
currX = -this.xRef;
|
||||
currZ++;
|
||||
if (currZ == this.z - this.zRef)
|
||||
{
|
||||
currZ = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (in.readVarInt());
|
||||
if (!BlockTypes.getFromStateId(id).getMaterial().isAir() && this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).isEmpty())
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ));
|
||||
// v.sendMessage("currX:" + currX + " currZ:"+currZ + " currY:" + currY + " id:" + id + " data:" + data);
|
||||
this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(id);
|
||||
}
|
||||
currX++;
|
||||
if (currX == this.x - this.xRef)
|
||||
{
|
||||
currX = -this.xRef;
|
||||
currZ++;
|
||||
if (currZ == this.z - this.zRef)
|
||||
{
|
||||
currZ = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // replace
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readVarInt());
|
||||
for (int j = 0; j < (numLoops); j++)
|
||||
{
|
||||
if (!BlockTypes.getFromStateId(id).getMaterial().isAir())
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ));
|
||||
this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(id);
|
||||
}
|
||||
currX++;
|
||||
if (currX == this.x - this.xRef)
|
||||
{
|
||||
currX = -this.xRef;
|
||||
currZ++;
|
||||
if (currZ == this.z - this.zRef)
|
||||
{
|
||||
currZ = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (in.readVarInt());
|
||||
if (id != 0)
|
||||
{
|
||||
undo.put(this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ));
|
||||
this.clampY(blockPositionX + currX, blockPositionY + currY, blockPositionZ + currZ).setCombinedId(id);
|
||||
}
|
||||
currX++;
|
||||
if (currX == this.x)
|
||||
{
|
||||
currX = 0;
|
||||
currZ++;
|
||||
if (currZ == this.z)
|
||||
{
|
||||
currZ = 0;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
in.close();
|
||||
v.owner().storeUndo(undo);
|
||||
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "You need to type a stencil name / your specified stencil does not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void stencilSave(final SnipeData v)
|
||||
{
|
||||
|
||||
final File file = new File("plugins/VoxelSniper/stencils/" + this.filename + ".vstencil");
|
||||
try
|
||||
{
|
||||
this.x = (short) (Math.abs((this.firstPoint[0] - this.secondPoint[0])) + 1);
|
||||
this.z = (short) (Math.abs((this.firstPoint[1] - this.secondPoint[1])) + 1);
|
||||
this.y = (short) (Math.abs((this.firstPoint[2] - this.secondPoint[2])) + 1);
|
||||
this.xRef = (short) ((this.firstPoint[0] > this.secondPoint[0]) ? (this.pastePoint[0] - this.secondPoint[0]) : (this.pastePoint[0] - this.firstPoint[0]));
|
||||
this.zRef = (short) ((this.firstPoint[1] > this.secondPoint[1]) ? (this.pastePoint[1] - this.secondPoint[1]) : (this.pastePoint[1] - this.firstPoint[1]));
|
||||
this.yRef = (short) ((this.firstPoint[2] > this.secondPoint[2]) ? (this.pastePoint[2] - this.secondPoint[2]) : (this.pastePoint[2] - this.firstPoint[2]));
|
||||
|
||||
if ((this.x * this.y * this.z) > 50000)
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Volume exceeds maximum limit.");
|
||||
return;
|
||||
}
|
||||
|
||||
Files.createParentDirs(file);
|
||||
file.createNewFile();
|
||||
final FaweOutputStream out = new FaweOutputStream(new DataOutputStream(new PGZIPOutputStream(new BufferedOutputStream(new FileOutputStream(file)))));
|
||||
int blockPositionX = (this.firstPoint[0] > this.secondPoint[0]) ? this.secondPoint[0] : this.firstPoint[0];
|
||||
int blockPositionZ = (this.firstPoint[1] > this.secondPoint[1]) ? this.secondPoint[1] : this.firstPoint[1];
|
||||
int blockPositionY = (this.firstPoint[2] > this.secondPoint[2]) ? this.secondPoint[2] : this.firstPoint[2];
|
||||
out.writeShort(this.x);
|
||||
out.writeShort(this.z);
|
||||
out.writeShort(this.y);
|
||||
out.writeShort(this.xRef);
|
||||
out.writeShort(this.zRef);
|
||||
out.writeShort(this.yRef);
|
||||
|
||||
v.sendMessage(ChatColor.AQUA + "Volume: " + this.x * this.z * this.y + " blockPositionX:" + blockPositionX + " blockPositionZ:" + blockPositionZ + " blockPositionY:" + blockPositionY);
|
||||
|
||||
int[] blockArray = new int[this.x * this.z * this.y];
|
||||
byte[] runSizeArray = new byte[this.x * this.z * this.y];
|
||||
|
||||
int lastId = (this.getWorld().getBlockAt(blockPositionX, blockPositionY, blockPositionZ).getCombinedId());
|
||||
int thisId;
|
||||
int counter = 0;
|
||||
int arrayIndex = 0;
|
||||
for (int y = 0; y < this.y; y++)
|
||||
{
|
||||
for (int z = 0; z < this.z; z++)
|
||||
{
|
||||
for (int x = 0; x < this.x; x++)
|
||||
{
|
||||
AsyncBlock currentBlock = getWorld().getBlockAt(blockPositionX + x, blockPositionY + y, blockPositionZ + z);
|
||||
thisId = (currentBlock.getCombinedId());
|
||||
if (thisId != lastId || counter == 255)
|
||||
{
|
||||
blockArray[arrayIndex] = lastId;
|
||||
runSizeArray[arrayIndex] = (byte) (counter - 128);
|
||||
arrayIndex++;
|
||||
counter = 1;
|
||||
lastId = thisId;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter++;
|
||||
lastId = thisId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
blockArray[arrayIndex] = lastId; // saving last run, which will always be left over.
|
||||
runSizeArray[arrayIndex] = (byte) (counter - 128);
|
||||
|
||||
out.writeInt(arrayIndex + 1);
|
||||
// v.sendMessage("number of runs = " + arrayIndex);
|
||||
for (int i = 0; i < arrayIndex + 1; i++)
|
||||
{
|
||||
if (runSizeArray[i] > -127)
|
||||
{
|
||||
out.writeBoolean(true);
|
||||
out.writeByte(runSizeArray[i]);
|
||||
out.writeVarInt(blockArray[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.writeBoolean(false);
|
||||
out.writeVarInt(blockArray[i]);
|
||||
}
|
||||
}
|
||||
|
||||
v.sendMessage(ChatColor.BLUE + "Saved as '" + this.filename + "'.");
|
||||
out.close();
|
||||
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{ // will be used to copy/save later on?
|
||||
if (this.point == 1)
|
||||
{
|
||||
this.firstPoint[0] = this.getTargetBlock().getX();
|
||||
this.firstPoint[1] = this.getTargetBlock().getZ();
|
||||
this.firstPoint[2] = this.getTargetBlock().getY();
|
||||
v.sendMessage(ChatColor.GRAY + "First point");
|
||||
v.sendMessage("X:" + this.firstPoint[0] + " Z:" + this.firstPoint[1] + " Y:" + this.firstPoint[2]);
|
||||
this.point = 2;
|
||||
}
|
||||
else if (this.point == 2)
|
||||
{
|
||||
this.secondPoint[0] = this.getTargetBlock().getX();
|
||||
this.secondPoint[1] = this.getTargetBlock().getZ();
|
||||
this.secondPoint[2] = this.getTargetBlock().getY();
|
||||
if ((Math.abs(this.firstPoint[0] - this.secondPoint[0]) * Math.abs(this.firstPoint[1] - this.secondPoint[1]) * Math.abs(this.firstPoint[2] - this.secondPoint[2])) > 5000000)
|
||||
{
|
||||
v.sendMessage(ChatColor.DARK_RED + "Area selected is too large. (Limit is 5,000,000 blocks)");
|
||||
this.point = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.GRAY + "Second point");
|
||||
v.sendMessage("X:" + this.secondPoint[0] + " Z:" + this.secondPoint[1] + " Y:" + this.secondPoint[2]);
|
||||
this.point = 3;
|
||||
}
|
||||
}
|
||||
else if (this.point == 3)
|
||||
{
|
||||
this.pastePoint[0] = this.getTargetBlock().getX();
|
||||
this.pastePoint[1] = this.getTargetBlock().getZ();
|
||||
this.pastePoint[2] = this.getTargetBlock().getY();
|
||||
v.sendMessage(ChatColor.GRAY + "Paste Reference point");
|
||||
v.sendMessage("X:" + this.pastePoint[0] + " Z:" + this.pastePoint[1] + " Y:" + this.pastePoint[2]);
|
||||
this.point = 1;
|
||||
|
||||
this.stencilSave(v);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{ // will be used to paste later on
|
||||
this.stencilPaste(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom("File loaded: " + this.filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Stencil brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b schem [optional: 'full' 'fill' or 'replace', with fill as default] [name] -- Loads the specified schematic. Allowed size of schematic is based on rank. Full/fill/replace must come first. Full = paste all blocks, fill = paste only into air blocks, replace = paste full blocks in only, but replace anything in their way.");
|
||||
v.sendMessage(ChatColor.BLUE + "Size of the stencils you are allowed to paste depends on rank (member / lite, sniper, curator, admin)");
|
||||
return;
|
||||
}
|
||||
else if (par[1].equalsIgnoreCase("full"))
|
||||
{
|
||||
this.pasteOption = 0;
|
||||
this.pasteParam = 1;
|
||||
}
|
||||
else if (par[1].equalsIgnoreCase("fill"))
|
||||
{
|
||||
this.pasteOption = 1;
|
||||
this.pasteParam = 1;
|
||||
}
|
||||
else if (par[1].equalsIgnoreCase("replace"))
|
||||
{
|
||||
this.pasteOption = 2;
|
||||
this.pasteParam = 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
this.filename = par[1 + this.pasteParam];
|
||||
final File file = new File("plugins/VoxelSniper/stencils/" + this.filename + ".vstencil");
|
||||
if (file.exists())
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Stencil '" + this.filename + "' exists and was loaded. Make sure you are using powder if you do not want any chance of overwriting the file.");
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Stencil '" + this.filename + "' does not exist. Ready to be saved to, but cannot be pasted.");
|
||||
}
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "You need to type a stencil name.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.stencil";
|
||||
}
|
||||
}
|
@ -0,0 +1,984 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* @author Gavjenks
|
||||
*/
|
||||
public class StencilListBrush extends Brush
|
||||
{
|
||||
private byte pasteOption = 1; // 0 = full, 1 = fill, 2 = replace
|
||||
private String filename = "NoFileLoaded";
|
||||
private short x;
|
||||
private short z;
|
||||
private short y;
|
||||
private short xRef;
|
||||
private short zRef;
|
||||
private short yRef;
|
||||
private byte pasteParam = 0;
|
||||
private HashMap<Integer, String> stencilList = new HashMap<Integer, String>();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public StencilListBrush()
|
||||
{
|
||||
this.setName("StencilList");
|
||||
}
|
||||
|
||||
private String readRandomStencil(final SnipeData v)
|
||||
{
|
||||
double rand = Math.random() * (this.stencilList.size());
|
||||
final int choice = (int) rand;
|
||||
return this.stencilList.get(choice);
|
||||
}
|
||||
|
||||
private void readStencilList(final String listname, final SnipeData v)
|
||||
{
|
||||
final File file = new File("plugins/VoxelSniper/stencilLists/" + this.filename + ".txt");
|
||||
if (file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
final Scanner scanner = new Scanner(file);
|
||||
int counter = 0;
|
||||
while (scanner.hasNext())
|
||||
{
|
||||
this.stencilList.put(counter, scanner.nextLine());
|
||||
counter++;
|
||||
}
|
||||
scanner.close();
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void stencilPaste(final SnipeData v)
|
||||
{
|
||||
if (this.filename.matches("NoFileLoaded"))
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "You did not specify a filename for the list. This is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
final String stencilName = this.readRandomStencil(v);
|
||||
v.sendMessage(stencilName);
|
||||
|
||||
final Undo undo = new Undo();
|
||||
final File file = new File("plugins/VoxelSniper/stencils/" + stencilName + ".vstencil");
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
|
||||
|
||||
this.x = in.readShort();
|
||||
this.z = in.readShort();
|
||||
this.y = in.readShort();
|
||||
|
||||
this.xRef = in.readShort();
|
||||
this.zRef = in.readShort();
|
||||
this.yRef = in.readShort();
|
||||
|
||||
final int numRuns = in.readInt();
|
||||
// Something here that checks ranks using sanker'world thingie he added to Sniper and boots you out with error message if too big.
|
||||
final int volume = this.x * this.y * this.z;
|
||||
v.owner().getPlayer().sendMessage(ChatColor.AQUA + this.filename + " pasted. Volume is " + volume + " blocks.");
|
||||
|
||||
int currX = -this.xRef; // so if your ref point is +5 x, you want to start pasting -5 blocks from the clicked point (the reference) to get the
|
||||
// corner, for example.
|
||||
int currZ = -this.zRef;
|
||||
int currY = -this.yRef;
|
||||
int id;
|
||||
int data;
|
||||
if (this.pasteOption == 0)
|
||||
{
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < numLoops; j++)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
currX++;
|
||||
if (currX == this.x - this.xRef)
|
||||
{
|
||||
currX = -this.xRef;
|
||||
currZ++;
|
||||
if (currZ == this.z - this.zRef)
|
||||
{
|
||||
currZ = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId((in.readByte() + 128), (in.readByte() + 128), false);
|
||||
currX++;
|
||||
if (currX == this.x - this.xRef)
|
||||
{
|
||||
currX = -this.xRef;
|
||||
currZ++;
|
||||
if (currZ == this.z - this.zRef)
|
||||
{
|
||||
currZ = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.pasteOption == 1)
|
||||
{
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < numLoops; j++)
|
||||
{
|
||||
if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false);
|
||||
}
|
||||
currX++;
|
||||
if (currX == this.x - this.xRef)
|
||||
{
|
||||
currX = -this.xRef;
|
||||
currZ++;
|
||||
if (currZ == this.z - this.zRef)
|
||||
{
|
||||
currZ = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false);
|
||||
}
|
||||
currX++;
|
||||
if (currX == this.x - this.xRef)
|
||||
{
|
||||
currX = -this.xRef;
|
||||
currZ++;
|
||||
if (currZ == this.z - this.zRef)
|
||||
{
|
||||
currZ = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // replace
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < (numLoops); j++)
|
||||
{
|
||||
if (id != 0)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
}
|
||||
currX++;
|
||||
if (currX == this.x - this.xRef)
|
||||
{
|
||||
currX = -this.xRef;
|
||||
currZ++;
|
||||
if (currZ == this.z - this.zRef)
|
||||
{
|
||||
currZ = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
if (id != 0)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
}
|
||||
currX++;
|
||||
if (currX == this.x)
|
||||
{
|
||||
currX = 0;
|
||||
currZ++;
|
||||
if (currZ == this.z)
|
||||
{
|
||||
currZ = 0;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
in.close();
|
||||
v.owner().storeUndo(undo);
|
||||
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "You need to type a stencil name / your specified stencil does not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void stencilPaste180(final SnipeData v)
|
||||
{
|
||||
if (this.filename.matches("NoFileLoaded"))
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "You did not specify a filename for the list. This is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
final String stencilName = this.readRandomStencil(v);
|
||||
|
||||
final Undo undo = new Undo();
|
||||
final File file = new File("plugins/VoxelSniper/stencils/" + stencilName + ".vstencil");
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
|
||||
|
||||
this.x = in.readShort();
|
||||
this.z = in.readShort();
|
||||
this.y = in.readShort();
|
||||
|
||||
this.xRef = in.readShort();
|
||||
this.zRef = in.readShort();
|
||||
this.yRef = in.readShort();
|
||||
|
||||
final int numRuns = in.readInt();
|
||||
// Something here that checks ranks using sanker'world thingie he added to Sniper and boots you out with error message if too big.
|
||||
final int volume = this.x * this.y * this.z;
|
||||
v.owner().getPlayer().sendMessage(ChatColor.AQUA + this.filename + " pasted. Volume is " + volume + " blocks.");
|
||||
|
||||
int currX = +this.xRef; // so if your ref point is +5 x, you want to start pasting -5 blocks from the clicked point (the reference) to get the
|
||||
// corner, for example.
|
||||
int currZ = +this.zRef;
|
||||
int currY = -this.yRef;
|
||||
int id;
|
||||
int data;
|
||||
if (this.pasteOption == 0)
|
||||
{
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < numLoops; j++)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
currX--;
|
||||
if (currX == -this.x + this.xRef)
|
||||
{
|
||||
currX = this.xRef;
|
||||
currZ--;
|
||||
if (currZ == -this.z + this.zRef)
|
||||
{
|
||||
currZ = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId((in.readByte() + 128), (in.readByte() + 128), false);
|
||||
currX--;
|
||||
if (currX == -this.x + this.xRef)
|
||||
{
|
||||
currX = this.xRef;
|
||||
currZ--;
|
||||
if (currZ == -this.z + this.zRef)
|
||||
{
|
||||
currZ = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.pasteOption == 1)
|
||||
{
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < numLoops; j++)
|
||||
{
|
||||
if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false);
|
||||
}
|
||||
currX--;
|
||||
if (currX == -this.x + this.xRef)
|
||||
{
|
||||
currX = this.xRef;
|
||||
currZ--;
|
||||
if (currZ == -this.z + this.zRef)
|
||||
{
|
||||
currZ = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false);
|
||||
}
|
||||
currX--;
|
||||
if (currX == -this.x + this.xRef)
|
||||
{
|
||||
currX = this.xRef;
|
||||
currZ--;
|
||||
if (currZ == -this.z + this.zRef)
|
||||
{
|
||||
currZ = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // replace
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < (numLoops); j++)
|
||||
{
|
||||
if (id != 0)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
}
|
||||
currX--;
|
||||
if (currX == -this.x + this.xRef)
|
||||
{
|
||||
currX = this.xRef;
|
||||
currZ--;
|
||||
if (currZ == -this.z + this.zRef)
|
||||
{
|
||||
currZ = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
if (id != 0)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
}
|
||||
currX--;
|
||||
if (currX == -this.x + this.xRef)
|
||||
{
|
||||
currX = this.xRef;
|
||||
currZ--;
|
||||
if (currZ == -this.z + this.zRef)
|
||||
{
|
||||
currZ = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
in.close();
|
||||
v.owner().storeUndo(undo);
|
||||
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "You need to type a stencil name / your specified stencil does not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void stencilPaste270(final SnipeData v)
|
||||
{
|
||||
if (this.filename.matches("NoFileLoaded"))
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "You did not specify a filename for the list. This is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
final String stencilName = this.readRandomStencil(v);
|
||||
|
||||
final Undo undo = new Undo();
|
||||
final File file = new File("plugins/VoxelSniper/stencils/" + stencilName + ".vstencil");
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
|
||||
|
||||
this.x = in.readShort();
|
||||
this.z = in.readShort();
|
||||
this.y = in.readShort();
|
||||
|
||||
this.xRef = in.readShort();
|
||||
this.zRef = in.readShort();
|
||||
this.yRef = in.readShort();
|
||||
|
||||
final int numRuns = in.readInt();
|
||||
// Something here that checks ranks using sanker'world thingie he added to Sniper and boots you out with error message if too big.
|
||||
final int volume = this.x * this.y * this.z;
|
||||
v.owner().getPlayer().sendMessage(ChatColor.AQUA + this.filename + " pasted. Volume is " + volume + " blocks.");
|
||||
|
||||
int currX = +this.zRef; // so if your ref point is +5 x, you want to start pasting -5 blocks from the clicked point (the reference) to get the
|
||||
// corner, for example.
|
||||
int currZ = -this.xRef;
|
||||
int currY = -this.yRef;
|
||||
int id;
|
||||
int data;
|
||||
if (this.pasteOption == 0)
|
||||
{
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < numLoops; j++)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
currZ++;
|
||||
if (currZ == this.x - this.xRef)
|
||||
{
|
||||
currZ = -this.xRef;
|
||||
currX--;
|
||||
if (currX == -this.z + this.zRef)
|
||||
{
|
||||
currX = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId((in.readByte() + 128), (in.readByte() + 128), false);
|
||||
currZ++;
|
||||
currZ++;
|
||||
if (currZ == this.x - this.xRef)
|
||||
{
|
||||
currZ = -this.xRef;
|
||||
currX--;
|
||||
if (currX == -this.z + this.zRef)
|
||||
{
|
||||
currX = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.pasteOption == 1)
|
||||
{
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < numLoops; j++)
|
||||
{
|
||||
if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty())
|
||||
{ // no reason to paste air over
|
||||
// air, and it prevents us
|
||||
// most of the time from
|
||||
// having to even check the
|
||||
// block.
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false);
|
||||
}
|
||||
currZ++;
|
||||
if (currZ == this.x - this.xRef)
|
||||
{
|
||||
currZ = -this.xRef;
|
||||
currX--;
|
||||
if (currX == -this.z + this.zRef)
|
||||
{
|
||||
currX = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty())
|
||||
{ // no reason to paste air over
|
||||
// air, and it prevents us most of
|
||||
// the time from having to even
|
||||
// check the block.
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false);
|
||||
}
|
||||
currZ++;
|
||||
if (currZ == this.x - this.xRef)
|
||||
{
|
||||
currZ = -this.xRef;
|
||||
currX--;
|
||||
if (currX == -this.z + this.zRef)
|
||||
{
|
||||
currX = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // replace
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < (numLoops); j++)
|
||||
{
|
||||
if (id != 0)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
}
|
||||
currZ++;
|
||||
if (currZ == this.x - this.xRef)
|
||||
{
|
||||
currZ = -this.xRef;
|
||||
currX--;
|
||||
if (currX == -this.z + this.zRef)
|
||||
{
|
||||
currX = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
if (id != 0)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
}
|
||||
currZ++;
|
||||
if (currZ == this.x - this.xRef)
|
||||
{
|
||||
currZ = -this.xRef;
|
||||
currX--;
|
||||
if (currX == -this.z + this.zRef)
|
||||
{
|
||||
currX = +this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
in.close();
|
||||
v.owner().storeUndo(undo);
|
||||
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "You need to type a stencil name / your specified stencil does not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void stencilPaste90(final SnipeData v)
|
||||
{
|
||||
if (this.filename.matches("NoFileLoaded"))
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "You did not specify a filename for the list. This is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
final String stencilName = this.readRandomStencil(v);
|
||||
|
||||
final Undo undo = new Undo();
|
||||
final File file = new File("plugins/VoxelSniper/stencils/" + stencilName + ".vstencil");
|
||||
|
||||
if (file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
|
||||
|
||||
this.x = in.readShort();
|
||||
this.z = in.readShort();
|
||||
this.y = in.readShort();
|
||||
|
||||
this.xRef = in.readShort();
|
||||
this.zRef = in.readShort();
|
||||
this.yRef = in.readShort();
|
||||
|
||||
final int numRuns = in.readInt();
|
||||
// Something here that checks ranks using sanker'world thingie he added to Sniper and boots you out with error message if too big.
|
||||
final int volume = this.x * this.y * this.z;
|
||||
v.sendMessage(ChatColor.AQUA + this.filename + " pasted. Volume is " + volume + " blocks.");
|
||||
|
||||
int currX = -this.zRef; // so if your ref point is +5 x, you want to start pasting -5 blocks from the clicked point (the reference) to get the
|
||||
// corner, for example.
|
||||
int currZ = +this.xRef;
|
||||
int currY = -this.yRef;
|
||||
int id;
|
||||
int data;
|
||||
if (this.pasteOption == 0)
|
||||
{
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < numLoops; j++)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
currZ--;
|
||||
if (currZ == -this.x + this.xRef)
|
||||
{
|
||||
currZ = this.xRef;
|
||||
currX++;
|
||||
if (currX == this.z - this.zRef)
|
||||
{
|
||||
currX = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId((in.readByte() + 128), (in.readByte() + 128), false);
|
||||
currZ--;
|
||||
if (currZ == -this.x + this.xRef)
|
||||
{
|
||||
currZ = this.xRef;
|
||||
currX++;
|
||||
if (currX == this.z - this.zRef)
|
||||
{
|
||||
currX = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.pasteOption == 1)
|
||||
{
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < numLoops; j++)
|
||||
{
|
||||
if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false);
|
||||
}
|
||||
currZ--;
|
||||
if (currZ == -this.x + this.xRef)
|
||||
{
|
||||
currZ = this.xRef;
|
||||
currX++;
|
||||
if (currX == this.z - this.zRef)
|
||||
{
|
||||
currX = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
if (id != 0 && this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).isEmpty())
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, (data), false);
|
||||
}
|
||||
currZ--;
|
||||
if (currZ == -this.x + this.xRef)
|
||||
{
|
||||
currZ = this.xRef;
|
||||
currX++;
|
||||
if (currX == this.z - this.zRef)
|
||||
{
|
||||
currX = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // replace
|
||||
for (int i = 1; i < numRuns + 1; i++)
|
||||
{
|
||||
if (in.readBoolean())
|
||||
{
|
||||
final int numLoops = in.readByte() + 128;
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
for (int j = 0; j < (numLoops); j++)
|
||||
{
|
||||
if (id != 0)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
}
|
||||
currZ--;
|
||||
if (currZ == -this.x + this.xRef)
|
||||
{
|
||||
currZ = this.xRef;
|
||||
currX++;
|
||||
if (currX == this.z - this.zRef)
|
||||
{
|
||||
currX = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
id = (in.readByte() + 128);
|
||||
data = (in.readByte() + 128);
|
||||
if (id != 0)
|
||||
{
|
||||
undo.put(this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ));
|
||||
this.clampY(this.getTargetBlock().getX() + currX, this.getTargetBlock().getY() + currY, this.getTargetBlock().getZ() + currZ).setTypeIdAndPropertyId(id, data, false);
|
||||
}
|
||||
currZ--;
|
||||
if (currZ == -this.x + this.xRef)
|
||||
{
|
||||
currZ = this.xRef;
|
||||
currX++;
|
||||
if (currX == this.z - this.zRef)
|
||||
{
|
||||
currX = -this.zRef;
|
||||
currY++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
in.close();
|
||||
v.owner().storeUndo(undo);
|
||||
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Something went wrong.");
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "You need to type a stencil name / your specified stencil does not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
private void stencilPasteRotation(final SnipeData v)
|
||||
{
|
||||
// just randomly chooses a rotation and then calls stencilPaste.
|
||||
this.readStencilList(this.filename, v);
|
||||
final double random = Math.random();
|
||||
if (random < 0.26)
|
||||
{
|
||||
this.stencilPaste(v);
|
||||
}
|
||||
else if (random < 0.51)
|
||||
{
|
||||
this.stencilPaste90(v);
|
||||
}
|
||||
else if (random < 0.76)
|
||||
{
|
||||
this.stencilPaste180(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.stencilPaste270(v);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.stencilPaste(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.stencilPasteRotation(v);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.custom("File loaded: " + this.filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Stencil List brush Parameters:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b schem [optional: 'full' 'fill' or 'replace', with fill as default] [name] -- Loads the specified stencil list. Full/fill/replace must come first. Full = paste all blocks, fill = paste only into air blocks, replace = paste full blocks in only, but replace anything in their way.");
|
||||
return;
|
||||
}
|
||||
else if (par[1].equalsIgnoreCase("full"))
|
||||
{
|
||||
this.pasteOption = 0;
|
||||
this.pasteParam = 1;
|
||||
}
|
||||
else if (par[1].equalsIgnoreCase("fill"))
|
||||
{
|
||||
this.pasteOption = 1;
|
||||
this.pasteParam = 1;
|
||||
}
|
||||
else if (par[1].equalsIgnoreCase("replace"))
|
||||
{
|
||||
this.pasteOption = 2;
|
||||
this.pasteParam = 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
this.filename = par[1 + this.pasteParam];
|
||||
final File file = new File("plugins/VoxelSniper/stencilLists/" + this.filename + ".txt");
|
||||
if (file.exists())
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "Stencil List '" + this.filename + "' exists and was loaded.");
|
||||
this.readStencilList(this.filename, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.sendMessage(ChatColor.AQUA + "Stencil List '" + this.filename + "' does not exist. This brush will not function without a valid stencil list.");
|
||||
this.filename = "NoFileLoaded";
|
||||
}
|
||||
}
|
||||
catch (final Exception exception)
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "You need to type a stencil name.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.stencillist";
|
||||
}
|
||||
}
|
@ -0,0 +1,238 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Three-Point_Circle_Brush
|
||||
*
|
||||
* @author Giltwist
|
||||
*/
|
||||
public class ThreePointCircleBrush extends PerformBrush
|
||||
{
|
||||
private Vector coordsOne;
|
||||
private Vector coordsTwo;
|
||||
private Vector coordsThree;
|
||||
private Tolerance tolerance = Tolerance.DEFAULT;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
public ThreePointCircleBrush()
|
||||
{
|
||||
this.setName("3-Point Circle");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
if (this.coordsOne == null)
|
||||
{
|
||||
this.coordsOne = this.getTargetBlock().getLocation().toVector();
|
||||
v.sendMessage(ChatColor.GRAY + "First Corner set.");
|
||||
}
|
||||
else if (this.coordsTwo == null)
|
||||
{
|
||||
this.coordsTwo = this.getTargetBlock().getLocation().toVector();
|
||||
v.sendMessage(ChatColor.GRAY + "Second Corner set.");
|
||||
}
|
||||
else if (this.coordsThree == null)
|
||||
{
|
||||
this.coordsThree = this.getTargetBlock().getLocation().toVector();
|
||||
v.sendMessage(ChatColor.GRAY + "Third Corner set.");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.coordsOne = this.getTargetBlock().getLocation().toVector();
|
||||
this.coordsTwo = null;
|
||||
this.coordsThree = null;
|
||||
v.sendMessage(ChatColor.GRAY + "First Corner set.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
if (this.coordsOne == null || this.coordsTwo == null || this.coordsThree == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate triangle defining vectors
|
||||
final Vector vectorOne = this.coordsTwo.clone();
|
||||
vectorOne.subtract(this.coordsOne);
|
||||
final Vector vectorTwo = this.coordsThree.clone();
|
||||
vectorTwo.subtract(this.coordsOne);
|
||||
final Vector vectorThree = this.coordsThree.clone();
|
||||
vectorThree.subtract(vectorTwo);
|
||||
|
||||
// Redundant data check
|
||||
if (vectorOne.length() == 0 || vectorTwo.length() == 0 || vectorThree.length() == 0 || vectorOne.angle(vectorTwo) == 0 || vectorOne.angle(vectorThree) == 0 || vectorThree.angle(vectorTwo) == 0)
|
||||
{
|
||||
|
||||
v.sendMessage(ChatColor.RED + "ERROR: Invalid points, try again.");
|
||||
this.coordsOne = null;
|
||||
this.coordsTwo = null;
|
||||
this.coordsThree = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate normal vector of the plane.
|
||||
final Vector normalVector = vectorOne.clone();
|
||||
normalVector.crossProduct(vectorTwo);
|
||||
|
||||
// Calculate constant term of the plane.
|
||||
final double planeConstant = normalVector.getX() * this.coordsOne.getX() + normalVector.getY() * this.coordsOne.getY() + normalVector.getZ() * this.coordsOne.getZ();
|
||||
|
||||
final Vector midpointOne = this.coordsOne.getMidpoint(this.coordsTwo);
|
||||
final Vector midpointTwo = this.coordsOne.getMidpoint(this.coordsThree);
|
||||
|
||||
// Find perpendicular vectors to two sides in the plane
|
||||
final Vector perpendicularOne = normalVector.clone();
|
||||
perpendicularOne.crossProduct(vectorOne);
|
||||
final Vector perpendicularTwo = normalVector.clone();
|
||||
perpendicularTwo.crossProduct(vectorTwo);
|
||||
|
||||
// determine value of parametric variable at intersection of two perpendicular bisectors
|
||||
final Vector tNumerator = midpointTwo.clone();
|
||||
tNumerator.subtract(midpointOne);
|
||||
tNumerator.crossProduct(perpendicularTwo);
|
||||
final Vector tDenominator = perpendicularOne.clone();
|
||||
tDenominator.crossProduct(perpendicularTwo);
|
||||
final double t = tNumerator.length() / tDenominator.length();
|
||||
|
||||
// Calculate Circumcenter and Brushcenter.
|
||||
final Vector circumcenter = new Vector();
|
||||
circumcenter.copy(perpendicularOne);
|
||||
circumcenter.multiply(t);
|
||||
circumcenter.add(midpointOne);
|
||||
|
||||
final Vector brushCenter = new Vector(Math.round(circumcenter.getX()), Math.round(circumcenter.getY()), Math.round(circumcenter.getZ()));
|
||||
|
||||
// Calculate radius of circumcircle and determine brushsize
|
||||
final double radius = circumcenter.distance(new Vector(this.coordsOne.getX(), this.coordsOne.getY(), this.coordsOne.getZ()));
|
||||
final int brushSize = NumberConversions.ceil(radius) + 1;
|
||||
|
||||
for (int x = -brushSize; x <= brushSize; x++)
|
||||
{
|
||||
for (int y = -brushSize; y <= brushSize; y++)
|
||||
{
|
||||
for (int z = -brushSize; z <= brushSize; z++)
|
||||
{
|
||||
// Calculate distance from center
|
||||
final double tempDistance = Math.pow(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2), .5);
|
||||
|
||||
// gets corner-on blocks
|
||||
final double cornerConstant = normalVector.getX() * (circumcenter.getX() + x) + normalVector.getY() * (circumcenter.getY() + y) + normalVector.getZ() * (circumcenter.getZ() + z);
|
||||
|
||||
// gets center-on blocks
|
||||
final double centerConstant = normalVector.getX() * (circumcenter.getX() + x + .5) + normalVector.getY() * (circumcenter.getY() + y + .5) + normalVector.getZ() * (circumcenter.getZ() + z + .5);
|
||||
|
||||
// Check if point is within sphere and on plane (some tolerance given)
|
||||
if (tempDistance <= radius && (Math.abs(cornerConstant - planeConstant) < this.tolerance.getValue() || Math.abs(centerConstant - planeConstant) < this.tolerance.getValue()))
|
||||
{
|
||||
this.current.perform(this.clampY(brushCenter.getBlockX() + x, brushCenter.getBlockY() + y, brushCenter.getBlockZ() + z));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.sendMessage(ChatColor.GREEN + "Done.");
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
|
||||
// Reset Brush
|
||||
this.coordsOne = null;
|
||||
this.coordsTwo = null;
|
||||
this.coordsThree = null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
switch (this.tolerance)
|
||||
{
|
||||
case ACCURATE:
|
||||
vm.custom(ChatColor.GOLD + "Mode: Accurate");
|
||||
break;
|
||||
case DEFAULT:
|
||||
vm.custom(ChatColor.GOLD + "Mode: Default");
|
||||
break;
|
||||
case SMOOTH:
|
||||
vm.custom(ChatColor.GOLD + "Mode: Smooth");
|
||||
break;
|
||||
default:
|
||||
vm.custom(ChatColor.GOLD + "Mode: Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.YELLOW + "3-Point Circle Brush instructions: Select three corners with the arrow brush, then generate the Circle with the powder brush.");
|
||||
String toleranceOptions = "";
|
||||
for (final Tolerance tolerance : Tolerance.values())
|
||||
{
|
||||
if (!toleranceOptions.isEmpty())
|
||||
{
|
||||
toleranceOptions += "|";
|
||||
}
|
||||
toleranceOptions += tolerance.name().toLowerCase();
|
||||
}
|
||||
v.sendMessage(ChatColor.GOLD + "/b tpc " + toleranceOptions + " -- Toggle the calculations to emphasize accuracy or smoothness");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
final String parameter = par[i].toUpperCase();
|
||||
try
|
||||
{
|
||||
this.tolerance = Tolerance.valueOf(parameter);
|
||||
v.sendMessage(ChatColor.AQUA + "Brush set to " + this.tolerance.name().toLowerCase() + " tolerance.");
|
||||
return;
|
||||
}
|
||||
catch (final IllegalArgumentException exception)
|
||||
{
|
||||
v.getVoxelMessage().brushMessage("No such tolerance.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration on Tolerance values.
|
||||
*
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
private enum Tolerance
|
||||
{
|
||||
DEFAULT(1000), ACCURATE(10), SMOOTH(2000);
|
||||
private int value;
|
||||
|
||||
Tolerance(final int value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.threepointcircle";
|
||||
}
|
||||
}
|
132
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TreeSnipeBrush.java
Normale Datei
132
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TreeSnipeBrush.java
Normale Datei
@ -0,0 +1,132 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlockState;
|
||||
import com.google.common.base.Objects;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.Undo;
|
||||
import com.thevoxelbox.voxelsniper.util.UndoDelegate;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.TreeType;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Tree_Brush
|
||||
*
|
||||
* @author Mick
|
||||
*/
|
||||
public class TreeSnipeBrush extends Brush
|
||||
{
|
||||
private TreeType treeType = TreeType.TREE;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public TreeSnipeBrush()
|
||||
{
|
||||
this.setName("Tree Snipe");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void single(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
UndoDelegate undoDelegate = new UndoDelegate(targetBlock.getWorld());
|
||||
AsyncBlock blockBelow = targetBlock.getRelative(BlockFace.DOWN);
|
||||
AsyncBlockState currentState = blockBelow.getState();
|
||||
undoDelegate.setBlock(blockBelow);
|
||||
blockBelow.setType(Material.GRASS);
|
||||
this.getWorld().generateTree(targetBlock.getLocation(), this.treeType, undoDelegate);
|
||||
Undo undo = undoDelegate.getUndo();
|
||||
blockBelow.setTypeIdAndPropertyId(currentState.getTypeId(), currentState.getPropertyId(), true);
|
||||
undo.put(blockBelow);
|
||||
v.owner().storeUndo(undo);
|
||||
}
|
||||
|
||||
private int getYOffset()
|
||||
{
|
||||
for (int i = 1; i < (getTargetBlock().getWorld().getMaxHeight() - 1 - getTargetBlock().getY()); i++)
|
||||
{
|
||||
if (Objects.equal(getTargetBlock().getRelative(0, i + 1, 0).getType(), Material.AIR))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void printTreeType(final Message vm)
|
||||
{
|
||||
String printout = "";
|
||||
|
||||
boolean delimiterHelper = true;
|
||||
for (final TreeType treeType : TreeType.values())
|
||||
{
|
||||
if (delimiterHelper)
|
||||
{
|
||||
delimiterHelper = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
printout += ", ";
|
||||
}
|
||||
printout += ((treeType.equals(this.treeType)) ? ChatColor.GRAY + treeType.name().toLowerCase() : ChatColor.DARK_GRAY + treeType.name().toLowerCase()) + ChatColor.WHITE;
|
||||
}
|
||||
|
||||
vm.custom(printout);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
AsyncBlock targetBlock = getTargetBlock().getRelative(0, getYOffset(), 0);
|
||||
this.single(v, targetBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.single(v, getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
this.printTreeType(vm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
if (par[i].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Tree snipe brush:");
|
||||
v.sendMessage(ChatColor.AQUA + "/b t treetype");
|
||||
this.printTreeType(v.getVoxelMessage());
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
this.treeType = TreeType.valueOf(par[i].toUpperCase());
|
||||
this.printTreeType(v.getVoxelMessage());
|
||||
}
|
||||
catch (final IllegalArgumentException exception)
|
||||
{
|
||||
v.getVoxelMessage().brushMessage("No such tree type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.treesnipe";
|
||||
}
|
||||
}
|
334
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TriangleBrush.java
Normale Datei
334
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/TriangleBrush.java
Normale Datei
@ -0,0 +1,334 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Triangle_Brush
|
||||
*
|
||||
* @author Giltwist
|
||||
*/
|
||||
public class TriangleBrush extends PerformBrush
|
||||
{
|
||||
private double[] coordsOne = new double[3]; // Three corners
|
||||
private double[] coordsTwo = new double[3];
|
||||
private double[] coordsThree = new double[3];
|
||||
private int cornernumber = 1;
|
||||
private double[] currentCoords = new double[3]; // For loop tracking
|
||||
private double[] vectorOne = new double[3]; // Point 1 to 2
|
||||
private double[] vectorTwo = new double[3]; // Point 1 to 3
|
||||
private double[] vectorThree = new double[3]; // Point 2 to 3, for area calculations
|
||||
private double[] normalVector = new double[3];
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public TriangleBrush()
|
||||
{
|
||||
this.setName("Triangle");
|
||||
}
|
||||
|
||||
private void triangleA(final SnipeData v)
|
||||
{
|
||||
switch (this.cornernumber)
|
||||
{
|
||||
case 1:
|
||||
this.coordsOne[0] = this.getTargetBlock().getX() + .5 * this.getTargetBlock().getX() / Math.abs(this.getTargetBlock().getX()); // I hate you sometimes, Notch. Really? Every quadrant is
|
||||
// different?
|
||||
this.coordsOne[1] = this.getTargetBlock().getY() + .5;
|
||||
this.coordsOne[2] = this.getTargetBlock().getZ() + .5 * this.getTargetBlock().getZ() / Math.abs(this.getTargetBlock().getZ());
|
||||
this.cornernumber = 2;
|
||||
v.sendMessage(ChatColor.GRAY + "First Corner set.");
|
||||
break;
|
||||
case 2:
|
||||
this.coordsTwo[0] = this.getTargetBlock().getX() + .5 * this.getTargetBlock().getX() / Math.abs(this.getTargetBlock().getX()); // I hate you sometimes, Notch. Really? Every quadrant is
|
||||
// different?
|
||||
this.coordsTwo[1] = this.getTargetBlock().getY() + .5;
|
||||
this.coordsTwo[2] = this.getTargetBlock().getZ() + .5 * this.getTargetBlock().getZ() / Math.abs(this.getTargetBlock().getZ());
|
||||
this.cornernumber = 3;
|
||||
v.sendMessage(ChatColor.GRAY + "Second Corner set.");
|
||||
break;
|
||||
case 3:
|
||||
this.coordsThree[0] = this.getTargetBlock().getX() + .5 * this.getTargetBlock().getX() / Math.abs(this.getTargetBlock().getX()); // I hate you sometimes, Notch. Really? Every quadrant is
|
||||
// different?
|
||||
this.coordsThree[1] = this.getTargetBlock().getY() + .5;
|
||||
this.coordsThree[2] = this.getTargetBlock().getZ() + .5 * this.getTargetBlock().getZ() / Math.abs(this.getTargetBlock().getZ());
|
||||
this.cornernumber = 1;
|
||||
v.sendMessage(ChatColor.GRAY + "Third Corner set.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void triangleP(final SnipeData v)
|
||||
{
|
||||
double lengthOne = 0;
|
||||
double lengthTwo = 0;
|
||||
double lengthThree = 0;
|
||||
double heronBig = 0;
|
||||
|
||||
// Calculate slope vectors
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
this.vectorOne[i] = this.coordsTwo[i] - this.coordsOne[i];
|
||||
this.vectorTwo[i] = this.coordsThree[i] - this.coordsOne[i];
|
||||
this.vectorThree[i] = this.coordsThree[i] - this.coordsTwo[i];
|
||||
}
|
||||
|
||||
// Calculate the cross product of vectorone and vectortwo
|
||||
this.normalVector[0] = this.vectorOne[1] * this.vectorTwo[2] - this.vectorOne[2] * this.vectorTwo[1];
|
||||
this.normalVector[1] = this.vectorOne[2] * this.vectorTwo[0] - this.vectorOne[0] * this.vectorTwo[2];
|
||||
this.normalVector[2] = this.vectorOne[0] * this.vectorTwo[1] - this.vectorOne[1] * this.vectorTwo[0];
|
||||
|
||||
// Calculate magnitude of slope vectors
|
||||
lengthOne = Math.pow(Math.pow(this.vectorOne[0], 2) + Math.pow(this.vectorOne[1], 2) + Math.pow(this.vectorOne[2], 2), .5);
|
||||
lengthTwo = Math.pow(Math.pow(this.vectorTwo[0], 2) + Math.pow(this.vectorTwo[1], 2) + Math.pow(this.vectorTwo[2], 2), .5);
|
||||
lengthThree = Math.pow(Math.pow(this.vectorThree[0], 2) + Math.pow(this.vectorThree[1], 2) + Math.pow(this.vectorThree[2], 2), .5);
|
||||
|
||||
// Bigger vector determines brush size
|
||||
final int brushSize = (int) Math.ceil((lengthOne > lengthTwo) ? lengthOne : lengthTwo);
|
||||
|
||||
// Calculate constant term
|
||||
final double planeConstant = this.normalVector[0] * this.coordsOne[0] + this.normalVector[1] * this.coordsOne[1] + this.normalVector[2] * this.coordsOne[2];
|
||||
|
||||
// Calculate the area of the full triangle
|
||||
heronBig = .25 * Math.pow(Math.pow(Math.pow(lengthOne, 2) + Math.pow(lengthTwo, 2) + Math.pow(lengthThree, 2), 2) - 2 * (Math.pow(lengthOne, 4) + Math.pow(lengthTwo, 4) + Math.pow(lengthThree, 4)), .5);
|
||||
|
||||
if (lengthOne == 0 || lengthTwo == 0 || (this.coordsOne[0] == 0 && this.coordsOne[1] == 0 && this.coordsOne[2] == 0) || (this.coordsTwo[0] == 0 && this.coordsTwo[1] == 0 && this.coordsTwo[2] == 0) || (this.coordsThree[0] == 0 && this.coordsThree[1] == 0 && this.coordsThree[2] == 0))
|
||||
{
|
||||
v.sendMessage(ChatColor.RED + "ERROR: Invalid corners, please try again.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make the Changes
|
||||
final double[] cVectorOne = new double[3];
|
||||
final double[] cVectorTwo = new double[3];
|
||||
final double[] cVectorThree = new double[3];
|
||||
|
||||
for (int y = -brushSize; y <= brushSize; y++)
|
||||
{ // X DEPENDENT
|
||||
for (int z = -brushSize; z <= brushSize; z++)
|
||||
{
|
||||
this.currentCoords[1] = this.coordsOne[1] + y;
|
||||
this.currentCoords[2] = this.coordsOne[2] + z;
|
||||
this.currentCoords[0] = (planeConstant - this.normalVector[1] * this.currentCoords[1] - this.normalVector[2] * this.currentCoords[2]) / this.normalVector[0];
|
||||
|
||||
// Area of triangle currentcoords, coordsone, coordstwo
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
cVectorOne[i] = this.coordsTwo[i] - this.coordsOne[i];
|
||||
cVectorTwo[i] = this.currentCoords[i] - this.coordsOne[i];
|
||||
cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i];
|
||||
}
|
||||
double cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5);
|
||||
double cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5);
|
||||
double cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5);
|
||||
|
||||
final double heronOne = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5);
|
||||
|
||||
// Area of triangle currentcoords, coordsthree, coordstwo
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
cVectorOne[i] = this.coordsTwo[i] - this.coordsThree[i];
|
||||
cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i];
|
||||
cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i];
|
||||
}
|
||||
cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5);
|
||||
cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5);
|
||||
cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5);
|
||||
final double heronTwo = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5);
|
||||
|
||||
// Area of triangle currentcoords, coordsthree, coordsone
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
cVectorOne[i] = this.coordsOne[i] - this.coordsThree[i];
|
||||
cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i];
|
||||
cVectorThree[i] = this.currentCoords[i] - this.coordsOne[i];
|
||||
}
|
||||
cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5);
|
||||
cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5);
|
||||
cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5);
|
||||
final double heronThree = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5);
|
||||
|
||||
final double barycentric = (heronOne + heronTwo + heronThree) / heronBig;
|
||||
|
||||
if (barycentric <= 1.1)
|
||||
{
|
||||
|
||||
this.current.perform(this.clampY((int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2]));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} // END X DEPENDENT
|
||||
|
||||
for (int x = -brushSize; x <= brushSize; x++)
|
||||
{ // Y DEPENDENT
|
||||
for (int z = -brushSize; z <= brushSize; z++)
|
||||
{
|
||||
this.currentCoords[0] = this.coordsOne[0] + x;
|
||||
this.currentCoords[2] = this.coordsOne[2] + z;
|
||||
this.currentCoords[1] = (planeConstant - this.normalVector[0] * this.currentCoords[0] - this.normalVector[2] * this.currentCoords[2]) / this.normalVector[1];
|
||||
|
||||
// Area of triangle currentcoords, coordsone, coordstwo
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
cVectorOne[i] = this.coordsTwo[i] - this.coordsOne[i];
|
||||
cVectorTwo[i] = this.currentCoords[i] - this.coordsOne[i];
|
||||
cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i];
|
||||
}
|
||||
double cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5);
|
||||
double cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5);
|
||||
double cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5);
|
||||
|
||||
final double heronOne = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5);
|
||||
|
||||
// Area of triangle currentcoords, coordsthree, coordstwo
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
cVectorOne[i] = this.coordsTwo[i] - this.coordsThree[i];
|
||||
cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i];
|
||||
cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i];
|
||||
}
|
||||
cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5);
|
||||
cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5);
|
||||
cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5);
|
||||
final double heronTwo = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5);
|
||||
|
||||
// Area of triangle currentcoords, coordsthree, coordsone
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
cVectorOne[i] = this.coordsOne[i] - this.coordsThree[i];
|
||||
cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i];
|
||||
cVectorThree[i] = this.currentCoords[i] - this.coordsOne[i];
|
||||
}
|
||||
cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5);
|
||||
cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5);
|
||||
cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5);
|
||||
final double heronThree = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5);
|
||||
|
||||
final double barycentric = (heronOne + heronTwo + heronThree) / heronBig;
|
||||
|
||||
if (barycentric <= 1.1)
|
||||
{
|
||||
|
||||
this.current.perform(this.clampY((int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2]));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} // END Y DEPENDENT
|
||||
for (int x = -brushSize; x <= brushSize; x++)
|
||||
{ // Z DEPENDENT
|
||||
for (int y = -brushSize; y <= brushSize; y++)
|
||||
{
|
||||
this.currentCoords[0] = this.coordsOne[0] + x;
|
||||
this.currentCoords[1] = this.coordsOne[1] + y;
|
||||
this.currentCoords[2] = (planeConstant - this.normalVector[0] * this.currentCoords[0] - this.normalVector[1] * this.currentCoords[1]) / this.normalVector[2];
|
||||
|
||||
// Area of triangle currentcoords, coordsone, coordstwo
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
cVectorOne[i] = this.coordsTwo[i] - this.coordsOne[i];
|
||||
cVectorTwo[i] = this.currentCoords[i] - this.coordsOne[i];
|
||||
cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i];
|
||||
}
|
||||
double cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5);
|
||||
double cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5);
|
||||
double cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5);
|
||||
|
||||
final double heronOne = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5);
|
||||
|
||||
// Area of triangle currentcoords, coordsthree, coordstwo
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
cVectorOne[i] = this.coordsTwo[i] - this.coordsThree[i];
|
||||
cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i];
|
||||
cVectorThree[i] = this.currentCoords[i] - this.coordsTwo[i];
|
||||
}
|
||||
cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5);
|
||||
cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5);
|
||||
cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5);
|
||||
final double heronTwo = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5);
|
||||
|
||||
// Area of triangle currentcoords, coordsthree, coordsone
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
cVectorOne[i] = this.coordsOne[i] - this.coordsThree[i];
|
||||
cVectorTwo[i] = this.currentCoords[i] - this.coordsThree[i];
|
||||
cVectorThree[i] = this.currentCoords[i] - this.coordsOne[i];
|
||||
}
|
||||
cLengthOne = Math.pow(Math.pow(cVectorOne[0], 2) + Math.pow(cVectorOne[1], 2) + Math.pow(cVectorOne[2], 2), .5);
|
||||
cLengthTwo = Math.pow(Math.pow(cVectorTwo[0], 2) + Math.pow(cVectorTwo[1], 2) + Math.pow(cVectorTwo[2], 2), .5);
|
||||
cLengthThree = Math.pow(Math.pow(cVectorThree[0], 2) + Math.pow(cVectorThree[1], 2) + Math.pow(cVectorThree[2], 2), .5);
|
||||
final double heronThree = .25 * Math.pow(Math.pow(Math.pow(cLengthOne, 2) + Math.pow(cLengthTwo, 2) + Math.pow(cLengthThree, 2), 2) - 2 * (Math.pow(cLengthOne, 4) + Math.pow(cLengthTwo, 4) + Math.pow(cLengthThree, 4)), .5);
|
||||
|
||||
final double barycentric = (heronOne + heronTwo + heronThree) / heronBig;
|
||||
|
||||
// VoxelSniper.log.info("Bary: "+barycentric+", hb: "+heronbig+", h1: "+heronone+", h2: "+herontwo+", h3: "+heronthree);
|
||||
|
||||
if (barycentric <= 1.1)
|
||||
{
|
||||
this.current.perform(this.clampY((int) this.currentCoords[0], (int) this.currentCoords[1], (int) this.currentCoords[2]));
|
||||
}
|
||||
}
|
||||
} // END Z DEPENDENT
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
|
||||
}
|
||||
|
||||
// RESET BRUSH
|
||||
this.coordsOne[0] = 0;
|
||||
this.coordsOne[1] = 0;
|
||||
this.coordsOne[2] = 0;
|
||||
this.coordsTwo[0] = 0;
|
||||
this.coordsTwo[1] = 0;
|
||||
this.coordsTwo[2] = 0;
|
||||
this.coordsThree[0] = 0;
|
||||
this.coordsThree[1] = 0;
|
||||
this.coordsThree[2] = 0;
|
||||
|
||||
this.cornernumber = 1;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.triangleA(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{ // Add a point
|
||||
this.triangleP(v);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{ // Make the triangle
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
if (par[1].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.sendMessage(ChatColor.GOLD + "Triangle Brush instructions: Select three corners with the arrow brush, then generate the triangle with the powder brush.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.triangle";
|
||||
}
|
||||
}
|
198
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/UnderlayBrush.java
Normale Datei
198
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/UnderlayBrush.java
Normale Datei
@ -0,0 +1,198 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.sk89q.worldedit.blocks.BlockMaterial;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#Underlay_Brush
|
||||
*
|
||||
* @author jmck95 Credit to GavJenks for framework and 95 of code. Big Thank you to GavJenks
|
||||
*/
|
||||
|
||||
public class UnderlayBrush extends PerformBrush
|
||||
{
|
||||
private static final int DEFAULT_DEPTH = 3;
|
||||
private int depth = DEFAULT_DEPTH;
|
||||
private boolean allBlocks = false;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public UnderlayBrush()
|
||||
{
|
||||
this.setName("Underlay (Reverse Overlay)");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void underlay(final SnipeData v)
|
||||
{
|
||||
final int[][] memory = new int[v.getBrushSize() * 2 + 1][v.getBrushSize() * 2 + 1];
|
||||
final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2);
|
||||
|
||||
for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int y = this.getTargetBlock().getY(); y < this.getTargetBlock().getY() + this.depth; y++)
|
||||
{ // start scanning from the height you clicked at
|
||||
if (memory[x + v.getBrushSize()][z + v.getBrushSize()] != 1)
|
||||
{ // if haven't already found the surface in this column
|
||||
if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared)
|
||||
{ // if inside of the column...
|
||||
if (!this.allBlocks)
|
||||
{ // if the override parameter has not been activated, go to the switch that filters out manmade stuff.
|
||||
int id = this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z);
|
||||
BlockMaterial mat = BlockTypes.get(id).getMaterial();
|
||||
if (!mat.isReplacedDuringPlacement() && mat.isFullCube()) {
|
||||
for (int d = 0; (d < this.depth); d++) {
|
||||
if (this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z).getTypeId() != 0) {
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in
|
||||
// parameters
|
||||
memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column.
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int d = 0; (d < this.depth); d++)
|
||||
{
|
||||
if (this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z).getTypeId() != 0)
|
||||
{
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y + d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in
|
||||
// parameters
|
||||
memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void underlay2(final SnipeData v)
|
||||
{
|
||||
final int[][] memory = new int[v.getBrushSize() * 2 + 1][v.getBrushSize() * 2 + 1];
|
||||
final double brushSizeSquared = Math.pow(v.getBrushSize() + 0.5, 2);
|
||||
|
||||
for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int y = this.getTargetBlock().getY(); y < this.getTargetBlock().getY() + this.depth; y++)
|
||||
{ // start scanning from the height you clicked at
|
||||
if (memory[x + v.getBrushSize()][z + v.getBrushSize()] != 1)
|
||||
{ // if haven't already found the surface in this column
|
||||
if ((Math.pow(x, 2) + Math.pow(z, 2)) <= brushSizeSquared)
|
||||
{ // if inside of the column...
|
||||
|
||||
if (!this.allBlocks)
|
||||
{ // if the override parameter has not been activated, go to the switch that filters out manmade stuff.
|
||||
|
||||
int id = this.getBlockIdAt(this.getTargetBlock().getX() + x, y, this.getTargetBlock().getZ() + z);
|
||||
BlockMaterial mat = BlockTypes.get(id).getMaterial();
|
||||
if (!mat.isReplacedDuringPlacement() && mat.isFullCube()) {
|
||||
for (int d = -1; (d < this.depth - 1); d++) {
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in
|
||||
// parameters
|
||||
memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column.
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int d = -1; (d < this.depth - 1); d++)
|
||||
{
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, y - d, this.getTargetBlock().getZ() + z)); // fills down as many layers as you specify in
|
||||
// parameters
|
||||
memory[x + v.getBrushSize()][z + v.getBrushSize()] = 1; // stop it from checking any other blocks in this vertical 1x1 column.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void arrow(final SnipeData v)
|
||||
{
|
||||
this.underlay(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void powder(final SnipeData v)
|
||||
{
|
||||
this.underlay2(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void parameters(final String[] par, final SnipeData v)
|
||||
{
|
||||
for (int i = 1; i < par.length; i++)
|
||||
{
|
||||
if (par[i].equalsIgnoreCase("info"))
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.GOLD + "Reverse Overlay brush parameters:");
|
||||
v.owner().getPlayer().sendMessage(ChatColor.AQUA + "d[number] (ex: d3) The number of blocks thick to change.");
|
||||
v.owner().getPlayer().sendMessage(ChatColor.BLUE + "all (ex: /b reover all) Sets the brush to affect ALL materials");
|
||||
if (this.depth < 1)
|
||||
{
|
||||
this.depth = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (par[i].startsWith("d"))
|
||||
{
|
||||
this.depth = Integer.parseInt(par[i].replace("d", ""));
|
||||
v.owner().getPlayer().sendMessage(ChatColor.AQUA + "Depth set to " + this.depth);
|
||||
}
|
||||
else if (par[i].startsWith("all"))
|
||||
{
|
||||
this.allBlocks = true;
|
||||
v.owner().getPlayer().sendMessage(ChatColor.BLUE + "Will underlay over any block." + this.depth);
|
||||
}
|
||||
else if (par[i].startsWith("some"))
|
||||
{
|
||||
this.allBlocks = false;
|
||||
v.owner().getPlayer().sendMessage(ChatColor.BLUE + "Will underlay only natural block types." + this.depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.owner().getPlayer().sendMessage(ChatColor.RED + "Invalid brush parameters! use the info parameter to display parameter info.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.underlay";
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Volt-Meter_Brush
|
||||
*
|
||||
* @author Gavjenks
|
||||
*/
|
||||
public class VoltMeterBrush extends Brush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public VoltMeterBrush()
|
||||
{
|
||||
this.setName("VoltMeter");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void data(final SnipeData v)
|
||||
{
|
||||
final AsyncBlock block = this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ());
|
||||
final int data = block.getPropertyId();
|
||||
v.sendMessage(ChatColor.AQUA + "Blocks until repeater needed: " + data);
|
||||
}
|
||||
|
||||
private void volt(final SnipeData v)
|
||||
{
|
||||
final Block block = this.clampY(this.getTargetBlock().getX(), this.getTargetBlock().getY(), this.getTargetBlock().getZ());
|
||||
final boolean indirect = block.isBlockIndirectlyPowered();
|
||||
final boolean direct = block.isBlockPowered();
|
||||
v.sendMessage(ChatColor.AQUA + "Direct Power? " + direct + " Indirect Power? " + indirect);
|
||||
v.sendMessage(ChatColor.BLUE + "Top Direct? " + block.isBlockFacePowered(BlockFace.UP) + " Top Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.UP));
|
||||
v.sendMessage(ChatColor.BLUE + "Bottom Direct? " + block.isBlockFacePowered(BlockFace.DOWN) + " Bottom Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.DOWN));
|
||||
v.sendMessage(ChatColor.BLUE + "East Direct? " + block.isBlockFacePowered(BlockFace.EAST) + " East Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.EAST));
|
||||
v.sendMessage(ChatColor.BLUE + "West Direct? " + block.isBlockFacePowered(BlockFace.WEST) + " West Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.WEST));
|
||||
v.sendMessage(ChatColor.BLUE + "North Direct? " + block.isBlockFacePowered(BlockFace.NORTH) + " North Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.NORTH));
|
||||
v.sendMessage(ChatColor.BLUE + "South Direct? " + block.isBlockFacePowered(BlockFace.SOUTH) + " South Indirect? " + block.isBlockFaceIndirectlyPowered(BlockFace.SOUTH));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.volt(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.data(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.brushMessage("Right click with arrow to see if blocks/faces are powered. Powder measures wire current.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.voltmeter";
|
||||
}
|
||||
}
|
61
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelBrush.java
Normale Datei
61
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/VoxelBrush.java
Normale Datei
@ -0,0 +1,61 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Voxel_Brush
|
||||
*
|
||||
* @author Piotr
|
||||
*/
|
||||
public class VoxelBrush extends PerformBrush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public VoxelBrush()
|
||||
{
|
||||
this.setName("Voxel");
|
||||
}
|
||||
|
||||
private void voxel(final SnipeData v)
|
||||
{
|
||||
for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--)
|
||||
{
|
||||
this.current.perform(this.clampY(this.getTargetBlock().getX() + x, this.getTargetBlock().getY() + z, this.getTargetBlock().getZ() + y));
|
||||
}
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.voxel(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.voxel(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.voxel";
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Voxel_Disc_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class VoxelDiscBrush extends PerformBrush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public VoxelDiscBrush()
|
||||
{
|
||||
this.setName("Voxel Disc");
|
||||
}
|
||||
|
||||
private void disc(final SnipeData v, AsyncBlock targetBlock)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int z = v.getBrushSize(); z >= -v.getBrushSize(); z--)
|
||||
{
|
||||
current.perform(targetBlock.getRelative(x, 0, z));
|
||||
}
|
||||
}
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.disc(v, this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.disc(v, this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.voxeldisc";
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.perform.PerformBrush;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
/**
|
||||
* http://www.voxelwiki.com/minecraft/Voxelsniper#The_Voxel_Disc_Face_Brush
|
||||
*
|
||||
* @author Voxel
|
||||
*/
|
||||
public class VoxelDiscFaceBrush extends PerformBrush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public VoxelDiscFaceBrush()
|
||||
{
|
||||
this.setName("Voxel Disc Face");
|
||||
}
|
||||
|
||||
private void disc(final SnipeData v, Block targetBlock)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--)
|
||||
{
|
||||
this.current.perform(this.clampY(targetBlock.getX() + x, targetBlock.getY(), targetBlock.getZ() + y));
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void discNS(final SnipeData v, Block targetBlock)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--)
|
||||
{
|
||||
this.current.perform(this.clampY(targetBlock.getX() + x, targetBlock.getY() + y, targetBlock.getZ()));
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void discEW(final SnipeData v, Block targetBlock)
|
||||
{
|
||||
for (int x = v.getBrushSize(); x >= -v.getBrushSize(); x--)
|
||||
{
|
||||
for (int y = v.getBrushSize(); y >= -v.getBrushSize(); y--)
|
||||
{
|
||||
this.current.perform(this.clampY(targetBlock.getX(), targetBlock.getY() + x, targetBlock.getZ() + y));
|
||||
}
|
||||
}
|
||||
|
||||
v.owner().storeUndo(this.current.getUndo());
|
||||
}
|
||||
|
||||
private void pre(final SnipeData v, final BlockFace bf, Block targetBlock)
|
||||
{
|
||||
if (bf == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (bf)
|
||||
{
|
||||
case NORTH:
|
||||
case SOUTH:
|
||||
this.discNS(v, targetBlock);
|
||||
break;
|
||||
|
||||
case EAST:
|
||||
case WEST:
|
||||
this.discEW(v, targetBlock);
|
||||
break;
|
||||
|
||||
case UP:
|
||||
case DOWN:
|
||||
this.disc(v, targetBlock);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
this.pre(v, this.getTargetBlock().getFace(this.getLastBlock()), this.getTargetBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
this.pre(v, this.getTargetBlock().getFace(this.getLastBlock()), this.getLastBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
vm.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.voxeldiscface";
|
||||
}
|
||||
}
|
97
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/WarpBrush.java
Normale Datei
97
favs/src/main/java/com/thevoxelbox/voxelsniper/brush/WarpBrush.java
Normale Datei
@ -0,0 +1,97 @@
|
||||
/**
|
||||
This file is part of VoxelSniper, licensed under the MIT License (MIT).
|
||||
|
||||
Copyright (c) The VoxelBox <http://thevoxelbox.com>
|
||||
Copyright (c) contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
package com.thevoxelbox.voxelsniper.brush;
|
||||
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @author MikeMatrix
|
||||
*/
|
||||
public class WarpBrush extends Brush
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public WarpBrush()
|
||||
{
|
||||
this.setName("Warp");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void info(final Message vm)
|
||||
{
|
||||
vm.brushName(this.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void arrow(final SnipeData v)
|
||||
{
|
||||
Player player = v.owner().getPlayer();
|
||||
Location location = this.getLastBlock().getLocation();
|
||||
Location playerLocation = player.getLocation();
|
||||
location.setPitch(playerLocation.getPitch());
|
||||
location.setYaw(playerLocation.getYaw());
|
||||
location.setWorld(Bukkit.getWorld(location.getWorld().getName()));
|
||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
player.teleport(location);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void powder(final SnipeData v)
|
||||
{
|
||||
Player player = v.owner().getPlayer();
|
||||
Location location = this.getLastBlock().getLocation();
|
||||
Location playerLocation = player.getLocation();
|
||||
location.setPitch(playerLocation.getPitch());
|
||||
location.setYaw(playerLocation.getYaw());
|
||||
location.setWorld(Bukkit.getWorld(location.getWorld().getName()));
|
||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
player.teleport(location);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode()
|
||||
{
|
||||
return "voxelsniper.brush.warp";
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return WarpBrush.class;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.thevoxelbox.voxelsniper.brush.perform;
|
||||
|
||||
import com.boydti.fawe.bukkit.wrapper.AsyncBlock;
|
||||
import com.boydti.fawe.object.pattern.PatternTraverser;
|
||||
import com.sk89q.worldedit.MutableBlockVector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
public class PatternPerformer extends vPerformer {
|
||||
private String info;
|
||||
private Pattern pattern;
|
||||
private Extent extent;
|
||||
private MutableBlockVector mutable = new MutableBlockVector();
|
||||
|
||||
@Override
|
||||
public void info(Message vm) {
|
||||
vm.performerName(this.name + ": " + info);
|
||||
vm.voxel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(SnipeData snipeData) {
|
||||
this.w = snipeData.getWorld();
|
||||
this.extent = snipeData.getExtent();
|
||||
this.info = snipeData.getPatternInfo();
|
||||
this.pattern = snipeData.getPattern();
|
||||
new PatternTraverser(pattern).reset(extent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(AsyncBlock block) {
|
||||
mutable.setComponents(block.getX(), block.getY(), block.getZ());
|
||||
try {
|
||||
pattern.apply(extent, mutable, mutable);
|
||||
} catch (WorldEditException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/**
|
||||
This file is part of VoxelSniper, licensed under the MIT License (MIT).
|
||||
|
||||
Copyright (c) The VoxelBox <http://thevoxelbox.com>
|
||||
Copyright (c) contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
package com.thevoxelbox.voxelsniper.brush.perform;
|
||||
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
import com.thevoxelbox.voxelsniper.SnipeData;
|
||||
import com.thevoxelbox.voxelsniper.brush.Brush;
|
||||
import com.thevoxelbox.voxelsniper.event.SniperBrushChangedEvent;
|
||||
import java.util.Arrays;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public abstract class PerformBrush extends Brush implements Performer {
|
||||
protected vPerformer current = new pMaterial();
|
||||
|
||||
public PerformBrush() {
|
||||
}
|
||||
|
||||
public vPerformer getCurrentPerformer() {
|
||||
return this.current;
|
||||
}
|
||||
|
||||
public void parse(String[] args, SnipeData v) {
|
||||
String handle = args[0];
|
||||
if(PerformerE.has(handle)) {
|
||||
vPerformer p = PerformerE.getPerformer(handle);
|
||||
if(p != null) {
|
||||
this.current = p;
|
||||
SniperBrushChangedEvent event = new SniperBrushChangedEvent(v.owner(), v.owner().getCurrentToolId(), this, this);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
this.info(v.getVoxelMessage());
|
||||
this.current.info(v.getVoxelMessage());
|
||||
if(args.length > 1) {
|
||||
String[] additionalArguments = (String[])Arrays.copyOfRange(args, 1, args.length);
|
||||
this.parameters(this.hackTheArray(additionalArguments), v);
|
||||
}
|
||||
} else {
|
||||
this.parameters(this.hackTheArray(args), v);
|
||||
}
|
||||
} else {
|
||||
this.parameters(this.hackTheArray(args), v);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String[] hackTheArray(String[] args) {
|
||||
String[] returnValue = new String[args.length + 1];
|
||||
int i = 0;
|
||||
|
||||
for(int argsLength = args.length; i < argsLength; ++i) {
|
||||
String arg = args[i];
|
||||
returnValue[i + 1] = arg;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public void initP(SnipeData v) {
|
||||
Pattern pattern = v.getPattern();
|
||||
if (pattern != null) {
|
||||
if (!(current instanceof PatternPerformer)) {
|
||||
current = new PatternPerformer();
|
||||
}
|
||||
} else if (current instanceof PatternPerformer) {
|
||||
current = new pMaterial();
|
||||
}
|
||||
this.current.init(v);
|
||||
this.current.setUndo();
|
||||
}
|
||||
|
||||
public void showInfo(Message vm) {
|
||||
this.current.info(vm);
|
||||
}
|
||||
|
||||
public static Class<?> inject() {
|
||||
return PerformBrush.class;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package com.thevoxelbox.voxelsniper.brush.perform;
|
||||
|
||||
import com.thevoxelbox.voxelsniper.Message;
|
||||
|
||||
/**
|
||||
* @author Voxel
|
||||
*/
|
||||
public interface Performer
|
||||
{
|
||||
|
||||
public void parse(String[] args, com.thevoxelbox.voxelsniper.SnipeData v);
|
||||
|
||||
public void showInfo(Message vm);
|
||||
}
|
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package com.thevoxelbox.voxelsniper.brush.perform;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
/**
|
||||
* @author Voxel
|
||||
*/
|
||||
|
||||
/* The m/i/c system of naming performers: <placement-option>[replacement-option][extras]
|
||||
*
|
||||
* placement-option is mandatory and can be material(m) [for /v], ink(i) [for /vi] or combo(c) [for both]
|
||||
* replacement-option is optional and can be m [for /vr], i [for /vir] or c [for both]
|
||||
* extras is optional and can be update(u) [for graphical glitch], physics(p) [for no-phys] or up [for both]
|
||||
*
|
||||
* new extra: n = no undo
|
||||
*
|
||||
* The main benefit of this system is that it provides the least possible number of characters in the paramaters
|
||||
* while guaranteeing that all sensible combinations will be made. Additionally, the names will be VERY consistent
|
||||
*
|
||||
* EX Old System: /b b isrcup (use /v, /vi, /vr and /vir, update graphics and no physics)
|
||||
* EX New System: /b b ccup (two characters shorter, good because snipers have been complaing about keystrokes)
|
||||
*
|
||||
*/
|
||||
|
||||
/* This enum is getting REALLY Long, would it be possible to algorithmically generate the full performer
|
||||
* from the pieces? So if the performer name is of the for m*, you'll setTypeId whereas if it is of the
|
||||
* form c* you'd setTypeIdAndPropertyId? Similarly, if the performer is of the form *p, any setTypeId's or setTypeIdAndPropertyId's
|
||||
* will be set to false instead of true? The middle bits might be tougher, being of the form _m* perhaps?
|
||||
* Regex to the rescue, am I right? - Giltwist
|
||||
*/
|
||||
|
||||
public enum PerformerE
|
||||
{
|
||||
|
||||
MATERIAL(pMaterial.class, "m", "material"),
|
||||
MATERIAL_NOPHYS(pMaterialNoPhys.class, "mp", "mat-nophys"),
|
||||
MAT_MAT(pMatMat.class, "mm", "mat-mat"),
|
||||
MAT_MAT_NOPHYS(pMatMatNoPhys.class, "mmp", "mat-mat-nophys"),
|
||||
MAT_INK(pMatInk.class, "mi", "mat-ink"),
|
||||
MAT_INK_NOPHYS(pMatInkNoPhys.class, "mip", "mat-ink-nophys"),
|
||||
MAT_COMBO(pMatCombo.class, "mc", "mat-combo"),
|
||||
MAT_COMBO_NOPHYS(pMatComboNophys.class, "mcp", "mat-combo-nophys"),
|
||||
INK(pInk.class, "i", "ink"),
|
||||
INK_MAT(pInkMat.class, "im", "ink-mat"),
|
||||
INK_INK(pInkInk.class, "ii", "ink-ink"),
|
||||
INK_COMBO(pInkCombo.class, "ic", "ink-combo"),
|
||||
INK_INK_NOPHYS(pInkInkNoPhys.class, "iip", "ink-ink-nophys"),
|
||||
INK_NOPHYS(pInkNoPhys.class, "ip", "ink-nophys"),
|
||||
INK_MAT_NOPHYS(pInkMatNoPhys.class, "imp", "ink-mat-nophys"),
|
||||
INK_COMBO_NOPHYS(pInkComboNoPhys.class, "icp", "ink-combo-nophys"),
|
||||
COMBO(pCombo.class, "c", "combo"),
|
||||
COMBO_NOPHYS(pComboNoPhys.class, "cp", "combo-nophys"),
|
||||
COMBO_MAT(pComboMat.class, "cm", "combo-mat"),
|
||||
COMBO_MAT_NOPHYS(pComboMatNoPhys.class, "cmp", "combo-mat-nophys"),
|
||||
COMBO_INK(pComboInk.class, "ci", "combo-ink"),
|
||||
COMBO_INK_NOPHYS(pComboInkNoPhys.class, "cip", "combo-ink-nophys"),
|
||||
COMBO_COMBO(pComboCombo.class, "cc", "combo-combo"),
|
||||
COMBO_COMBO_NOPHYS(pComboComboNoPhys.class, "ccp", "combo-combo-nophys"),
|
||||
EXCLUDE_MATERIAL(pExcludeMat.class, "xm", "exclude-mat"),
|
||||
EXCLUDE_INK(pExcludeInk.class, "xi", "exclude-ink"),
|
||||
EXCLUDE_COMBO(pExcludeCombo.class, "xc", "exclude-combo"),
|
||||
INCLUDE_MATERIAL(pIncludeMat.class, "nm", "include-mat"),
|
||||
INCLUDE_INK(pIncludeInk.class, "ni", "include-ink"),
|
||||
INCLUDE_COMBO(pIncludeCombo.class, "nc", "include-combo"),
|
||||
MAT_NO_UNDO(pNoUndo.class, "noundo", "noundo");
|
||||
//Other Performers which don't exist yet but are required for a full set of possibilities that actually could potentially do something:
|
||||
//List does not include any no-physics, unless materials are being placed (or combo), or any update unless ink is being placed (or combo) -Gavjenks
|
||||
|
||||
//MAT_MAT_UPDATE( pMatMatUpdate.class, "mmu", "mat-mat-update" ), // place mat, replace mat, graphical update
|
||||
//MAT_COMBO_UPDATE( pMatComboUpdate.class, "mcu", "mat-combo-update" ), // place mat, replace combo, graphical update
|
||||
//MAT_COMBO_NOPHYS_UPDATE( pMatComboNoPhysUpdate.class, "mcup", "mat-combo-update-nophys"), // place mat, replace combo, update, no physics
|
||||
//MAT_INK_UPDATE( pMatInkUpdate.class, "miu", "mat-ink-update"), // place mat, replace ink, graphical update
|
||||
//MAT_INK_NOPHYS_UPDATE( pMatInkNoPhysUpdate.class, "miup", "mat-ink-update-nophys"), // place mat, replace ink, graphical update no physics
|
||||
//INK_MAT_UPDATE( pInkMatUpdate.class, "imu", "ink-mat-update"), // place ink, replace mat, graphical update
|
||||
//INK_INK_UPDATE( pInkInkUpdate.class, "iiu", "ink-ink-update"), // place ink, replace ink, graphical update
|
||||
//INK_COMBO_UPDATE( pInkComboUpdate.class, "icu", "ink-combo-update"), // place ink, replace combo, graphical update
|
||||
//COMBO_MAT_UPDATE( pComboMatUpdate.class, "cmu", "combo-mat-update"), // place combo, replace mat, graphical update
|
||||
//COMBO_MAT_NOPHYS_UPDATE( pComboMatNoPhysUpdate.class, "cmup", "combo-mat-update-nophys"), // place combo, replace mat, graphical update, no physics
|
||||
//COMBO_INK_UPDATE( pComboInkUpdate.class, "ciu", "combo-ink-update"), // place combo, replace ink, graphical update
|
||||
//COMBO_INK_NOPHYS_UPDATE( pComboInkNoPhysUpdate.class, "ciup", "combo-ink-update-nophys"), // place combo, replace ink, graphical update, no physics
|
||||
//COMBO_COMBO_UPDATE( pComboComboUpdate.class, "ccu", "combo-combo-update"), // place combo, replace combo, graphical update
|
||||
//COMBO_COMBO_NOPHYS_UPDATE(pComboComboNoPhysUpdate.class, "ccup", "combo-combo-update-nophys"),// place combo, replace combo, graphical update, no physics
|
||||
|
||||
private static Map<String, vPerformer> performers;
|
||||
private static Map<String, String> long_names;
|
||||
private Class<? extends vPerformer> pclass;
|
||||
private String short_name;
|
||||
private String long_name;
|
||||
public static String performer_list_short = "";
|
||||
public static String performer_list_long = "";
|
||||
|
||||
private PerformerE(Class<? extends vPerformer> c, String s, String l)
|
||||
{
|
||||
pclass = c;
|
||||
short_name = s;
|
||||
long_name = l;
|
||||
}
|
||||
|
||||
private vPerformer getPerformer()
|
||||
{
|
||||
vPerformer p;
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
p = pclass.getConstructor().newInstance();
|
||||
return p;
|
||||
}
|
||||
catch (InstantiationException ex)
|
||||
{
|
||||
Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
catch (IllegalAccessException ex)
|
||||
{
|
||||
Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
catch (IllegalArgumentException ex)
|
||||
{
|
||||
Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
catch (InvocationTargetException ex)
|
||||
{
|
||||
Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException ex)
|
||||
{
|
||||
Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
catch (SecurityException ex)
|
||||
{
|
||||
Logger.getLogger(PerformerE.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static vPerformer getPerformer(String s)
|
||||
{
|
||||
if (performers.containsKey(s))
|
||||
{
|
||||
return performers.get(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
return performers.get(long_names.get(s));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean has(String s)
|
||||
{
|
||||
return performers.containsKey(s);
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
performers = new TreeMap<String, vPerformer>();
|
||||
long_names = new TreeMap<String, String>();
|
||||
|
||||
for (PerformerE pe : values())
|
||||
{
|
||||
performers.put(pe.short_name, pe.getPerformer());
|
||||
long_names.put(pe.long_name, pe.short_name);
|
||||
performer_list_short = performer_list_short + ChatColor.GREEN + pe.short_name + ChatColor.RED + ", ";
|
||||
performer_list_long = performer_list_long + ChatColor.GREEN + pe.long_name + ChatColor.RED + ", ";
|
||||
}
|
||||
performer_list_short = performer_list_short.substring(0, performer_list_short.length() - 2);
|
||||
performer_list_long = performer_list_long.substring(0, performer_list_long.length() - 2);
|
||||
}
|
||||
}
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren