Various (unfinished)

Fixes #439
Update to Java 8
Adds scrollable brushes to the API (action on brush scroll)
- Clipboard
- Mask
- Pattern
- Range
- Size
Adds movable brushes to the API (action on brush move)
Adds different targeting modes for brushes (see enum TargetMode)
Adds VisualBrush to API (sends client block changes instead of changing
the world)
Updater now checks every 30m for updates
Adds in game updater changelog (/fawe changelog)
Adds language option to config
Adds german translations
Adds CircleBrush (WIP)
Simplify DoubleActionBrush and DoubleActionBrushTool to extend
Brush/BrushTool
Use ImmutableBlock instead of anonymous BaseBlock for cache
Fixes CuboidRegion iteration (affected some commands)
Fixes WorldCopyClipboard schematic saving
Optimize FawePlayer -> Player by caching value
Simplified pattern and mask API by extending legacy versions
Optimize sphere, cylinder and deform
Added brush cancellation by SHIFT + LEFT CLICK
Probably some other stuff
This commit is contained in:
Jesse Boyd 2017-02-26 16:39:00 +11:00
parent 74baf5fee8
commit 9c74d0b981
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
93 changed files with 2779 additions and 726 deletions

View File

@ -74,8 +74,8 @@ subprojects {
apply plugin: 'eclipse'
apply plugin: 'idea'
sourceCompatibility = 1.7
targetCompatibility = 1.7
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()

View File

@ -0,0 +1,135 @@
package com.boydti.fawe.bukkit;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.brush.MovableBrush;
import com.boydti.fawe.object.brush.scroll.ScrollableBrush;
import com.boydti.fawe.object.brush.visualization.VisualBrush;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.InvalidToolBindException;
import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.command.tool.brush.Brush;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.plugin.Plugin;
public class BrushListener implements Listener {
public BrushListener(Plugin plugin) {
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerItemHoldEvent(final PlayerItemHeldEvent event) {
final Player bukkitPlayer = event.getPlayer();
if (bukkitPlayer.isSneaking()) {
return;
}
FawePlayer<Object> fp = FawePlayer.wrap(bukkitPlayer);
com.sk89q.worldedit.entity.Player player = fp.getPlayer();
LocalSession session = fp.getSession();
Tool tool = session.getTool(player);
if (tool != null) {
ScrollableBrush scrollable;
if (tool instanceof ScrollableBrush) {
scrollable = (ScrollableBrush) tool;
} else if (tool instanceof BrushTool) {
Brush brush = ((BrushTool) tool).getBrush();
scrollable = brush instanceof ScrollableBrush ? (ScrollableBrush) brush : null;
} else {
return;
}
if (scrollable != null) {
final int slot = event.getNewSlot();
final int oldSlot = event.getPreviousSlot();
final int ri;
if ((((slot - oldSlot) <= 4) && ((slot - oldSlot) > 0)) || (((slot - oldSlot) < -4))) {
ri = 1;
} else {
ri = -1;
}
if (scrollable.increment(ri)) {
final PlayerInventory inv = bukkitPlayer.getInventory();
final ItemStack item = inv.getItem(slot);
final ItemStack newItem = inv.getItem(oldSlot);
inv.setItem(slot, newItem);
inv.setItem(oldSlot, item);
bukkitPlayer.updateInventory();
if (scrollable instanceof VisualBrush) {
try {
((VisualBrush) scrollable).queueVisualization(fp);
} catch (Throwable e) {
WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player);
}
}
}
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerMove(PlayerMoveEvent event) {
Location from = event.getFrom();
Location to = event.getTo();
if ((from.getYaw() != to.getYaw() && from.getPitch() != to.getPitch()) || from.getBlockX() != to.getBlockX() || from.getBlockZ() != to.getBlockZ() || from.getBlockY() != to.getBlockY()) {
Player bukkitPlayer = event.getPlayer();
FawePlayer<Object> fp = FawePlayer.wrap(bukkitPlayer);
com.sk89q.worldedit.entity.Player player = fp.getPlayer();
LocalSession session = fp.getSession();
Tool tool = session.getTool(player);
if (tool != null) {
if (tool instanceof MovableBrush) {
((MovableBrush) tool).move(player);
} else if (tool instanceof BrushTool) {
Brush brush = ((BrushTool) tool).getBrush();
if (brush instanceof MovableBrush) {
if (((MovableBrush) brush).move(player)) {
if (brush instanceof VisualBrush) {
try {
((VisualBrush) brush).queueVisualization(fp);
} catch (Throwable e) {
WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player);
}
}
}
}
}
}
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerInteract(final PlayerInteractEvent event) {
switch (event.getAction()) {
case LEFT_CLICK_AIR:
case LEFT_CLICK_BLOCK:
Player bukkitPlayer = event.getPlayer();
if (!bukkitPlayer.isSneaking()) {
return;
}
FawePlayer<Object> fp = FawePlayer.wrap(bukkitPlayer);
com.sk89q.worldedit.entity.Player player = fp.getPlayer();
LocalSession session = fp.getSession();
int item = player.getItemInHand();
Tool tool = session.getTool(item);
if (tool != null) {
try {
session.setTool(item, null, player);
BBC.TOOL_NONE.send(player);
} catch (InvalidToolBindException e) {
e.printStackTrace();
}
}
}
}
}

View File

@ -5,6 +5,7 @@ import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
import com.boydti.fawe.bukkit.v1_10.BukkitQueue_1_10;
import com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11;
import com.boydti.fawe.bukkit.v1_11.compression.CompressionOptimizer;
import com.boydti.fawe.bukkit.v1_7.BukkitQueue17;
import com.boydti.fawe.bukkit.v1_8.BukkitQueue18R3;
import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9_R1;
@ -68,6 +69,15 @@ public class BukkitMain extends JavaPlugin {
break;
} catch (IllegalStateException e) {}
}
switch (version) {
case v1_11_R1:
try {
CompressionOptimizer optimizer = new CompressionOptimizer();
// optimizer.optimize();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
private enum Version {

View File

@ -92,7 +92,7 @@ public class BukkitPlayer extends FawePlayer<Player> {
}
@Override
public com.sk89q.worldedit.entity.Player getPlayer() {
public com.sk89q.worldedit.entity.Player toWorldEditPlayer() {
return PlayerWrapper.wrap(Fawe.<FaweBukkit> imp().getWorldEditPlugin().wrapPlayer(this.parent));
}

View File

@ -70,6 +70,7 @@ public class FaweBukkit implements IFawe, Listener {
try {
Fawe.set(this);
setupInjector();
new BrushListener(plugin);
if (Bukkit.getVersion().contains("git-Spigot")) {
debug("====== USE PAPER ======");
debug("DOWNLOAD: https://ci.destroystokyo.com/job/PaperSpigot/");

View File

@ -9,6 +9,7 @@ import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
@ -142,9 +143,9 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
if ((BukkitQueue_0.adapter = adapter) != null) {
fieldAdapter.set(instance, adapter);
} else {
BukkitQueue_0.adapter = (BukkitImplAdapter) fieldAdapter.get(instance);
BukkitQueue_0.adapter = adapter = (BukkitImplAdapter) fieldAdapter.get(instance);
}
for (Method method : BukkitQueue_0.adapter.getClass().getDeclaredMethods()) {
for (Method method : adapter.getClass().getDeclaredMethods()) {
switch (method.getName()) {
case "toNative":
methodToNative = method;
@ -237,28 +238,41 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
}
@Override
public void sendBlockUpdate(Map<Long, Map<Short, Character>> blockMap, FawePlayer... players) {
for (FawePlayer player : players) {
Player bukkitPlayer = ((BukkitPlayer) player).parent;
World world = bukkitPlayer.getWorld();
for (Map.Entry<Long, Map<Short, Character>> entry : blockMap.entrySet()) {
long chunkHash = entry.getKey();
int cx = MathMan.unpairIntX(chunkHash);
int cz = MathMan.unpairIntY(chunkHash);
Map<Short, Character> blocks = entry.getValue();
for (Map.Entry<Short, Character> blockEntry : blocks.entrySet()) {
short blockHash = blockEntry.getKey();
int x = (blockHash >> 12 & 0xF) + (cx << 4);
int y = (blockHash & 0xFF);
int z = (blockHash >> 8 & 0xF) + (cz << 4);
char combined = blockEntry.getValue();
int id = FaweCache.getId(combined);
byte data = (byte) FaweCache.getData(combined);
Location loc = new Location(world, x, y, z);
bukkitPlayer.sendBlockChange(loc, id, data);
}
public void sendBlockUpdate(final FaweChunk chunk, FawePlayer... players) {
if (players.length == 0) {
return;
}
int cx = chunk.getX();
int cz = chunk.getZ();
int view = Bukkit.getServer().getViewDistance();
boolean sendAny = false;
boolean[] send = new boolean[players.length];
for (int i = 0; i < players.length; i++) {
FawePlayer player = players[i];
Player bp = ((BukkitPlayer) player).parent;
Location loc = bp.getLocation();
if (Math.abs((loc.getBlockX() >> 4) - cx) <= view && Math.abs((loc.getBlockZ() >> 4) - cz) <= view) {
sendAny = true;
send[i] = true;
}
}
if (!sendAny) {
return;
}
final World world = getWorld();
final int bx = cx << 4;
final int bz = cz << 4;
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
@Override
public void run(int localX, int y, int localZ, int combined) {
Location loc = new Location(world, bx + localX, y, bz + localZ);
for (int i = 0; i < players.length; i++) {
if (send[i]) {
((BukkitPlayer) players[i]).parent.sendBlockChange(loc, FaweCache.getId(combined), (byte) FaweCache.getData(combined));
}
}
}
});
}
@Override

View File

@ -0,0 +1,80 @@
package com.boydti.fawe.bukkit.v1_10;
import com.boydti.fawe.object.FaweQueue;
import net.minecraft.server.v1_10_R1.ChunkSection;
import net.minecraft.server.v1_10_R1.DataPaletteBlock;
import net.minecraft.server.v1_10_R1.NibbleArray;
public class BukkitChunk_1_10_Copy extends BukkitChunk_1_10 {
public final byte[][] idsBytes;
public final byte[][] datasBytes;
public BukkitChunk_1_10_Copy(FaweQueue parent, int x, int z) {
super(parent, x, z);
idsBytes = new byte[16][];
datasBytes = new byte[16][];
}
public void set(int i, byte[] ids, byte[] data) {
this.idsBytes[i] = ids;
this.datasBytes[i] = data;
}
public boolean storeSection(ChunkSection section, int layer) throws IllegalAccessException {
if (section == null) {
return false;
}
DataPaletteBlock blocks = section.getBlocks();
byte[] ids = new byte[4096];
NibbleArray data = new NibbleArray();
blocks.exportData(ids, data);
set(layer, ids, data.asBytes());
short solid = (short) getParent().fieldNonEmptyBlockCount.getInt(section);
count[layer] = solid;
air[layer] = (short) (4096 - solid);
return true;
}
@Override
public char[][] getCombinedIdArrays() {
for (int i = 0; i < ids.length; i++) {
getIdArray(i);
}
return super.getCombinedIdArrays();
}
@Override
public char[] getIdArray(int i) {
char[] combined = this.ids[i];
if (combined != null) {
return combined;
}
byte[] idsBytesArray = idsBytes[i];
if (idsBytesArray == null) {
return null;
}
byte[] datasBytesArray = datasBytes[i];
idsBytes[i] = null;
datasBytes[i] = null;
this.ids[i] = combined = new char[4096];
for (int j = 0, k = 0; j < 2048; j++, k += 2) {
combined[k] = (char) (((idsBytesArray[k] & 0xFF) << 4) + (datasBytesArray[j] & 15));
}
for (int j = 0, k = 1; j < 2048; j++, k += 2) {
combined[k] = (char) (((idsBytesArray[k] & 0xFF) << 4) + ((datasBytesArray[j] >> 4) & 15));
}
return combined;
}
@Override
public void setBlock(int x, int y, int z, int id) {
throw new UnsupportedOperationException("This chunk is an immutable copy");
}
@Override
public void setBlock(int x, int y, int z, int id, int data) {
throw new UnsupportedOperationException("This chunk is an immutable copy");
}
}

View File

@ -25,10 +25,13 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorCompletionService;
import net.minecraft.server.v1_10_R1.BiomeBase;
import net.minecraft.server.v1_10_R1.BiomeCache;
import net.minecraft.server.v1_10_R1.Block;
import net.minecraft.server.v1_10_R1.BlockPosition;
import net.minecraft.server.v1_10_R1.ChunkProviderGenerate;
import net.minecraft.server.v1_10_R1.ChunkProviderServer;
import net.minecraft.server.v1_10_R1.ChunkSection;
import net.minecraft.server.v1_10_R1.DataBits;
import net.minecraft.server.v1_10_R1.DataPaletteBlock;
import net.minecraft.server.v1_10_R1.Entity;
import net.minecraft.server.v1_10_R1.EntityPlayer;
@ -47,6 +50,7 @@ import net.minecraft.server.v1_10_R1.PlayerChunk;
import net.minecraft.server.v1_10_R1.PlayerChunkMap;
import net.minecraft.server.v1_10_R1.ServerNBTManager;
import net.minecraft.server.v1_10_R1.TileEntity;
import net.minecraft.server.v1_10_R1.WorldChunkManager;
import net.minecraft.server.v1_10_R1.WorldData;
import net.minecraft.server.v1_10_R1.WorldManager;
import net.minecraft.server.v1_10_R1.WorldServer;
@ -68,6 +72,8 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
protected static IBlockData air;
protected static Field fieldBits;
protected static Field fieldPalette;
protected static Field fieldSize;
protected static Method getEntitySlices;
protected static Field fieldTickingBlockCount;
protected static Field fieldNonEmptyBlockCount;
@ -80,9 +86,10 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
protected static Field fieldGenLayer1;
protected static Field fieldGenLayer2;
protected static MutableGenLayer genLayer;
public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE];
protected static ChunkSection emptySection;
public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE + 1];
static {
try {
emptySection = new ChunkSection(0, true);
@ -93,21 +100,26 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
fieldTickingBlockCount.setAccessible(true);
fieldNonEmptyBlockCount.setAccessible(true);
fieldBiomes = net.minecraft.server.v1_10_R1.ChunkProviderGenerate.class.getDeclaredField("C");
fieldBiomes = ChunkProviderGenerate.class.getDeclaredField("D");
fieldBiomes.setAccessible(true);
fieldChunkGenerator = net.minecraft.server.v1_10_R1.ChunkProviderServer.class.getDeclaredField("chunkGenerator");
fieldChunkGenerator = ChunkProviderServer.class.getDeclaredField("chunkGenerator");
fieldChunkGenerator.setAccessible(true);
fieldSeed = net.minecraft.server.v1_10_R1.WorldData.class.getDeclaredField("e");
fieldSeed = WorldData.class.getDeclaredField("e");
fieldSeed.setAccessible(true);
fieldBiomeCache = net.minecraft.server.v1_10_R1.WorldChunkManager.class.getDeclaredField("c");
fieldBiomeCache = WorldChunkManager.class.getDeclaredField("d");
fieldBiomeCache.setAccessible(true);
fieldBiomes2 = net.minecraft.server.v1_10_R1.WorldChunkManager.class.getDeclaredField("d");
fieldBiomes2 = WorldChunkManager.class.getDeclaredField("e");
fieldBiomes2.setAccessible(true);
fieldGenLayer1 = net.minecraft.server.v1_10_R1.WorldChunkManager.class.getDeclaredField("a") ;
fieldGenLayer2 = net.minecraft.server.v1_10_R1.WorldChunkManager.class.getDeclaredField("b") ;
fieldGenLayer1 = WorldChunkManager.class.getDeclaredField("b") ;
fieldGenLayer2 = WorldChunkManager.class.getDeclaredField("c") ;
fieldGenLayer1.setAccessible(true);
fieldGenLayer2.setAccessible(true);
fieldPalette = DataPaletteBlock.class.getDeclaredField("c");
fieldPalette.setAccessible(true);
fieldSize = DataPaletteBlock.class.getDeclaredField("e");
fieldSize.setAccessible(true);
Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
fieldAir.setAccessible(true);
air = (IBlockData) fieldAir.get(null);
@ -115,12 +127,10 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
fieldBits.setAccessible(true);
getEntitySlices = net.minecraft.server.v1_10_R1.Chunk.class.getDeclaredMethod("getEntitySlices");
getEntitySlices.setAccessible(true);
if (adapter == null) {
setupAdapter(new com.boydti.fawe.bukkit.v1_10.FaweAdapter_1_10());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("=========================================");
}
for (int i = 0; i < Character.MAX_VALUE; i++) {
setupAdapter(new com.boydti.fawe.bukkit.v1_10.FaweAdapter_1_10());
Fawe.debug("Using adapter: " + adapter);
Fawe.debug("=========================================");
for (int i = 0; i < IBD_CACHE.length; i++) {
try {
IBD_CACHE[i] = Block.getById(i >> 4).fromLegacyData(i & 0xF);
} catch (Throwable ignore) {}
@ -140,6 +150,40 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
getImpWorld();
}
@Override
public ChunkSection[] getSections(net.minecraft.server.v1_10_R1.Chunk chunk) {
return chunk.getSections();
}
@Override
public net.minecraft.server.v1_10_R1.Chunk loadChunk(World world, int x, int z, boolean generate) {
net.minecraft.server.v1_10_R1.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_10_R1.CraftWorld) world).getHandle().getChunkProviderServer();
if (generate) {
return provider.getOrLoadChunkAt(x, z);
} else {
return provider.loadChunk(x, z);
}
}
@Override
public ChunkSection[] getCachedSections(World world, int cx, int cz) {
net.minecraft.server.v1_10_R1.Chunk chunk = ((org.bukkit.craftbukkit.v1_10_R1.CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz);
if (chunk != null) {
return chunk.getSections();
}
return null;
}
@Override
public net.minecraft.server.v1_10_R1.Chunk getCachedChunk(World world, int cx, int cz) {
return ((org.bukkit.craftbukkit.v1_10_R1.CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz);
}
@Override
public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) {
return chunkSections[cy];
}
@Override
public boolean regenerateChunk(World world, int x, int z, BaseBiome biome, Long seed) {
if (biome != null) {
@ -149,10 +193,10 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
}
nmsWorld.worldData.getSeed();
boolean result;
net.minecraft.server.v1_10_R1.ChunkProviderGenerate generator = new net.minecraft.server.v1_10_R1.ChunkProviderGenerate(nmsWorld, seed, false, "");
ChunkProviderGenerate generator = new ChunkProviderGenerate(nmsWorld, seed, false, "");
Biome bukkitBiome = adapter.getBiome(biome.getId());
net.minecraft.server.v1_10_R1.BiomeBase base = net.minecraft.server.v1_10_R1.BiomeBase.getBiome(biome.getId());
fieldBiomes.set(generator, new net.minecraft.server.v1_10_R1.BiomeBase[]{base});
BiomeBase base = BiomeBase.getBiome(biome.getId());
fieldBiomes.set(generator, new BiomeBase[]{base});
boolean cold = base.getTemperature() <= 1;
net.minecraft.server.v1_10_R1.ChunkGenerator existingGenerator = nmsWorld.getChunkProviderServer().chunkGenerator;
long existingSeed = world.getSeed();
@ -166,7 +210,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
fieldSeed.set(nmsWorld.worldData, seed);
ReflectionUtils.setFailsafeFieldValue(fieldBiomeCache, this.nmsWorld.getWorldChunkManager(), new net.minecraft.server.v1_10_R1.BiomeCache(this.nmsWorld.getWorldChunkManager()));
ReflectionUtils.setFailsafeFieldValue(fieldBiomeCache, this.nmsWorld.getWorldChunkManager(), new BiomeCache(this.nmsWorld.getWorldChunkManager()));
ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProviderServer(), generator);
@ -217,9 +261,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
section.getEmittedLightArray().a(x & 15, y & 15, z & 15, value);
}
protected DataBits lastBits;
protected DataPaletteBlock lastBlocks;
@Override
public World createWorld(final WorldCreator creator) {
final String name = creator.name();
@ -303,46 +344,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
});
}
@Override
public int getBiome(net.minecraft.server.v1_10_R1.Chunk chunk, int x, int z) {
return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)];
}
@Override
public net.minecraft.server.v1_10_R1.ChunkSection[] getSections(net.minecraft.server.v1_10_R1.Chunk chunk) {
return chunk.getSections();
}
@Override
public net.minecraft.server.v1_10_R1.Chunk loadChunk(World world, int x, int z, boolean generate) {
net.minecraft.server.v1_10_R1.Chunk chunk;
net.minecraft.server.v1_10_R1.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_10_R1.CraftWorld) world).getHandle().getChunkProviderServer();
if (generate) {
return provider.getOrLoadChunkAt(x, z);
} else {
return provider.loadChunk(x, z);
}
}
@Override
public net.minecraft.server.v1_10_R1.ChunkSection[] getCachedSections(World world, int cx, int cz) {
net.minecraft.server.v1_10_R1.Chunk chunk = ((org.bukkit.craftbukkit.v1_10_R1.CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz);
if (chunk != null) {
return chunk.getSections();
}
return null;
}
@Override
public net.minecraft.server.v1_10_R1.Chunk getCachedChunk(World world, int cx, int cz) {
return ((org.bukkit.craftbukkit.v1_10_R1.CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz);
}
@Override
public net.minecraft.server.v1_10_R1.ChunkSection getCachedSection(net.minecraft.server.v1_10_R1.ChunkSection[] chunkSections, int cy) {
return chunkSections[cy];
}
@Override
public int getCombinedId4Data(ChunkSection lastSection, int x, int y, int z) {
DataPaletteBlock dataPalette = lastSection.getBlocks();
@ -356,6 +357,11 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
}
}
@Override
public int getBiome(net.minecraft.server.v1_10_R1.Chunk chunk, int x, int z) {
return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)];
}
@Override
public int getOpacity(ChunkSection section, int x, int y, int z) {
DataPaletteBlock dataPalette = section.getBlocks();
@ -403,6 +409,13 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
if (playerChunk.c.isEmpty()) {
return;
}
if (mask == 0) {
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65535);
for (EntityPlayer player : playerChunk.c) {
player.playerConnection.sendPacket(packet);
}
return;
}
// Send chunks
boolean empty = false;
ChunkSection[] sections = nmsChunk.getSections();
@ -523,7 +536,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
}
public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException {
fieldSection.setAccessible(true);
fieldSection.set(section, palette);
Arrays.fill(section.getEmittedLightArray().asBytes(), (byte) 0);
}
@ -554,33 +566,18 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
public BukkitChunk_1_10 getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
Map<BlockPosition, TileEntity> tiles = (Map<BlockPosition, TileEntity>) tilesGeneric;
Collection<Entity>[] entities = (Collection<Entity>[]) entitiesGeneric;
BukkitChunk_1_10 previous = getFaweChunk(fs.getX(), fs.getZ());
// Copy blocks
char[][] idPrevious = previous.getCombinedIdArrays();
BukkitChunk_1_10_Copy previous = new BukkitChunk_1_10_Copy(this, fs.getX(), fs.getZ());
for (int layer = 0; layer < sections.length; layer++) {
if (fs.getCount(layer) != 0 || all) {
ChunkSection section = sections[layer];
if (section != null) {
short solid = 0;
char[] previousLayer = idPrevious[layer] = new char[4096];
DataPaletteBlock blocks = section.getBlocks();
for (int j = 0; j < 4096; j++) {
int x = FaweCache.CACHE_X[0][j];
int y = FaweCache.CACHE_Y[0][j];
int z = FaweCache.CACHE_Z[0][j];
IBlockData ibd = blocks.a(x, y, z);
Block block = ibd.getBlock();
int combined = Block.getId(block);
if (FaweCache.hasData(combined)) {
combined = (combined << 4) + block.toLegacyData(ibd);
} else {
combined = combined << 4;
}
if (combined > 1) {
solid++;
}
previousLayer[j] = (char) combined;
}
byte[] ids = new byte[4096];
NibbleArray data = new NibbleArray();
blocks.exportData(ids, data);
previous.set(layer, ids, data.asBytes());
short solid = (short) fieldNonEmptyBlockCount.getInt(section);
previous.count[layer] = solid;
previous.air[layer] = (short) (4096 - solid);
}
@ -605,7 +602,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<net.minecraft.server.v1_10_R
}
int x = ((int) Math.round(ent.locX) & 15);
int z = ((int) Math.round(ent.locZ) & 15);
int y = ((int) Math.round(ent.locY)) & 255;
int y = ((int) Math.round(ent.locY) & 0xFF);
int i = FaweCache.CACHE_I[y][z][x];
char[] array = fs.getIdArray(i);
if (array == null) {

View File

@ -0,0 +1,118 @@
package com.boydti.fawe.bukkit.v1_11.compression;
import com.boydti.fawe.util.MainUtil;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.LoaderClassPath;
import net.minecraft.server.v1_11_R1.RegionFile;
public class CompressionOptimizer {
private final ClassPool pool;
public CompressionOptimizer() {
this.pool = ClassPool.getDefault();
}
public void loadSafe(String name) throws Throwable {
try {
pool.get(name).toClass();
} catch (Throwable e) {
while (e.getCause() != null) {
e = e.getCause();
}
if (e instanceof ClassNotFoundException) {
loadSafe(e.getMessage());
}
}
}
public void loadPackage(String... packages) throws IOException {
JarInputStream jarFile = new JarInputStream(new FileInputStream(MainUtil.getJarFile()));
JarEntry jarEntry;
while(true) {
jarEntry = jarFile.getNextJarEntry();
if(jarEntry == null){
break;
}
if (jarEntry.getName ().endsWith (".class")) {
for (String p : packages) {
if (jarEntry.getName ().startsWith(p)) {
String name = jarEntry.getName().substring(0, jarEntry.getName().length() - 6).replaceAll("/", "\\.");
try {
loadSafe(name);
} catch (Throwable ignore) {}
break;
}
}
}
}
}
public void optimize() throws Throwable {
// pool.insertClassPath(new ClassClassPath(PGZIPOutputStream.class));
// pool.insertClassPath(new ClassClassPath(PGZIPBlock.class));
// pool.insertClassPath(new ClassClassPath(PGZIPState.class));
// pool.insertClassPath(new ClassClassPath(PGZIPThreadLocal.class));
// pool.insertClassPath(new ClassClassPath(ClassPath.class));
// pool.insertClassPath(new ClassClassPath(CompressionOptimizer.class));
pool.insertClassPath(new LoaderClassPath(this.getClass().getClassLoader()));
pool.get("com.boydti.fawe.object.io.PGZIPOutputStream").toClass();
pool.get("com.boydti.fawe.object.io.PGZIPBlock").toClass();
pool.get("com.boydti.fawe.object.io.PGZIPState").toClass();
pool.get("com.boydti.fawe.object.io.PGZIPThreadLocal").toClass();
pool.get("com.boydti.fawe.bukkit.v1_11.compression.CompressionOptimizer").toClass();
pool.get("javassist.ClassPath").toClass();
pool.importPackage("net.minecraft.server.v1_11_R1");
pool.importPackage("java.lang");
pool.importPackage("java.lang.reflect");
pool.importPackage("java.io");
pool.importPackage("com.boydti.fawe.bukkit.v1_11.compression");
// RegionFile.class.getDeclaredClasses()[0];
{ // Optimize NBTCompressedStreamTools
CtClass clazz = pool.get("net.minecraft.server.v1_11_R1.NBTCompressedStreamTools");
CtMethod methodA_getStream = clazz.getDeclaredMethod("a", new CtClass[]{pool.get("net.minecraft.server.v1_11_R1.NBTTagCompound"), pool.get("java.io.OutputStream")});
methodA_getStream.setBody("{" +
"java.io.DataOutputStream dataoutputstream = new java.io.DataOutputStream(new java.io.BufferedOutputStream(new com.boydti.fawe.object.io.PGZIPOutputStream($2)));" +
"try {" +
" a($1, (java.io.DataOutput) dataoutputstream);" +
"} finally {" +
" dataoutputstream.close();" +
"}" +
"}");
clazz.toClass();
}
{ // Optimize RegionFile
CtClass clazz = pool.get("net.minecraft.server.v1_11_R1.RegionFile");
CtMethod methodB_getStream = clazz.getDeclaredMethod("b", new CtClass[]{CtClass.intType, CtClass.intType});
methodB_getStream.setBody("{" +
"Constructor constructor = $0.getClass().getDeclaredClasses()[0].getConstructors()[0];" +
" constructor.setAccessible(true);" +
" return $0.d($1, $2) ? null : new java.io.DataOutputStream(new java.io.BufferedOutputStream(new com.boydti.fawe.object.io.PGZIPOutputStream((OutputStream) CompressionOptimizer.newInstance(constructor, $0, $1, $2))));" +
"}");
clazz.toClass();
// RegionFile $0 = null;
// int $1 = 0;
// int $2 = 0;
//
// Constructor<?> constructor = $0.getClass().getDeclaredClasses()[0].getConstructors()[0];
// constructor.setAccessible(true);
// return $0.d($1, $2) ? null : new java.io.DataOutputStream(new java.io.BufferedOutputStream(new com.boydti.fawe.object.io.PGZIPOutputStream((OutputStream) constructor.newInstance($1, $2))));
}
}
public static Object newInstance(Constructor constructor, RegionFile file, int a, int b) throws IllegalAccessException, InvocationTargetException, InstantiationException {
return constructor.newInstance(file, a, b);
}
}

View File

@ -14,9 +14,6 @@ dependencies {
}
}
sourceCompatibility = 1.7
targetCompatibility = 1.7
processResources {
from('src/main/resources') {
include 'fawe.properties'

View File

@ -8,6 +8,7 @@ import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Commands;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.brush.visualization.VisualQueue;
import com.boydti.fawe.regions.general.plot.PlotSquaredFeature;
import com.boydti.fawe.util.FaweTimer;
import com.boydti.fawe.util.MainUtil;
@ -26,6 +27,7 @@ import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockData;
import com.sk89q.worldedit.command.BiomeCommands;
import com.sk89q.worldedit.command.BrushCommands;
@ -69,6 +71,7 @@ import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.function.entity.ExtentEntityCopy;
import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.mask.FuzzyBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.MaskUnion;
import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.function.mask.OffsetMask;
@ -77,6 +80,7 @@ import com.sk89q.worldedit.function.operation.ChangeSetExecutor;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.ClipboardPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.Patterns;
import com.sk89q.worldedit.function.pattern.RandomPattern;
import com.sk89q.worldedit.function.visitor.BreadthFirstSearch;
@ -167,6 +171,8 @@ public class Fawe {
*/
private final FaweTimer timer;
private FaweVersion version;
private VisualQueue visualQueue;
private Updater updater;
/**
* Get the implementation specific class
@ -242,7 +248,7 @@ public class Fawe {
* Instance independent stuff
*/
this.setupMemoryListener();
timer = new FaweTimer();
this.timer = new FaweTimer();
Fawe.this.IMP.setupVault();
// Delayed worldedit setup
@ -250,6 +256,7 @@ public class Fawe {
@Override
public void run() {
try {
visualQueue = new VisualQueue();
WEManager.IMP.managers.addAll(Fawe.this.IMP.getMaskManagers());
WEManager.IMP.managers.add(new PlotSquaredFeature());
Fawe.debug("Plugin 'PlotSquared' found. Using it now.");
@ -265,7 +272,8 @@ public class Fawe {
TaskManager.IMP.repeatAsync(new Runnable() {
@Override
public void run() {
Updater.update(IMP.getPlatform(), getVersion());
updater = new Updater();
updater.update(IMP.getPlatform(), getVersion());
}
}, 36000);
}
@ -277,6 +285,15 @@ public class Fawe {
return isJava8;
}
/**
* The FAWE updater class
* - Use to get basic update information (changelog/version etc)
* @return
*/
public Updater getUpdater() {
return updater;
}
/**
* The FaweTimer is a useful class for monitoring TPS
* @return FaweTimer
@ -285,6 +302,14 @@ public class Fawe {
return timer;
}
/**
* The visual queue is used to queue visualizations
* @return
*/
public VisualQueue getVisualQueue() {
return visualQueue;
}
/**
* The FAWE version
* - Unofficial jars may be lacking version information
@ -306,6 +331,7 @@ public class Fawe {
}
public void setupConfigs() {
MainUtil.copyFile(MainUtil.getJarFile(), "de/messages.yml", null);
// Setting up config.yml
File file = new File(this.IMP.getDirectory(), "config.yml");
Settings.IMP.PLATFORM = IMP.getPlatform().replace("\"", "");
@ -345,7 +371,7 @@ public class Fawe {
Commands.inject(); // Translations
EditSession.inject(); // Custom block placer + optimizations
EditSessionEvent.inject(); // Add EditSession to event (API)
LocalSession.inject(); // Add remember order / queue flushing / Optimizations for disk
LocalSession.inject(); // Add remember order / queue flushing / Optimizations for disk / brush visualization
SessionManager.inject(); // Faster custom session saving + Memory improvements
Request.inject(); // Custom pattern extent
// Commands
@ -381,7 +407,7 @@ public class Fawe {
LongRangeBuildTool.inject();
AreaPickaxe.inject(); // Fixes
RecursivePickaxe.inject(); // Fixes
BrushTool.inject(); // Add transform
BrushTool.inject(); // Add transform + support for double action brushes + visualizations
// Selectors
CuboidRegionSelector.inject(); // Translations
EllipsoidRegion.inject(); // Optimizations
@ -415,13 +441,17 @@ public class Fawe {
BlockVector.inject(); // Optimizations
Vector.inject(); // Optimizations
Vector2D.inject(); // Optimizations
// Block
BaseBlock.inject(); // Optimizations
// Pattern
Pattern.inject(); // Simplify API
Patterns.inject(); // Optimizations (reduce object creation)
RandomPattern.inject(); // Optimizations
ClipboardPattern.inject(); // Optimizations
HashTagPatternParser.inject(); // Add new patterns
DefaultBlockParser.inject(); // Fix block lookups
// Mask
Mask.inject(); // Extend deprecated mask
BlockMask.inject(); // Optimizations
SolidBlockMask.inject(); // Optimizations
FuzzyBlockMask.inject(); // Optimizations

View File

@ -14,9 +14,10 @@ import com.sk89q.jnbt.LongTag;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.ImmutableBlock;
import com.sk89q.worldedit.blocks.ImmutableDatalessBlock;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.awt.Color;
@ -171,34 +172,11 @@ public class FaweCache {
for (int i = 0; i < Character.MAX_VALUE; i++) {
int id = i >> 4;
int data = i & 0xf;
CACHE_BLOCK[i] = new BaseBlock(id, data) {
@Override
public void setData(int data) {
throw new IllegalStateException("Cannot set data");
}
@Override
public void setId(int id) {
throw new IllegalStateException("Cannot set id");
}
@Override
public BaseBlock flip() {
BaseBlock clone = new BaseBlock(getId(), getData(), getNbtData());
return clone.flip();
}
@Override
public BaseBlock flip(CuboidClipboard.FlipDirection direction) {
BaseBlock clone = new BaseBlock(getId(), getData(), getNbtData());
return clone.flip(direction);
}
@Override
public boolean hasWildcardData() {
return true;
}
};
if (FaweCache.hasData(id)) {
CACHE_BLOCK[i] = new ImmutableBlock(id, data);
} else {
CACHE_BLOCK[i] = new ImmutableDatalessBlock(id);
}
CACHE_ITEM[i] = new BaseItem(id, (short) data) {
@Override

View File

@ -7,12 +7,14 @@ import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.util.HastebinUtility;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.Updater;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.net.URL;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.Scanner;
public class Reload extends FaweCommand {
@ -23,7 +25,7 @@ public class Reload extends FaweCommand {
@Override
public boolean execute(final FawePlayer player, final String... args) {
if (args.length != 1) {
BBC.COMMAND_SYNTAX.send(player, "/fawe [reload|version|debugpaste|threads]");
BBC.COMMAND_SYNTAX.send(player, "/fawe [reload|version|debugpaste|threads|changelog]");
return false;
}
switch (args[0].toLowerCase()) {
@ -54,6 +56,22 @@ public class Reload extends FaweCommand {
}
return true;
}
case "changelog": {
try {
Updater updater = Fawe.get().getUpdater();
String changes = updater != null ? updater.getChanges() : null;
if (changes == null) {
try (Scanner scanner = new Scanner(new URL("http://boydti.com/fawe/cl?" + Integer.toHexString(Fawe.get().getVersion().hash)).openStream(), "UTF-8")) {
changes = scanner.useDelimiter("\\A").next();
}
}
player.sendMessage(BBC.getPrefix() + changes);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
case "debugpaste":
case "paste": {
try {

View File

@ -123,6 +123,7 @@ public enum BBC {
BRUSH_SPLINE_SECONDARY("Created spline", "WorldEdit.Brush"),
BRUSH_BLEND_BALL("Blend ball brush equipped (%s0).", "WorldEdit.Brush"),
BRUSH_ERODE("Erode brush equipped (%s0). Right click to erode, left click to pull.", "WorldEdit.Brush"),
BRUSH_CIRCLE("Circle brush equipped (%s0). Right click to create a circle.", "WorldEdit.Brush"),
BRUSH_RECURSIVE("Recursive brush equipped (%s0).", "WorldEdit.Brush"),
BRUSH_PASTE_NONE("Nothing to paste", "WorldEdit.Brush"),
BRUSH_SIZE("Brush size set", "WorldEdit.Brush"),

View File

@ -2,7 +2,6 @@ package com.boydti.fawe.config;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer;
import com.sk89q.worldedit.LocalSession;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
@ -26,6 +25,9 @@ public class Settings extends Config {
@Final
public String PLATFORM; // These values are set from FAWE before loading
@Comment({"Options: de",
"Create a PR to contribute a translation: https://github.com/boy0001/FastAsyncWorldedit/new/master/core/src/main/resources",})
public String LANGUAGE = "";
@Comment("Allow the plugin to update")
public boolean UPDATE = true;
@Comment("Send anonymous usage statistics to MCStats.org")
@ -330,9 +332,6 @@ public class Settings extends Config {
public void reload(File file) {
load(file);
save(file);
if (HISTORY.USE_DISK) {
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
}
}
public FaweLimit getLimit(FawePlayer player) {

View File

@ -0,0 +1,34 @@
package com.boydti.fawe.example;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.util.MainUtil;
public class NullQueueCharFaweChunk extends CharFaweChunk {
public NullQueueCharFaweChunk(int cx, int cz) {
super(null, cx, cz);
}
public NullQueueCharFaweChunk(int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
super(null, x, z, ids, count, air, heightMap);
}
@Override
public Object getNewChunk() {
return null;
}
@Override
public CharFaweChunk copy(boolean shallow) {
if (shallow) {
return new NullQueueCharFaweChunk(getX(), getZ(), ids, count, air, heightMap);
} else {
return new NullQueueCharFaweChunk(getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
}
}
@Override
public FaweChunk call() {
return null;
}
}

View File

@ -350,9 +350,9 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
}
@Override
public void sendBlockUpdate(Map<Long, Map<Short, Character>> blockMap, FawePlayer... players) {
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
if (parent != null) {
parentNMS.sendBlockUpdate(blockMap, players);
parentNMS.sendBlockUpdate(chunk, players);
}
}
}

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.boydti.fawe.util.MainUtil;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BaseBlock;
@ -146,6 +147,20 @@ public abstract class FaweChunk<T> implements Callable<FaweChunk> {
public abstract byte[] getBiomeArray();
public void forEachQueuedBlock(FaweChunkVisitor onEach) {
for (int y = 0; y < HEIGHT; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
int combined = getBlockCombinedId(x, y, z);
if (combined == 0) {
continue;
}
onEach.run(x, y, z, combined);
}
}
}
}
public char[][] getCombinedIdArrays() {
char[][] ids = new char[HEIGHT >> 4][];
for (int y = 0; y < HEIGHT >> 4; y++) {

View File

@ -209,7 +209,7 @@ public abstract class FawePlayer<T> extends Metadatable {
try {
if (file.exists() && file.length() > 5) {
DiskOptimizedClipboard doc = new DiskOptimizedClipboard(file);
Player player = getPlayer();
Player player = toWorldEditPlayer();
LocalSession session = getSession();
try {
if (session.getClipboard() != null) {
@ -331,7 +331,16 @@ public abstract class FawePlayer<T> extends Metadatable {
* Get the WorldEdit player object
* @return
*/
public abstract Player getPlayer();
public abstract Player toWorldEditPlayer();
private Player cachedWorldEditPlayer;
public Player getPlayer() {
if (cachedWorldEditPlayer == null) {
cachedWorldEditPlayer = toWorldEditPlayer();
}
return cachedWorldEditPlayer;
}
/**
* Get the player's current selection (or null)
@ -382,7 +391,7 @@ public abstract class FawePlayer<T> extends Metadatable {
* @param selector
*/
public void setSelection(final RegionSelector selector) {
this.getSession().setRegionSelector(getPlayer().getWorld(), selector);
this.getSession().setRegionSelector(toWorldEditPlayer().getWorld(), selector);
}
/**
@ -422,7 +431,7 @@ public abstract class FawePlayer<T> extends Metadatable {
public void unregister() {
if (Settings.IMP.HISTORY.DELETE_ON_LOGOUT) {
session = getSession();
WorldEdit.getInstance().removeSession(getPlayer());
WorldEdit.getInstance().removeSession(toWorldEditPlayer());
session.setClipboard(null);
session.clearHistory();
}
@ -433,7 +442,7 @@ public abstract class FawePlayer<T> extends Metadatable {
* Get a new EditSession from this player
*/
public EditSession getNewEditSession() {
return WorldEdit.getInstance().getEditSessionFactory().getEditSession(getWorld(), -1, getPlayer());
return WorldEdit.getInstance().getEditSessionFactory().getEditSession(getWorld(), -1, toWorldEditPlayer());
}

View File

@ -25,7 +25,6 @@ import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedDeque;
@ -308,7 +307,7 @@ public abstract class FaweQueue implements HasFaweQueue {
return count;
}
public abstract void sendBlockUpdate(Map<Long, Map<Short, Character>> blockMap, FawePlayer... players);
public abstract void sendBlockUpdate(FaweChunk chunk, FawePlayer... players);
@Deprecated
public boolean next() {

View File

@ -0,0 +1,48 @@
package com.boydti.fawe.object.brush;
import com.boydti.fawe.object.brush.visualization.VisualBrush;
import com.boydti.fawe.object.collection.LocalBlockVectorSet;
import com.boydti.fawe.wrappers.LocationMaskedPlayerWrapper;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.transform.AffineTransform;
public class CircleBrush extends VisualBrush {
private final Player player;
public CircleBrush(BrushTool tool, Player player) {
super(tool);
this.player = LocationMaskedPlayerWrapper.unwrap(player);
}
@Override
public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
switch (action) {
case PRIMARY:
LocalBlockVectorSet set = new LocalBlockVectorSet();
int radius = (int) size;
Vector normal = position.subtract(player.getPosition());
editSession.makeCircle(position, pattern, size, size, size, false, normal);
break;
case SECONDARY:
break;
}
}
private static Vector any90Rotate(Vector normal) {
normal = normal.normalize();
if (normal.getX() == 1 || normal.getY() == 1 || normal.getZ() == 1) {
return new Vector(normal.getZ(), normal.getX(), normal.getY());
}
AffineTransform affine = new AffineTransform();
affine = affine.rotateX(90);
affine = affine.rotateY(90);
affine = affine.rotateZ(90);
Vector random = affine.apply(normal);
return random.cross(normal).normalize();
}
}

View File

@ -11,6 +11,7 @@ import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
@ -23,14 +24,14 @@ import com.sk89q.worldedit.session.ClipboardHolder;
public class CopyPastaBrush implements DoubleActionBrush {
private final DoubleActionBrushTool tool;
private final BrushTool tool;
public CopyPastaBrush(DoubleActionBrushTool tool) {
public CopyPastaBrush(BrushTool tool) {
this.tool = tool;
}
@Override
public void build(DoubleActionBrushTool.BrushAction action, final EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
public void build(BrushTool.BrushAction action, final EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
FawePlayer fp = editSession.getPlayer();
LocalSession session = fp.getSession();
switch (action) {

View File

@ -3,8 +3,16 @@ package com.boydti.fawe.object.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.function.pattern.Pattern;
public interface DoubleActionBrush {
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException;
public interface DoubleActionBrush extends Brush {
@Override
default void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
build(BrushTool.BrushAction.PRIMARY, editSession, position, pattern, size);
}
public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException;
}

View File

@ -1,239 +0,0 @@
package com.boydti.fawe.object.brush;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.command.tool.DoubleActionTraceTool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.MaskIntersection;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.session.request.Request;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public class DoubleActionBrushTool implements DoubleActionTraceTool {
public enum BrushAction {
PRIMARY,
SECONDARY
}
protected static int MAX_RANGE = 500;
protected int range = -1;
private Mask mask = null;
private Mask sourceMask = null;
private ResettableExtent transform = null;
private DoubleActionBrush brush = null;
@Nullable
private Pattern material;
private double size = 1;
private String permission;
/**
* Construct the tool.
*
* @param permission the permission to check before use is allowed
*/
public DoubleActionBrushTool(String permission) {
checkNotNull(permission);
this.permission = permission;
}
@Override
public boolean canUse(Actor player) {
return player.hasPermission(permission);
}
public ResettableExtent getTransform() {
return transform;
}
public void setTransform(ResettableExtent transform) {
this.transform = transform;
}
/**
* Get the filter.
*
* @return the filter
*/
public Mask getMask() {
return mask;
}
/**
* Get the filter.
*
* @return the filter
*/
public Mask getSourceMask() {
return sourceMask;
}
/**
* Set the block filter used for identifying blocks to replace.
*
* @param filter the filter to set
*/
public void setMask(Mask filter) {
this.mask = filter;
}
/**
* Set the block filter used for identifying blocks to replace.
*
* @param filter the filter to set
*/
public void setSourceMask(Mask filter) {
this.sourceMask = filter;
}
/**
* Set the brush.
*
* @param brush tbe brush
* @param permission the permission
*/
public void setBrush(DoubleActionBrush brush, String permission) {
this.brush = brush;
this.permission = permission;
}
/**
* Get the current brush.
*
* @return the current brush
*/
public DoubleActionBrush getBrush() {
return brush;
}
/**
* Set the material.
*
* @param material the material
*/
public void setFill(@Nullable Pattern material) {
this.material = material;
}
/**
* Get the material.
*
* @return the material
*/
@Nullable public Pattern getMaterial() {
return material;
}
/**
* Get the set brush size.
*
* @return a radius
*/
public double getSize() {
return size;
}
/**
* Set the set brush size.
*
* @param radius a radius
*/
public void setSize(double radius) {
this.size = radius;
}
/**
* Get the set brush range.
*
* @return the range of the brush in blocks
*/
public int getRange() {
return (range < 0) ? MAX_RANGE : Math.min(range, MAX_RANGE);
}
/**
* Set the set brush range.
*
* @param range the range of the brush in blocks
*/
public void setRange(int range) {
this.range = range;
}
public boolean act(BrushAction action, Platform server, LocalConfiguration config, Player player, LocalSession session) {
WorldVector target = null;
target = player.getBlockTrace(getRange(), true);
if (target == null) {
BBC.NO_BLOCK.send(player);
return true;
}
BlockBag bag = session.getBlockBag(player);
EditSession editSession = session.createEditSession(player);
Request.request().setEditSession(editSession);
if (mask != null) {
Mask existingMask = editSession.getMask();
if (existingMask == null) {
editSession.setMask(mask);
} else if (existingMask instanceof MaskIntersection) {
((MaskIntersection) existingMask).add(mask);
} else {
MaskIntersection newMask = new MaskIntersection(existingMask);
newMask.add(mask);
editSession.setMask(newMask);
}
}
if (sourceMask != null) {
Mask existingMask = editSession.getSourceMask();
if (existingMask == null) {
editSession.setSourceMask(sourceMask);
} else if (existingMask instanceof MaskIntersection) {
((MaskIntersection) existingMask).add(sourceMask);
} else {
MaskIntersection newMask = new MaskIntersection(existingMask);
newMask.add(sourceMask);
editSession.setSourceMask(newMask);
}
}
if (transform != null) {
editSession.addTransform(transform);
}
try {
brush.build(action, editSession, target, material, size);
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached."); // Never happens
} finally {
if (bag != null) {
bag.flushChanges();
}
session.remember(editSession);
}
return true;
}
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
return act(BrushAction.PRIMARY, server, config, player, session);
}
@Override
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
return act(BrushAction.SECONDARY, server, config, player, session);
}
}

View File

@ -10,6 +10,7 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.util.Arrays;
@ -20,7 +21,7 @@ public class ErodeBrush implements DoubleActionBrush {
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)};
@Override
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
switch (action) {
case PRIMARY: {
int erodeFaces = 2;

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
@ -12,18 +13,18 @@ import java.io.InputStream;
public class FlattenBrush extends HeightBrush {
public FlattenBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard, ScalableHeightMap.Shape shape) {
public FlattenBrush(InputStream stream, int rotation, double yscale, BrushTool tool, Clipboard clipboard, ScalableHeightMap.Shape shape) {
super(stream, rotation, yscale, tool, clipboard, shape);
}
@Override
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
int size = (int) sizeDouble;
Mask mask = tool.getMask();
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
mask = null;
}
heightMap.setSize(size);
heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, true);
heightMap.apply(editSession, mask, position, size, rotation, action == BrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, true);
}
}

View File

@ -6,6 +6,7 @@ import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
@ -18,14 +19,13 @@ public class HeightBrush implements DoubleActionBrush {
public final ScalableHeightMap heightMap;
public final int rotation;
public final double yscale;
public final DoubleActionBrushTool tool;
public final BrushTool tool;
public HeightBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) {
public HeightBrush(InputStream stream, int rotation, double yscale, BrushTool tool, Clipboard clipboard) {
this(stream, rotation, yscale, tool, clipboard, ScalableHeightMap.Shape.CONE);
}
public HeightBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard, ScalableHeightMap.Shape shape) {
this.tool = tool;
public HeightBrush(InputStream stream, int rotation, double yscale, BrushTool tool, Clipboard clipboard, ScalableHeightMap.Shape shape) {
this.rotation = (rotation / 90) % 4;
this.yscale = yscale;
if (stream != null) {
@ -39,16 +39,17 @@ public class HeightBrush implements DoubleActionBrush {
} else {
heightMap = ScalableHeightMap.fromShape(shape);
}
this.tool = tool;
}
@Override
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
int size = (int) sizeDouble;
Mask mask = tool.getMask();
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
mask = null;
}
heightMap.setSize(size);
heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, false);
heightMap.apply(editSession, mask, position, size, rotation, action == BrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, false);
}
}

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.object.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.Patterns;
@ -18,7 +19,7 @@ public class LineBrush implements DoubleActionBrush {
}
@Override
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, final Pattern pattern, double size) throws MaxChangedBlocksException {
public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, final Pattern pattern, double size) throws MaxChangedBlocksException {
switch (action) {
case PRIMARY:
if (pos1 == null) {

View File

@ -0,0 +1,7 @@
package com.boydti.fawe.object.brush;
import com.sk89q.worldedit.entity.Player;
public interface MovableBrush {
public boolean move(Player player);
}

View File

@ -3,13 +3,14 @@ package com.boydti.fawe.object.brush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.function.pattern.Pattern;
public class RaiseBrush implements DoubleActionBrush {
@Override
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
switch (action) {
case PRIMARY:
break;

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.brush;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.brush.visualization.VisualExtent;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.mask.IdMask;
import com.boydti.fawe.object.visitor.DFSRecursiveVisitor;
@ -9,6 +10,7 @@ import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.mask.Mask;
@ -16,8 +18,6 @@ import com.sk89q.worldedit.function.mask.MaskIntersection;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.Patterns;
import com.sk89q.worldedit.math.interpolation.Interpolation;
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
import com.sk89q.worldedit.math.interpolation.Node;
import com.sk89q.worldedit.math.transform.AffineTransform;
import java.util.ArrayList;
@ -30,11 +30,11 @@ public class SplineBrush implements DoubleActionBrush {
private ArrayList<ArrayList<Vector>> positionSets;
private int numSplines;
private final DoubleActionBrushTool tool;
private final BrushTool tool;
private final LocalSession session;
private final Player player;
public SplineBrush(Player player, LocalSession session, DoubleActionBrushTool tool) {
public SplineBrush(Player player, LocalSession session, BrushTool tool) {
this.tool = tool;
this.session = session;
this.player = player;
@ -42,15 +42,20 @@ public class SplineBrush implements DoubleActionBrush {
}
@Override
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, final Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
public void build(BrushTool.BrushAction action, EditSession editSession, final Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
Mask mask = tool.getMask();
if (mask == null) {
mask = new IdMask(editSession);
} else {
mask = new MaskIntersection(mask, new IdMask(editSession));
}
boolean visualization = editSession.getExtent() instanceof VisualExtent;
if (visualization && positionSets.isEmpty()) {
return;
}
int originalSize = numSplines;
switch (action) {
case PRIMARY: { // Right
case PRIMARY: {
if (positionSets.size() >= MAX_POINTS) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
}
@ -62,6 +67,17 @@ public class SplineBrush implements DoubleActionBrush {
return true;
}
}, (int) size, 1);
Collection<Vector> directions = visitor.getDirections();
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
for (int z = -1; z <= 1; z++) {
Vector pos = new Vector(x, y, z);
if (!directions.contains(pos)) {
directions.add(pos);
}
}
}
}
visitor.visit(position);
Operations.completeBlindly(visitor);
if (points.size() > numSplines) {
@ -69,7 +85,9 @@ public class SplineBrush implements DoubleActionBrush {
}
this.positionSets.add(points);
player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE_PRIMARY.s());
break;
if (!visualization) {
break;
}
}
case SECONDARY: {
if (positionSets.size() < 2) {
@ -88,7 +106,6 @@ public class SplineBrush implements DoubleActionBrush {
final List<Node> nodes = new ArrayList<Node>(centroids.size());
final Interpolation interpol = new KochanekBartelsInterpolation();
for (final Vector nodevector : centroids) {
final Node n = new Node(nodevector);
n.setTension(tension);
@ -113,8 +130,13 @@ public class SplineBrush implements DoubleActionBrush {
editSession.drawSpline(Patterns.wrap(pattern), currentSpline, 0, 0, 0, 10, 0, true);
}
player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE_SECONDARY.s());
positionSets.clear();
numSplines = 0;
if (visualization) {
positionSets.clear();
numSplines = 0;
} else {
numSplines = originalSize;
positionSets.remove(positionSets.size() - 1);
}
break;
}
}

View File

@ -0,0 +1,8 @@
package com.boydti.fawe.object.brush;
public enum TargetMode {
TARGET_BLOCK_RANGE,
FOWARD_POINT_PITCH,
TARGET_POINT_HEIGHT,
TARGET_POINT_RANGE,
}

View File

@ -0,0 +1,11 @@
package com.boydti.fawe.object.brush.scroll;
import com.sk89q.worldedit.command.tool.BrushTool;
public abstract class ScrollAction implements ScrollableBrush {
public final BrushTool tool;
public ScrollAction(BrushTool tool) {
this.tool = tool;
}
}

View File

@ -0,0 +1,4 @@
package com.boydti.fawe.object.brush.scroll;
public class ScrollClipboard {
}

View File

@ -0,0 +1,25 @@
package com.boydti.fawe.object.brush.scroll;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.function.mask.Mask;
public class ScrollMask extends ScrollAction {
private final Mask[] masks;
private int index;
public ScrollMask(BrushTool tool, Mask... masks) {
super(tool);
this.masks = masks;
}
@Override
public boolean increment(int amount) {
if (masks.length > 1) {
tool.setMask(masks[MathMan.wrap(index += amount, 0, masks.length - 1)]);
return true;
}
return false;
}
}

View File

@ -0,0 +1,25 @@
package com.boydti.fawe.object.brush.scroll;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.function.pattern.Pattern;
public class ScrollPattern extends ScrollAction {
private final Pattern[] patterns;
private int index;
public ScrollPattern(BrushTool tool, Pattern... patterns) {
super(tool);
this.patterns = patterns;
}
@Override
public boolean increment(int amount) {
if (patterns.length > 1) {
tool.setFill(patterns[MathMan.wrap(index += amount, 0, patterns.length - 1)]);
return true;
}
return false;
}
}

View File

@ -0,0 +1,19 @@
package com.boydti.fawe.object.brush.scroll;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.tool.BrushTool;
public class ScrollRange extends ScrollAction {
public ScrollRange(BrushTool tool) {
super(tool);
}
@Override
public boolean increment(int amount) {
int max = WorldEdit.getInstance().getConfiguration().maxBrushRadius;
int newSize = MathMan.wrap(tool.getRange() + amount, (int) (tool.getSize() + 1), max);
tool.setRange(newSize);
return true;
}
}

View File

@ -0,0 +1,18 @@
package com.boydti.fawe.object.brush.scroll;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.tool.BrushTool;
public class ScrollSize extends ScrollAction {
public ScrollSize(BrushTool tool) {
super(tool);
}
@Override
public boolean increment(int amount) {
int max = WorldEdit.getInstance().getConfiguration().maxRadius;
double newSize = Math.max(0, Math.min(max, tool.getSize() + amount));
tool.setSize(newSize);
return true;
}
}

View File

@ -0,0 +1,5 @@
package com.boydti.fawe.object.brush.scroll;
public interface ScrollableBrush {
public boolean increment(int amount);
}

View File

@ -0,0 +1,32 @@
package com.boydti.fawe.object.brush.visualization;
import com.boydti.fawe.object.brush.DoubleActionBrush;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.function.pattern.Pattern;
public class DelegateVisualBrush extends VisualBrush {
private final Brush brush;
public DelegateVisualBrush(BrushTool tool, Brush brush) {
super(tool);
this.brush = brush;
}
@Override
public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
switch (action) {
case PRIMARY:
brush.build(editSession, position, pattern, size);
break;
case SECONDARY:
if (brush instanceof DoubleActionBrush) {
((DoubleActionBrush) brush).build(BrushTool.BrushAction.SECONDARY, editSession, position, pattern, size);
}
break;
}
}
}

View File

@ -0,0 +1,142 @@
package com.boydti.fawe.object.brush.visualization;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.brush.DoubleActionBrush;
import com.boydti.fawe.object.brush.MovableBrush;
import com.boydti.fawe.object.brush.TargetMode;
import com.boydti.fawe.object.brush.scroll.ScrollableBrush;
import com.boydti.fawe.util.EditSessionBuilder;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.Location;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public abstract class VisualBrush implements DoubleActionBrush, MovableBrush, ScrollableBrush {
private Lock lock = new ReentrantLock();
private final BrushTool tool;
private VisualExtent visualExtent;
private TargetMode mode;
public VisualBrush(BrushTool tool) {
this.tool = tool;
this.mode = TargetMode.TARGET_POINT_RANGE;
}
public BrushTool getTool() {
return tool;
}
public TargetMode getMode() {
return mode;
}
public void setMode(TargetMode mode) {
this.mode = mode;
}
@Override
public abstract void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException;
public Vector getPosition(EditSession editSession, Player player) {
switch (mode) {
case TARGET_BLOCK_RANGE:
return player.getBlockTrace(tool.getRange(), false);
case FOWARD_POINT_PITCH: {
int d = 0;
Location loc = player.getLocation();
float pitch = loc.getPitch();
pitch = 23 - (pitch / 4);
d += (int) (Math.sin(Math.toRadians(pitch)) * 50);
final Vector vector = loc.getDirection().setY(0).normalize().multiply(d);
vector.add(loc.getX(), loc.getY(), loc.getZ()).toBlockVector();
return vector;
}
case TARGET_POINT_HEIGHT: {
Location loc = player.getLocation();
final int height = loc.getBlockY();
final int x = loc.getBlockX();
final int z = loc.getBlockZ();
int y;
for (y = height; y > 0; y--) {
BaseBlock block = editSession.getBlock(x, y, z);
if (!FaweCache.isLiquidOrGas(block.getId())) {
break;
}
}
final int distance = (height - y) + 8;
return player.getBlockTrace(distance, true);
}
case TARGET_POINT_RANGE:
return player.getBlockTrace(tool.getRange(), true);
default:
return null;
}
}
public void queueVisualization(FawePlayer player) {
Fawe.get().getVisualQueue().queue(player);
}
/**
* Visualize the brush action
* @deprecated It is preferred to visualize only if a visualization is not in progress
* @param action
* @param player
* @throws MaxChangedBlocksException
*/
@Deprecated
public synchronized void visualize(BrushTool.BrushAction action, Player player) throws MaxChangedBlocksException {
FawePlayer<Object> fp = FawePlayer.wrap(player);
EditSession editSession = new EditSessionBuilder(player.getWorld())
.player(fp)
.allowedRegionsEverywhere()
.autoQueue(false)
.blockBag(null)
.changeSetNull()
.combineStages(false)
.build();
VisualExtent newVisualExtent = new VisualExtent(editSession.getExtent(), editSession.getQueue());
editSession.setExtent(newVisualExtent);
Vector position = getPosition(editSession, player);
if (position != null) {
build(BrushTool.BrushAction.PRIMARY, editSession, position, tool.getMaterial(), tool.getSize());
}
if (visualExtent != null) {
// clear old data
visualExtent.clear(newVisualExtent, fp);
}
visualExtent = newVisualExtent;
newVisualExtent.visualize(fp);
}
public void clear(Player player) {
FawePlayer<Object> fp = FawePlayer.wrap(player);
Fawe.get().getVisualQueue().dequeue(fp);
if (visualExtent != null) {
visualExtent.clear(null, fp);
}
}
@Override
public boolean move(Player player) {
return true;
}
@Override
public boolean increment(int amount) {
int max = WorldEdit.getInstance().getConfiguration().maxBrushRadius;
double newSize = Math.max(0, Math.min(max, tool.getSize() + amount));
tool.setSize(newSize);
return true;
}
}

View File

@ -0,0 +1,171 @@
package com.boydti.fawe.object.brush.visualization;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.collection.SparseBitSet;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/**
* FAWE visualizations display glass (20) as a placeholder
* - Using a non transparent block can cause FPS lag
*/
public class VisualChunk extends FaweChunk<FaweChunk> {
public static int VISUALIZE_BLOCK = (95 << 4);
private SparseBitSet add;
private SparseBitSet remove;
/**
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
*
* @param x
* @param z
*/
public VisualChunk(int x, int z) {
super(null, x, z);
this.add = new SparseBitSet();
this.remove = new SparseBitSet();
}
protected VisualChunk(int x, int z, SparseBitSet add, SparseBitSet remove) {
super(null, x, z);
this.add = add;
this.remove = remove;
}
public int size() {
return add.cardinality() + remove.cardinality();
}
private final int getIndex(int x, int y, int z) {
return MathMan.tripleBlockCoordChar(x, y, z);
}
@Override
public int getBitMask() {
return 0;
}
@Override
public int getBlockCombinedId(int x, int y, int z) {
int index = getIndex(x, y, z);
if (add.get(index)) {
return VISUALIZE_BLOCK;
} else if (remove.get(index)) {
return 1;
} else {
return 0;
}
}
@Override
public void forEachQueuedBlock(FaweChunkVisitor onEach) {
int index = -1;
while ((index = add.nextSetBit(index + 1)) != -1) {
int x = MathMan.untripleBlockCoordX(index);
int y = MathMan.untripleBlockCoordY(index);
int z = MathMan.untripleBlockCoordZ(index);
onEach.run(x, y, z, VISUALIZE_BLOCK);
}
index = -1;
while ((index = remove.nextSetBit(index + 1)) != -1) {
int x = MathMan.untripleBlockCoordX(index);
int y = MathMan.untripleBlockCoordY(index);
int z = MathMan.untripleBlockCoordZ(index);
onEach.run(x, y, z, 1);
}
}
@Override
public byte[] getBiomeArray() {
return new byte[256];
}
@Override
public FaweChunk getChunk() {
return this;
}
@Override
public void setTile(int x, int y, int z, CompoundTag tile) {
// Unsupported
}
@Override
public void setEntity(CompoundTag entity) {
// Unsupported
}
@Override
public void removeEntity(UUID uuid) {
// Unsupported
}
@Override
public void setBlock(int x, int y, int z, int id, int data) {
int index = getIndex(x, y, z);
try {
if (id == 0) {
add.clear(index);
remove.set(index);
} else {
remove.clear(index);
add.set(index);
}
} catch (Throwable e) {
e.printStackTrace();
}
}
public void unset(int x, int y, int z) {
int index = getIndex(x, y, z);
remove.clear(index);
add.clear(index);
}
@Override
public Set<CompoundTag> getEntities() {
return new HashSet<>();
}
@Override
public Set<UUID> getEntityRemoves() {
return new HashSet<>();
}
@Override
public Map<Short, CompoundTag> getTiles() {
return new HashMap<>();
}
@Override
public CompoundTag getTile(int x, int y, int z) {
return null;
}
@Override
public void setBiome(int x, int z, byte biome) {
// Unsupported
}
@Override
public FaweChunk copy(boolean shallow) {
if (shallow) {
return new VisualChunk(getX(), getZ(), add, remove);
} else {
return new VisualChunk(getX(), getZ(), add.clone(), remove.clone());
}
}
@Override
public FaweChunk call() {
return this;
}
}

View File

@ -0,0 +1,110 @@
package com.boydti.fawe.object.brush.visualization;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NullQueueCharFaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.biome.BaseBiome;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
public class VisualExtent extends AbstractDelegateExtent {
private final FaweQueue queue;
private Long2ObjectMap<VisualChunk> chunks = new Long2ObjectOpenHashMap<>();
public VisualExtent(Extent parent, FaweQueue queue) {
super(parent);
this.queue = queue;
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block);
}
public VisualChunk getChunk(int cx, int cz) {
return chunks.get(MathMan.pairInt(cx, cz));
}
@Override
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
BaseBlock previous = super.getLazyBlock(x, y, z);
int cx = x >> 4;
int cz = z >> 4;
long chunkPair = MathMan.pairInt(cx, cz);
VisualChunk chunk = chunks.get(chunkPair);
if (previous.equals(block)) {
if (chunk != null) {
chunk.unset(x, y, z);
}
return false;
} else {
if (chunk == null) {
chunk = new VisualChunk(cx, cz);
chunks.put(chunkPair, chunk);
}
chunk.setBlock(x, y, z, block.getId(), block.getData());
return true;
}
}
@Override
public boolean setBiome(Vector2D position, BaseBiome biome) {
// Do nothing
return false;
}
public void clear(VisualExtent other, FawePlayer... players) {
ObjectIterator<Long2ObjectMap.Entry<VisualChunk>> iter = chunks.long2ObjectEntrySet().iterator();
while (iter.hasNext()) {
Long2ObjectMap.Entry<VisualChunk> entry = iter.next();
long pair = entry.getLongKey();
int cx = MathMan.unpairIntX(pair);
int cz = MathMan.unpairIntY(pair);
VisualChunk chunk = entry.getValue();
final VisualChunk otherChunk = other != null ? other.getChunk(cx, cz) : null;
final CharFaweChunk newChunk = new NullQueueCharFaweChunk(cx, cz);
final int bx = cx << 4;
final int bz = cz << 4;
if (otherChunk == null) {
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
@Override
public void run(int localX, int y, int localZ, int combined) {
combined = queue.getCombinedId4Data(bx + localX, y, bz + localZ, 0);
newChunk.setBlock(localX, y, localZ, FaweCache.getId(combined), FaweCache.getData(combined));
}
});
} else {
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
@Override
public void run(int localX, int y, int localZ, int combined) {
if (combined != otherChunk.getBlockCombinedId(localX, y, localZ)) {
combined = queue.getCombinedId4Data(bx + localX, y, bz + localZ, 0);
newChunk.setBlock(localX, y, localZ, FaweCache.getId(combined), FaweCache.getData(combined));
}
}
});
}
if (newChunk.getTotalCount() != 0) {
queue.sendBlockUpdate(newChunk, players);
}
}
}
public void visualize(FawePlayer players) {
for (VisualChunk chunk : chunks.values()) {
queue.sendBlockUpdate(chunk, players);
}
}
}

View File

@ -0,0 +1,7 @@
package com.boydti.fawe.object.brush.visualization;
public enum VisualMode {
NONE,
POINT,
OUTLINE
}

View File

@ -0,0 +1,66 @@
package com.boydti.fawe.object.brush.visualization;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.entity.Player;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class VisualQueue {
private ConcurrentHashMap<FawePlayer, Long> playerMap;
public VisualQueue() {
playerMap = new ConcurrentHashMap<>();
Runnable task = new Runnable() {
@Override
public void run() {
long allowedTick = Fawe.get().getTimer().getTick() - 1;
Iterator<Map.Entry<FawePlayer, Long>> iter = playerMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<FawePlayer, Long> entry = iter.next();
Long time = entry.getValue();
if (time < allowedTick) {
FawePlayer fp = entry.getKey();
iter.remove();
LocalSession session = fp.getSession();
Player player = fp.getPlayer();
Tool tool = session.getTool(player.getItemInHand());
Brush brush;
if (tool instanceof BrushTool) {
brush = ((BrushTool) tool).getBrush();
} else if (tool instanceof VisualBrush) {
brush = (Brush) tool;
} else {
continue;
}
if (brush instanceof VisualBrush) {
try {
((VisualBrush) brush).visualize(BrushTool.BrushAction.PRIMARY, player);
} catch (Throwable e) {
WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player);
}
}
}
}
TaskManager.IMP.laterAsync(this, 3);
}
};
TaskManager.IMP.laterAsync(task, 3);
}
public boolean dequeue(FawePlayer player) {
return playerMap.remove(player) != null;
}
public void queue(FawePlayer player) {
playerMap.put(player, Fawe.get().getTimer().getTick());
}
}

View File

@ -75,19 +75,8 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
private void init(UUID uuid, String worldName) {
File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + worldName + File.separator + uuid);
int max = 0;
if (folder.exists()) {
for (File file : folder.listFiles()) {
String name = file.getName().split("\\.")[0];
if (name.matches("\\d+")) {
int index = Integer.parseInt(name);
if (index > max) {
max = index;
}
}
}
}
init(uuid, ++max);
int max = MainUtil.getMaxFileId(folder);
init(uuid, max);
}
public DiskStorageHistory(String world, UUID uuid, int index) {

View File

@ -69,6 +69,11 @@ public abstract class FaweChangeSet implements ChangeSet {
return world;
}
@Deprecated
public boolean flushAsync() {
return closeAsync();
}
public boolean closeAsync() {
waitingAsync.incrementAndGet();
TaskManager.IMP.async(new Runnable() {

View File

@ -53,6 +53,7 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
final Vector pos = new Vector();
if (region instanceof CuboidRegion) {
if (air) {
((CuboidRegion) region).setUseOldIterator(true);
RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
@Override
public boolean apply(Vector pos) throws WorldEditException {
@ -76,27 +77,33 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
}, editSession);
Operations.completeBlindly(visitor);
} else {
RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
CuboidRegion cuboidEquivalent = new CuboidRegion(region.getMinimumPoint(), region.getMaximumPoint());
cuboidEquivalent.setUseOldIterator(true);
RegionVisitor visitor = new RegionVisitor(cuboidEquivalent, new RegionFunction() {
@Override
public boolean apply(Vector pos) throws WorldEditException {
int x = pos.getBlockX();
int y = pos.getBlockY();
int z = pos.getBlockZ();
BaseBlock block = getBlockAbs(x, y, z);
if (block == EditSession.nullBlock) {
return false;
if (region.contains(pos)) {
int x = pos.getBlockX();
int y = pos.getBlockY();
int z = pos.getBlockZ();
BaseBlock block = getBlockAbs(x, y, z);
pos.mutX(x - mx);
pos.mutY(y - my);
pos.mutZ(z - mz);
CompoundTag tag = block.getNbtData();
if (tag != null) {
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
values.put("x", new IntTag(pos.getBlockX()));
values.put("y", new IntTag(pos.getBlockY()));
values.put("z", new IntTag(pos.getBlockZ()));
}
task.run(pos, block);
} else {
pos.mutX(pos.getBlockX() - mx);
pos.mutY(pos.getBlockY() - my);
pos.mutZ(pos.getBlockZ() - mz);
task.run(pos, EditSession.nullBlock);
}
pos.mutX(x - mx);
pos.mutY(y - my);
pos.mutZ(z - mz);
CompoundTag tag = block.getNbtData();
if (tag != null) {
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
values.put("x", new IntTag(pos.getBlockX()));
values.put("y", new IntTag(pos.getBlockY()));
values.put("z", new IntTag(pos.getBlockZ()));
}
task.run(pos, block);
return true;
}
}, editSession);

View File

@ -0,0 +1,43 @@
package com.boydti.fawe.object.io;
import java.util.concurrent.Callable;
public class PGZIPBlock implements Callable<byte[]> {
public PGZIPBlock(final PGZIPOutputStream parent) {
STATE = new PGZIPThreadLocal(parent);
}
/** This ThreadLocal avoids the recycling of a lot of memory, causing lumpy performance. */
protected final ThreadLocal<PGZIPState> STATE;
public static final int SIZE = 64 * 1024;
// private final int index;
protected final byte[] in = new byte[SIZE];
protected int in_length = 0;
/*
public Block(@Nonnegative int index) {
this.index = index;
}
*/
// Only on worker thread
@Override
public byte[] call() throws Exception {
// LOG.info("Processing " + this + " on " + Thread.currentThread());
PGZIPState state = STATE.get();
// ByteArrayOutputStream buf = new ByteArrayOutputStream(in.length); // Overestimate output size required.
// DeflaterOutputStream def = newDeflaterOutputStream(buf);
state.def.reset();
state.buf.reset();
state.str.write(in, 0, in_length);
state.str.flush();
// return Arrays.copyOf(in, in_length);
return state.buf.toByteArray();
}
@Override
public String toString() {
return "Block" /* + index */ + "(" + in_length + "/" + in.length + " bytes)";
}
}

View File

@ -37,7 +37,7 @@ public class PGZIPOutputStream extends FilterOutputStream {
private int strategy = Deflater.HUFFMAN_ONLY;
@Nonnull
private Deflater newDeflater() {
protected Deflater newDeflater() {
Deflater def = new Deflater(level, true);
def.setStrategy(strategy);
return def;
@ -52,63 +52,16 @@ public class PGZIPOutputStream extends FilterOutputStream {
}
@Nonnull
private static DeflaterOutputStream newDeflaterOutputStream(@Nonnull OutputStream out, @Nonnull Deflater deflater) {
protected static DeflaterOutputStream newDeflaterOutputStream(@Nonnull OutputStream out, @Nonnull Deflater deflater) {
return new DeflaterOutputStream(out, deflater, 512, true);
}
private class Block implements Callable<byte[]> {
private class State {
private final Deflater def = newDeflater();
private final ByteArrayOutputStream buf = new ByteArrayOutputStream(SIZE);
private final DeflaterOutputStream str = newDeflaterOutputStream(buf, def);
}
/** This ThreadLocal avoids the recycling of a lot of memory, causing lumpy performance. */
private final ThreadLocal<State> STATE = new ThreadLocal<State>() {
@Override
protected State initialValue() {
return new State();
}
};
public static final int SIZE = 64 * 1024;
// private final int index;
private final byte[] in = new byte[SIZE];
private int in_length = 0;
/*
public Block(@Nonnegative int index) {
this.index = index;
}
*/
// Only on worker thread
@Override
public byte[] call() throws Exception {
// LOG.info("Processing " + this + " on " + Thread.currentThread());
State state = STATE.get();
// ByteArrayOutputStream buf = new ByteArrayOutputStream(in.length); // Overestimate output size required.
// DeflaterOutputStream def = newDeflaterOutputStream(buf);
state.def.reset();
state.buf.reset();
state.str.write(in, 0, in_length);
state.str.flush();
// return Arrays.copyOf(in, in_length);
return state.buf.toByteArray();
}
@Override
public String toString() {
return "Block" /* + index */ + "(" + in_length + "/" + in.length + " bytes)";
}
}
// TODO: Share, daemonize.
private final ExecutorService executor;
private final int nthreads;
private final CRC32 crc = new CRC32();
private final BlockingQueue<Future<byte[]>> emitQueue;
private Block block = new Block(/* 0 */);
private PGZIPBlock block = new PGZIPBlock(this/* 0 */);
/** Used as a sentinel for 'closed'. */
private int bytesWritten = 0;
@ -201,7 +154,7 @@ public class PGZIPOutputStream extends FilterOutputStream {
private void submit() throws IOException {
emitUntil(nthreads - 1);
emitQueue.add(executor.submit(block));
block = new Block(/* block.index + 1 */);
block = new PGZIPBlock(this/* block.index + 1 */);
}
// Emit If Available - submit always

View File

@ -0,0 +1,19 @@
package com.boydti.fawe.object.io;
import java.io.ByteArrayOutputStream;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
public class PGZIPState {
protected final DeflaterOutputStream str;
protected final ByteArrayOutputStream buf;
protected final Deflater def;
public PGZIPState(PGZIPOutputStream parent) {
this.def = parent.newDeflater();
this.buf = new ByteArrayOutputStream(PGZIPBlock.SIZE);
this.str = parent.newDeflaterOutputStream(buf, def);
}
}

View File

@ -0,0 +1,15 @@
package com.boydti.fawe.object.io;
public class PGZIPThreadLocal extends ThreadLocal<PGZIPState> {
private final PGZIPOutputStream parent;
public PGZIPThreadLocal(PGZIPOutputStream parent) {
this.parent = parent;
}
@Override
protected PGZIPState initialValue() {
return new PGZIPState(parent);
}
}

View File

@ -0,0 +1,12 @@
package com.boydti.fawe.object.visitor;
public abstract class FaweChunkVisitor {
/**
* The will run for each set block in the chunk
* @param localX The x position in the chunk (0-15)
* @param y The y position (0 - 255)
* @param localZ The z position in the chunk (0-15)
* @param combined The combined id
*/
public abstract void run(int localX, int y, int localZ, int combined);
}

View File

@ -16,7 +16,6 @@ import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.File;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedDeque;
@ -222,8 +221,8 @@ public class DelegateFaweQueue extends FaweQueue {
}
@Override
public void sendBlockUpdate(Map<Long, Map<Short, Character>> blockMap, FawePlayer... players) {
parent.sendBlockUpdate(blockMap, players);
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
parent.sendBlockUpdate(chunk, players);
}
@Deprecated

View File

@ -56,6 +56,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
@ -180,6 +181,29 @@ public class MainUtil {
}
}
public static int getMaxFileId(File folder) {
final AtomicInteger max = new AtomicInteger();
if (folder.exists()) {
MainUtil.traverse(folder.toPath(), new RunnableVal2<Path, BasicFileAttributes>() {
@Override
public void run(Path path, BasicFileAttributes attr) {
try {
String file = path.getFileName().toString();
int index = file.indexOf('.');
if (index == -1) {
return;
}
int id = Integer.parseInt(file.substring(0, index));
if (id > max.get()) {
max.set(id);
}
} catch (NumberFormatException ignore){}
}
});
}
return max.get() + 1;
}
public static File getFile(File base, String path) {
if (Paths.get(path).isAbsolute()) {
return new File(path);

View File

@ -43,6 +43,20 @@ public class MathMan {
253, 254, 254, 255
};
public static final int wrap(int value, int min, int max) {
if (max <= min) {
return value;
}
int diff = max - min + 1;
if (value < min) {
return max - ((min - value) % diff);
} else if (value > max) {
return min + ((value - min) % diff);
} else {
return value;
}
}
public static final long inverseRound(double val) {
long round = Math.round(val);
return (long) (round + Math.signum(val - round));
@ -84,6 +98,22 @@ public class MathMan {
return (short) ((x & 15) << 12 | (z & 15) << 8 | y);
}
public static final char tripleBlockCoordChar(int x, int y, int z) {
return (char) ((x & 15) << 12 | (z & 15) << 8 | y);
}
public static final int untripleBlockCoordX(int triple) {
return (triple >> 12) & 0xF;
}
public static final int untripleBlockCoordY(int triple) {
return (triple & 0xFF);
}
public static final int untripleBlockCoordZ(int triple) {
return (triple >> 8) & 0xF;
}
public static int tripleSearchCoords(int x, int y, int z) {
byte b1 = (byte) y;
byte b3 = (byte) (x);

View File

@ -4,15 +4,21 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweVersion;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.Scanner;
public class Updater {
private static FaweVersion newVersion = null;
private FaweVersion newVersion;
private String changes = "N/A";
public static void update(String platform, FaweVersion currentVersion) {
public String getChanges() throws IOException {
return changes;
}
public void update(String platform, FaweVersion currentVersion) {
if (currentVersion == null || platform == null) {
return;
}
@ -42,7 +48,11 @@ public class Updater {
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
}
Fawe.debug("Updated FAWE to " + versionString);
MainUtil.sendAdmin("Restart to update FAWE with these changes: " + "http://boydti.com/fawe/cl?" + Integer.toHexString(Fawe.get().getVersion().hash));
Scanner scanner = new Scanner(new URL("http://boydti.com/fawe/cl?" + Integer.toHexString(Fawe.get().getVersion().hash)).openStream(), "UTF-8");
changes = scanner.useDelimiter("\\A").next();
scanner.close();
MainUtil.sendAdmin("&7Restart to update FAWE with these changes: &c/fawe changelog &7or&c " + "http://boydti.com/fawe/cl?" + Integer.toHexString(currentVersion.hash));
}
}
}

View File

@ -122,7 +122,7 @@ public class FakePlayer extends LocalPlayer {
}
@Override
public Player getPlayer() {
public Player toWorldEditPlayer() {
return FakePlayer.this;
}
};

View File

@ -84,6 +84,10 @@ public class BlockVector extends Vector {
}
public boolean equals(BlockVector obj) {
return obj.getBlockX() == this.getBlockX() && obj.getBlockY() == this.getBlockY() && obj.getBlockZ() == this.getBlockZ();
}
@Override
public int hashCode() {
return ((int) getX() ^ ((int) getZ() << 16)) ^ ((int) getY() << 30);

View File

@ -454,14 +454,14 @@ public class CuboidClipboard {
}
if (reverse) {
for (int i = 0; i < numRotations; ++i) {
if (block.hasWildcardData()) {
if (block.isImmutable()) {
block = new BaseBlock(block);
}
block.rotate90Reverse();
}
} else {
for (int i = 0; i < numRotations; ++i) {
if (block.hasWildcardData()) {
if (block.isImmutable()) {
block = new BaseBlock(block);
}
block.rotate90();

View File

@ -415,6 +415,22 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
return traverser == null ? null : traverser.get();
}
public Extent getBypassAll() {
return bypassAll;
}
public Extent getBypassHistory() {
return bypassHistory;
}
public Extent getExtent() {
return extent;
}
public void setExtent(AbstractDelegateExtent extent) {
this.extent = extent;
}
/**
* Get the FawePlayer or null
* @return
@ -2151,20 +2167,26 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final double invRadiusX = 1 / radiusX;
final double invRadiusZ = 1 / radiusZ;
int px = pos.getBlockX();
int py = pos.getBlockY();
int pz = pos.getBlockZ();
MutableBlockVector mutable = new MutableBlockVector();
final int ceilRadiusX = (int) Math.ceil(radiusX);
final int ceilRadiusZ = (int) Math.ceil(radiusZ);
double dx, dxz, dz;
double nextXn = 0;
forX: for (int x = 0; x <= ceilRadiusX; ++x) {
final double xn = nextXn;
nextXn = (x + 1) * invRadiusX;
double nextZn = 0;
dx = xn * xn;
forZ: for (int z = 0; z <= ceilRadiusZ; ++z) {
final double zn = nextZn;
nextZn = (z + 1) * invRadiusZ;
final double distanceSq = this.lengthSq(xn, zn);
if (distanceSq > 1) {
dz = zn * zn;
dxz = dx + dz;
if (dxz > 1) {
if (z == 0) {
break forX;
}
@ -2172,16 +2194,16 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
if (!filled) {
if ((this.lengthSq(nextXn, zn) <= 1) && (this.lengthSq(xn, nextZn) <= 1)) {
if ((dz + nextXn * nextXn <= 1) && (nextZn * nextZn + dx <= 1)) {
continue;
}
}
for (int y = 0; y < height; ++y) {
this.setBlock(pos.add(x, y, z), block);
this.setBlock(pos.add(-x, y, z), block);
this.setBlock(pos.add(x, y, -z), block);
this.setBlock(pos.add(-x, y, -z), block);
this.setBlock(mutable.setComponents(px + x, py + y, pz + z), block);
this.setBlock(mutable.setComponents(px - x, py + y, pz + z), block);
this.setBlock(mutable.setComponents(px + x, py + y, pz - z), block);
this.setBlock(mutable.setComponents(px - x, py + y, pz - z), block);
}
}
}
@ -2189,6 +2211,82 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
return this.changes;
}
public int makeCircle(Vector pos, final Pattern block, double radiusX, double radiusY, double radiusZ, boolean filled, Vector normal) throws MaxChangedBlocksException {
radiusX += 0.5;
radiusY += 0.5;
radiusZ += 0.5;
normal = normal.normalize();
double nx = normal.getX();
double ny = normal.getY();
double nz = normal.getZ();
final double invRadiusX = 1 / radiusX;
final double invRadiusY = 1 / radiusY;
final double invRadiusZ = 1 / radiusZ;
int px = pos.getBlockX();
int py = pos.getBlockY();
int pz = pos.getBlockZ();
MutableBlockVector mutable = new MutableBlockVector();
final int ceilRadiusX = (int) Math.ceil(radiusX);
final int ceilRadiusY = (int) Math.ceil(radiusY);
final int ceilRadiusZ = (int) Math.ceil(radiusZ);
double threshold = 0.5;
LocalBlockVectorSet set = new LocalBlockVectorSet();
double nextXn = 0;
double dx, dy, dz, dxy, dxyz;
forX: for (int x = 0; x <= ceilRadiusX; ++x) {
final double xn = nextXn;
dx = xn * xn;
nextXn = (x + 1) * invRadiusX;
double nextYn = 0;
forY: for (int y = 0; y <= ceilRadiusY; ++y) {
final double yn = nextYn;
dy = yn * yn;
dxy = dx + dy;
nextYn = (y + 1) * invRadiusY;
double nextZn = 0;
forZ: for (int z = 0; z <= ceilRadiusZ; ++z) {
final double zn = nextZn;
dz = zn * zn;
dxyz = dxy + dz;
nextZn = (z + 1) * invRadiusZ;
if (dxyz > 1) {
if (z == 0) {
if (y == 0) {
break forX;
}
break forY;
}
break forZ;
}
if (!filled) {
if (nextXn * nextXn + dy + dz <= 1 && nextYn * nextYn + dx + dz <= 1 && nextZn * nextZn + dx + dy <= 1) {
continue;
}
}
if (Math.abs((x) * nx + (y) * ny + (z) * nz) < threshold) setBlock(mutable.setComponents(px + x, py + y, pz + z), block);
if (Math.abs((-x) * nx + (y) * ny + (z) * nz) < threshold) setBlock(mutable.setComponents(px - x, py + y, pz + z), block);
if (Math.abs((x) * nx + (-y) * ny + (z) * nz) < threshold) setBlock(mutable.setComponents(px + x, py - y, pz + z), block);
if (Math.abs((x) * nx + (y) * ny + (-z) * nz) < threshold) setBlock(mutable.setComponents(px + x, py + y, pz - z), block);
if (Math.abs((-x) * nx + (-y) * ny + (z) * nz) < threshold) setBlock(mutable.setComponents(px - x, py - y, pz + z), block);
if (Math.abs((x) * nx + (-y) * ny + (-z) * nz) < threshold) setBlock(mutable.setComponents(px + x, py - y, pz - z), block);
if (Math.abs((-x) * nx + (y) * ny + (-z) * nz) < threshold) setBlock(mutable.setComponents(px - x, py + y, pz - z), block);
if (Math.abs((-x) * nx + (-y) * ny + (-z) * nz) < threshold) setBlock(mutable.setComponents(px - x, py - y, pz - z), block);
}
}
}
return changes;
}
/**
* Makes a sphere.
*
@ -2224,25 +2322,34 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final double invRadiusY = 1 / radiusY;
final double invRadiusZ = 1 / radiusZ;
int px = pos.getBlockX();
int py = pos.getBlockY();
int pz = pos.getBlockZ();
MutableBlockVector mutable = new MutableBlockVector();
final int ceilRadiusX = (int) Math.ceil(radiusX);
final int ceilRadiusY = (int) Math.ceil(radiusY);
final int ceilRadiusZ = (int) Math.ceil(radiusZ);
double nextXn = 0;
double dx, dy, dz, dxy, dxyz;
forX: for (int x = 0; x <= ceilRadiusX; ++x) {
final double xn = nextXn;
dx = xn * xn;
nextXn = (x + 1) * invRadiusX;
double nextYn = 0;
forY: for (int y = 0; y <= ceilRadiusY; ++y) {
final double yn = nextYn;
dy = yn * yn;
dxy = dx + dy;
nextYn = (y + 1) * invRadiusY;
double nextZn = 0;
forZ: for (int z = 0; z <= ceilRadiusZ; ++z) {
final double zn = nextZn;
dz = zn * zn;
dxyz = dxy + dz;
nextZn = (z + 1) * invRadiusZ;
final double distanceSq = this.lengthSq(xn, yn, zn);
if (distanceSq > 1) {
if (dxyz > 1) {
if (z == 0) {
if (y == 0) {
break forX;
@ -2253,19 +2360,19 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
if (!filled) {
if ((this.lengthSq(nextXn, yn, zn) <= 1) && (this.lengthSq(xn, nextYn, zn) <= 1) && (this.lengthSq(xn, yn, nextZn) <= 1)) {
if (nextXn * nextXn + dy + dz <= 1 && nextYn * nextYn + dx + dz <= 1 && nextZn * nextZn + dx + dy <= 1 ) {
continue;
}
}
this.setBlock(pos.add(x, y, z), block);
this.setBlock(pos.add(-x, y, z), block);
this.setBlock(pos.add(x, -y, z), block);
this.setBlock(pos.add(x, y, -z), block);
this.setBlock(pos.add(-x, -y, z), block);
this.setBlock(pos.add(x, -y, -z), block);
this.setBlock(pos.add(-x, y, -z), block);
this.setBlock(pos.add(-x, -y, -z), block);
this.setBlock(mutable.setComponents(px + x, py + y, pz + z), block);
this.setBlock(mutable.setComponents(px - x, py + y, pz + z), block);
this.setBlock(mutable.setComponents(px + x, py - y, pz + z), block);
this.setBlock(mutable.setComponents(px + x, py + y, pz - z), block);
this.setBlock(mutable.setComponents(px - x, py - y, pz + z), block);
this.setBlock(mutable.setComponents(px + x, py - y, pz - z), block);
this.setBlock(mutable.setComponents(px - x, py + y, pz - z), block);
this.setBlock(mutable.setComponents(px - x, py - y, pz - z), block);
}
}
}
@ -2960,9 +3067,11 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
private Set<Vector> getBallooned(final Set<Vector> vset, final double radius) {
if (radius < 1) {
return vset;
}
final Set returnset = new LocalBlockVectorSet();
final int ceilrad = (int) Math.ceil(radius);
for (final Vector v : vset) {
final int tipx = v.getBlockX(), tipy = v.getBlockY(), tipz = v.getBlockZ();
for (int loopx = tipx - ceilrad; loopx <= (tipx + ceilrad); loopx++) {
@ -2979,6 +3088,9 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
private Set<Vector> getStretched(final Set<Vector> vset, final double radius) {
if (radius < 1) {
return vset;
}
final Set returnset = new LocalBlockVectorSet();
final int ceilrad = (int) Math.ceil(radius);
for (final Vector v : vset) {

View File

@ -25,7 +25,7 @@ import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.brush.DoubleActionBrushTool;
import com.boydti.fawe.object.brush.visualization.VisualBrush;
import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
@ -42,6 +42,7 @@ import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.InvalidToolBindException;
import com.sk89q.worldedit.command.tool.SinglePickaxe;
import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
@ -440,6 +441,9 @@ public class LocalSession {
}
public synchronized void remember(final EditSession editSession, final boolean append, final boolean sendMessage, int limitMb) {
if (Settings.IMP.HISTORY.USE_DISK) {
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
}
// It should have already been flushed, but just in case!
editSession.flushQueue();
if (editSession == null || editSession.getChangeSet() == null || limitMb == 0 || ((historySize >> 20) > limitMb && !append)) {
@ -953,6 +957,14 @@ public class LocalSession {
return tools.get(item);
}
@Nullable
public Tool getTool(Player player) {
if (tools.isEmpty()) {
return null;
}
return getTool(player.getItemInHand());
}
/**
* Get the brush tool assigned to the item. If there is no tool assigned
* or the tool is not assigned, the slot will be replaced with the
@ -963,36 +975,20 @@ public class LocalSession {
* @throws InvalidToolBindException if the item can't be bound to that item
*/
public BrushTool getBrushTool(int item) throws InvalidToolBindException {
return getBrushTool(item, null);
}
public BrushTool getBrushTool(int item, Player player) throws InvalidToolBindException {
Tool tool = getTool(item);
if (tool == null || !(tool instanceof BrushTool)) {
tool = new BrushTool("worldedit.brush.sphere");
setTool(item, tool);
setTool(item, tool, player);
}
return (BrushTool) tool;
}
/**
* Get the brush tool assigned to the item. If there is no tool assigned
* or the tool is not assigned, the slot will be replaced with the
* brush tool.
*
* @param item the item type ID
* @return the tool, or {@code null}
* @throws InvalidToolBindException if the item can't be bound to that item
*/
public DoubleActionBrushTool getDoubleActionBrushTool(int item) throws InvalidToolBindException {
Tool tool = getTool(item);
if (tool == null || !(tool instanceof DoubleActionBrushTool)) {
tool = new DoubleActionBrushTool("worldedit.brush.sphere");
setTool(item, tool);
}
return (DoubleActionBrushTool) tool;
}
/**
* Set the tool.
*
@ -1001,6 +997,10 @@ public class LocalSession {
* @throws InvalidToolBindException if the item can't be bound to that item
*/
public void setTool(int item, @Nullable Tool tool) throws InvalidToolBindException {
setTool(item, tool, null);
}
public void setTool(int item, @Nullable Tool tool, Player player) throws InvalidToolBindException {
if (item > 0 && item < 255) {
throw new InvalidToolBindException(item, "Blocks can't be used");
} else if (item == config.wandItem) {
@ -1008,8 +1008,17 @@ public class LocalSession {
} else if (item == config.navigationWand) {
throw new InvalidToolBindException(item, "Already used for the navigation wand");
}
this.tools.put(item, tool);
Tool previous = this.tools.put(item, tool);
if (player != null) {
if (previous instanceof BrushTool) {
Brush brush = ((BrushTool) previous).getBrush();
if (brush instanceof VisualBrush) {
((VisualBrush) brush).clear(player);
}
} else if (previous instanceof VisualBrush) {
((VisualBrush) tool).clear(player);
}
}
}
/**

View File

@ -1,6 +1,17 @@
package com.sk89q.worldedit;
public class MutableBlockVector extends BlockVector {
private static ThreadLocal<MutableBlockVector> MUTABLE_CACHE = new ThreadLocal<MutableBlockVector>() {
@Override
protected MutableBlockVector initialValue() {
return new MutableBlockVector();
}
};
public static Vector get(int x, int y, int z) {
return MUTABLE_CACHE.get().setComponents(x, y, z);
}
private int x,y,z;
public MutableBlockVector(Vector v) {

View File

@ -0,0 +1,421 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.blocks;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
import com.sk89q.worldedit.foundation.Block;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.world.registry.WorldData;
import javax.annotation.Nullable;
import java.util.Collection;
/**
* Represents a mutable "snapshot" of a block.
*
* <p>An instance of this block contains all the information needed to
* accurately reproduce the block, provided that the instance was
* made correctly. In some implementations, it may not be possible to get a
* snapshot of blocks correctly, so, for example, the NBT data for a block
* may be missing.</p>
*
* <p>This class identifies blocks using an integer ID. However, IDs for
* a given block may differ between worlds so it is important that users of
* this class convert the ID from one "world space" to another "world space,"
* a task that that is assisted with by working with the source and
* destination {@link WorldData} instances. Numeric IDs are utilized because
* they are more space efficient to store, and it also implies that internal
* uses of this class (i.e. history, etc.) do not need to worry about
* interning block string IDs.</p>
*
* <p>A peculiar detail of this class is that it accepts {@code -1} as a
* valid data value. This is due to legacy reasons: WorldEdit uses -1
* as a "wildcard" block value, even though a {@link Mask} would be
* more appropriate.</p>
*/
@SuppressWarnings("deprecation")
public class BaseBlock extends Block implements TileEntityBlock {
/**
* Indicates the highest possible block ID (inclusive) that can be used.
* This value is subject to change depending on the implementation, but
* internally this class only supports a range of 4096 IDs (for space
* reasons), which coincides with the number of possible IDs that official
* Minecraft supports as of version 1.7.
*/
public static final int MAX_ID = 4095;
/**
* Indicates the maximum data value (inclusive) that can be used. A future
* version of Minecraft may abolish block data values.
*/
public static final int MAX_DATA = 15;
// Instances of this class should be _as small as possible_ because there will
// be millions of instances of this object.
private short id;
private short data;
@Nullable
private CompoundTag nbtData;
/**
* Construct a block with the given ID and a data value of 0.
*
* @param id ID value
* @see #setId(int)
*/
public BaseBlock(int id) {
internalSetId(id);
internalSetData(0);
}
/**
* Construct a block with the given ID and data value.
*
* @param id ID value
* @param data data value
* @see #setId(int)
* @see #setData(int)
*/
public BaseBlock(int id, int data) {
internalSetId(id);
internalSetData(data);
}
/**
* Construct a block with the given ID, data value and NBT data structure.
*
* @param id ID value
* @param data data value
* @param nbtData NBT data, which may be null
*/
public BaseBlock(int id, int data, @Nullable CompoundTag nbtData) {
setId(id);
setData(data);
setNbtData(nbtData);
}
/**
* Create a clone of another block.
*
* @param other the other block
*/
public BaseBlock(BaseBlock other) {
this(other.getId(), other.getData(), other.getNbtData());
}
/**
* Get the ID of the block.
*
* @return ID (between 0 and {@link #MAX_ID})
*/
@Override
public int getId() {
return id;
}
/**
* Set the block ID.
*
* @param id block id (between 0 and {@link #MAX_ID}).
*/
protected final void internalSetId(int id) {
if (id > MAX_ID) {
throw new IllegalArgumentException("Can't have a block ID above "
+ MAX_ID + " (" + id + " given)");
}
if (id < 0) {
throw new IllegalArgumentException("Can't have a block ID below 0");
}
this.id = (short) id;
}
/**
* Set the block ID.
*
* @param id block id (between 0 and {@link #MAX_ID}).
*/
@Override
public void setId(int id) {
internalSetId(id);
}
/**
* Get the block's data value.
*
* @return data value (0-15)
*/
@Override
public int getData() {
return data;
}
/**
* Set the block's data value.
*
* @param data block data value (between 0 and {@link #MAX_DATA}).
*/
protected final void internalSetData(int data) {
if (data > MAX_DATA) {
throw new IllegalArgumentException(
"Can't have a block data value above " + MAX_DATA + " ("
+ data + " given)");
}
if (data < -1) {
throw new IllegalArgumentException("Can't have a block data value below -1");
}
this.data = (short) data;
}
/**
* Set the block's data value.
*
* @param data block data value (between 0 and {@link #MAX_DATA}).
*/
@Override
public void setData(int data) {
internalSetData(data);
}
/**
* Set both the block's ID and data value.
*
* @param id ID value
* @param data data value
* @see #setId(int)
* @see #setData(int)
*/
@Override
public void setIdAndData(int id, int data) {
setId(id);
setData(data);
}
/**
* Returns whether the data value is -1, indicating that this block is to be
* used as a wildcard matching block.
*
* @return true if the data value is -1
*/
@Override
public boolean hasWildcardData() {
return getData() == -1;
}
@Override
public boolean hasNbtData() {
return getNbtData() != null;
}
@Override
public String getNbtId() {
CompoundTag nbtData = getNbtData();
if (nbtData == null) {
return "";
}
Tag idTag = nbtData.getValue().get("id");
if (idTag != null && idTag instanceof StringTag) {
return ((StringTag) idTag).getValue();
} else {
return "";
}
}
@Nullable
@Override
public CompoundTag getNbtData() {
return nbtData;
}
@Override
public void setNbtData(@Nullable CompoundTag nbtData) {
this.nbtData = nbtData;
}
/**
* Get the type of block.
*
* @return the type
*/
public int getType() {
return getId();
}
/**
* Set the type of block.
*
* @param type the type to set
*/
public void setType(int type) {
setId(type);
}
/**
* Returns true if it's air.
*
* @return if air
*/
public boolean isAir() {
return getType() == BlockID.AIR;
}
/**
* Rotate this block 90 degrees.
*
* @return new data value
* @deprecated Use {@link BlockData#rotate90(int, int)}
*/
@Deprecated
public int rotate90() {
int newData = BlockData.rotate90(getType(), getData());
setData(newData);
return newData;
}
/**
* Rotate this block -90 degrees.
*
* @return new data value
* @deprecated Use {@link BlockData#rotate90Reverse(int, int)}
*/
@Deprecated
public int rotate90Reverse() {
int newData = BlockData.rotate90Reverse(getType(), getData());
setData((short) newData);
return newData;
}
/**
* Cycle the damage value of the block forward or backward
*
* @param increment 1 for forward, -1 for backward
* @return new data value
* @deprecated Use {@link BlockData#cycle(int, int, int)}
*/
@Deprecated
public int cycleData(int increment) {
int newData = BlockData.cycle(getType(), getData(), increment);
setData((short) newData);
return newData;
}
/**
* Flip this block.
*
* @return this block
* @deprecated Use {@link BlockData#flip(int, int)}
*/
@Deprecated
public BaseBlock flip() {
setData((short) BlockData.flip(getType(), getData()));
return this;
}
/**
* Flip this block.
*
* @param direction direction to flip in
* @return this block
* @deprecated Use {@link BlockData#flip(int, int, FlipDirection)}
*/
@Deprecated
public BaseBlock flip(FlipDirection direction) {
setData((short) BlockData.flip(getType(), getData(), direction));
return this;
}
/**
* Checks whether the type ID and data value are equal.
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof BaseBlock)) {
return false;
}
final BaseBlock otherBlock = (BaseBlock) o;
return getType() == otherBlock.getType() && getData() == otherBlock.getData();
}
public boolean equals(BaseBlock block) {
return block.getId() == this.getId() && block.getData() == this.getData();
}
/**
* Checks if the type is the same, and if data is the same if only data != -1.
*
* @param o other block
* @return true if equal
*/
public boolean equalsFuzzy(BaseBlock o) {
return (getType() == o.getType()) && (getData() == o.getData() || getData() == -1 || o.getData() == -1);
}
/**
* @deprecated This method is silly, use {@link #containsFuzzy(java.util.Collection, BaseBlock)} instead.
*/
@Deprecated
public boolean inIterable(Iterable<BaseBlock> iter) {
for (BaseBlock block : iter) {
if (block.equalsFuzzy(this)) {
return true;
}
}
return false;
}
/**
* @deprecated Use {@link Blocks#containsFuzzy(Collection, BaseBlock)}
*/
@Deprecated
public static boolean containsFuzzy(Collection<BaseBlock> collection, BaseBlock o) {
return Blocks.containsFuzzy(collection, o);
}
@Override
public int hashCode() {
int ret = getId() << 3;
if (getData() != (byte) -1) ret |= getData();
return ret;
}
@Override
public String toString() {
return "Block{ID:" + getId() + ", Data: " + getData() + "}";
}
public boolean isImmutable() {
return false;
}
public static Class<BaseBlock> inject() {
return BaseBlock.class;
}
}

View File

@ -0,0 +1,36 @@
package com.sk89q.worldedit.blocks;
import com.sk89q.worldedit.CuboidClipboard;
public class ImmutableBlock extends BaseBlock {
public ImmutableBlock(int id, int data) {
super(id, data);
}
@Override
public void setData(int data) {
throw new IllegalStateException("Cannot set data");
}
@Override
public void setId(int id) {
throw new IllegalStateException("Cannot set id");
}
@Override
public BaseBlock flip() {
BaseBlock clone = new BaseBlock(getId(), getData(), getNbtData());
return clone.flip();
}
@Override
public BaseBlock flip(CuboidClipboard.FlipDirection direction) {
BaseBlock clone = new BaseBlock(getId(), getData(), getNbtData());
return clone.flip(direction);
}
@Override
public boolean isImmutable() {
return true;
}
}

View File

@ -0,0 +1,26 @@
package com.sk89q.worldedit.blocks;
public class ImmutableDatalessBlock extends ImmutableBlock {
public ImmutableDatalessBlock(int id) {
super(id, 0);
}
@Override
public int getData() {
return 0;
}
@Override
public boolean equals(BaseBlock block) {
return block.getId() == this.getId();
}
@Override
public boolean equals(Object o) {
if (o instanceof BaseBlock) {
return ((BaseBlock) o).getId() == this.getId();
} else {
return false;
}
}
}

View File

@ -25,9 +25,9 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.brush.BlendBall;
import com.boydti.fawe.object.brush.CircleBrush;
import com.boydti.fawe.object.brush.CommandBrush;
import com.boydti.fawe.object.brush.CopyPastaBrush;
import com.boydti.fawe.object.brush.DoubleActionBrushTool;
import com.boydti.fawe.object.brush.ErodeBrush;
import com.boydti.fawe.object.brush.FlattenBrush;
import com.boydti.fawe.object.brush.HeightBrush;
@ -106,9 +106,9 @@ public class BrushCommands {
@CommandPermissions("worldedit.brush.blendball")
public void blendBallBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setSize(radius);
tool.setBrush(new BlendBall(), "worldedit.brush.blendball");
tool.setBrush(new BlendBall(), "worldedit.brush.blendball", player);
player.print(BBC.getPrefix() + BBC.BRUSH_BLEND_BALL.f(radius));
}
@ -123,12 +123,30 @@ public class BrushCommands {
@CommandPermissions("worldedit.brush.erode")
public void erodeBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setSize(radius);
tool.setBrush(new ErodeBrush(), "worldedit.brush.erode");
tool.setBrush(new ErodeBrush(), "worldedit.brush.erode", player);
player.print(BBC.getPrefix() + BBC.BRUSH_ERODE.f(radius));
}
@Command(
aliases = { "circle" },
usage = "<pattern> [radius]",
desc = "Choose the circle brush",
help = "Chooses the circle brush.",
min = 1,
max = 2
)
@CommandPermissions("worldedit.brush.sphere")
public void circleBrush(Player player, LocalSession session, Pattern fill, @Optional("5") double radius, @Switch('h') boolean hollow) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setSize(radius);
tool.setFill(fill);
tool.setBrush(new CircleBrush(tool, player), "worldedit.brush.circle", player);
player.print(BBC.getPrefix() + BBC.BRUSH_CIRCLE.f(radius));
}
@Command(
aliases = { "recursive", "recurse", "r" },
usage = "<pattern-to> [radius]",
@ -141,9 +159,9 @@ public class BrushCommands {
@CommandPermissions("worldedit.brush.recursive")
public void recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("2") double radius, @Switch('d') boolean depthFirst) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setSize(radius);
tool.setBrush(new RecurseBrush(tool, depthFirst), "worldedit.brush.recursive");
tool.setBrush(new RecurseBrush(tool, depthFirst), "worldedit.brush.recursive", player);
tool.setMask(new IdMask(editSession));
tool.setFill(fill);
player.print(BBC.getPrefix() + BBC.BRUSH_RECURSIVE.f(radius));
@ -165,10 +183,10 @@ public class BrushCommands {
@CommandPermissions("worldedit.brush.line")
public void lineBrush(Player player, LocalSession session, Pattern fill, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('f') boolean flat) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setFill(fill);
tool.setSize(radius);
tool.setBrush(new LineBrush(shell, select, flat), "worldedit.brush.line");
tool.setBrush(new LineBrush(shell, select, flat), "worldedit.brush.line", player);
player.print(BBC.getPrefix() + BBC.BRUSH_LINE.f(radius));
}
@ -183,10 +201,10 @@ public class BrushCommands {
@CommandPermissions("worldedit.brush.spline")
public void splineBrush(Player player, LocalSession session, Pattern fill, @Optional("25") double radius) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setFill(fill);
tool.setSize(radius);
tool.setBrush(new SplineBrush(player, session, tool), "worldedit.brush.spline");
tool.setBrush(new SplineBrush(player, session, tool), "worldedit.brush.spline", player);
player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.f(radius));
}
@ -205,14 +223,14 @@ public class BrushCommands {
public void sphereBrush(Player player, LocalSession session, Pattern fill, @Optional("2") double radius, @Switch('h') boolean hollow) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setFill(fill);
tool.setSize(radius);
if (hollow) {
tool.setBrush(new HollowSphereBrush(), "worldedit.brush.sphere");
tool.setBrush(new HollowSphereBrush(), "worldedit.brush.sphere", player);
} else {
tool.setBrush(new SphereBrush(), "worldedit.brush.sphere");
tool.setBrush(new SphereBrush(), "worldedit.brush.sphere", player);
}
if (fill instanceof BlockPattern) {
BaseBlock block = ((BlockPattern) fill).getBlock();
@ -245,14 +263,14 @@ public class BrushCommands {
worldEdit.checkMaxBrushRadius(radius);
worldEdit.checkMaxBrushRadius(height);
BrushTool tool = session.getBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setFill(fill);
tool.setSize(radius);
if (hollow) {
tool.setBrush(new HollowCylinderBrush(height), "worldedit.brush.cylinder");
tool.setBrush(new HollowCylinderBrush(height), "worldedit.brush.cylinder", player);
} else {
tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder");
tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder", player);
}
player.print(BBC.getPrefix() + BBC.BRUSH_SPHERE.f(radius, height));
}
@ -279,8 +297,8 @@ public class BrushCommands {
worldEdit.checkMaxBrushRadius(size.getBlockY());
worldEdit.checkMaxBrushRadius(size.getBlockZ());
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard");
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard", player);
player.print(BBC.getPrefix() + BBC.BRUSH_CLIPBOARD.s());
}
@ -305,9 +323,9 @@ public class BrushCommands {
FawePlayer fp = FawePlayer.wrap(player);
FaweLimit limit = Settings.IMP.getLimit(fp);
iterations = Math.min(limit.MAX_ITERATIONS, iterations);
BrushTool tool = session.getBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setSize(radius);
tool.setBrush(new SmoothBrush(iterations, naturalBlocksOnly), "worldedit.brush.smooth");
tool.setBrush(new SmoothBrush(iterations, naturalBlocksOnly), "worldedit.brush.smooth", player);
player.print(BBC.getPrefix() + BBC.BRUSH_SMOOTH.f(radius, iterations, (naturalBlocksOnly ? "natural blocks only" : "any block")));
}
@ -323,12 +341,12 @@ public class BrushCommands {
public void extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
Pattern fill = new BlockPattern(new BaseBlock(0));
tool.setFill(fill);
tool.setSize(radius);
tool.setMask(new BlockMask(editSession, new BaseBlock(BlockID.FIRE)));
tool.setBrush(new SphereBrush(), "worldedit.brush.ex");
tool.setBrush(new SphereBrush(), "worldedit.brush.ex", player);
BBC.BRUSH_EXTINGUISHER.send(player, radius);
player.print(BBC.getPrefix() + BBC.BRUSH_EXTINGUISHER.f(radius));
}
@ -349,9 +367,9 @@ public class BrushCommands {
public void gravityBrush(Player player, LocalSession session, @Optional("5") double radius, @Switch('h') boolean fromMaxY) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setSize(radius);
tool.setBrush(new GravityBrush(fromMaxY, tool), "worldedit.brush.gravity");
tool.setBrush(new GravityBrush(fromMaxY, tool), "worldedit.brush.gravity", player);
player.print(BBC.getPrefix() + BBC.BRUSH_GRAVITY.f(radius));
}
@ -431,19 +449,19 @@ public class BrushCommands {
}
}
DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setSize(radius);
if (flat) {
try {
tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null, shape), "worldedit.brush.height");
tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null, shape), "worldedit.brush.height", player);
} catch (EmptyClipboardException ignore) {
tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, null, shape), "worldedit.brush.height");
tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, null, shape), "worldedit.brush.height", player);
}
} else {
try {
tool.setBrush(new HeightBrush(stream, rotation, yscale, tool, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null), "worldedit.brush.height");
tool.setBrush(new HeightBrush(stream, rotation, yscale, tool, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null), "worldedit.brush.height", player);
} catch (EmptyClipboardException ignore) {
tool.setBrush(new HeightBrush(stream, rotation, yscale, tool, null), "worldedit.brush.height");
tool.setBrush(new HeightBrush(stream, rotation, yscale, tool, null), "worldedit.brush.height", player);
}
}
player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius));
@ -464,9 +482,9 @@ public class BrushCommands {
@CommandPermissions("worldedit.brush.copy")
public void copy(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setSize(radius);
tool.setBrush(new CopyPastaBrush(tool), "worldedit.brush.copy");
tool.setBrush(new CopyPastaBrush(tool), "worldedit.brush.copy", player);
player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius));
}
@ -481,9 +499,9 @@ public class BrushCommands {
)
@CommandPermissions("worldedit.brush.command")
public void command(Player player, LocalSession session, @Optional("5") double radius, CommandContext args) throws WorldEditException {
BrushTool tool = session.getBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
String cmd = args.getJoinedStrings(1);
tool.setBrush(new CommandBrush(tool, cmd, radius), "worldedit.brush.copy");
tool.setBrush(new CommandBrush(tool, cmd, radius), "worldedit.brush.copy", player);
player.print(BBC.getPrefix() + BBC.BRUSH_COMMAND.f(cmd));
}
@ -526,9 +544,9 @@ public class BrushCommands {
CreatureButcher flags = new CreatureButcher(player);
flags.fromCommand(args);
BrushTool tool = session.getBrushTool(player.getItemInHand());
BrushTool tool = session.getBrushTool(player.getItemInHand(), player);
tool.setSize(radius);
tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher");
tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher", player);
player.print(BBC.getPrefix() + BBC.BRUSH_BUTCHER.f(radius));
}

View File

@ -61,7 +61,7 @@ public class ToolCommands {
)
@CommandPermissions("worldedit.tool.inspect")
public void inspectBrush(Player player, LocalSession session, @Optional("1") double radius) throws WorldEditException {
session.setTool(player.getItemInHand(), new InspectBrush());
session.setTool(player.getItemInHand(), new InspectBrush(), player);
BBC.TOOL_INSPECT.send(player, ItemType.toHeldName(player.getItemInHand()));
}
@ -73,7 +73,7 @@ public class ToolCommands {
max = 0
)
public void none(Player player, LocalSession session, CommandContext args) throws WorldEditException {
session.setTool(player.getItemInHand(), null);
session.setTool(player.getItemInHand(), null, player);
BBC.TOOL_NONE.send(player);
}
@ -86,7 +86,7 @@ public class ToolCommands {
)
@CommandPermissions("worldedit.tool.info")
public void info(Player player, LocalSession session, CommandContext args) throws WorldEditException {
session.setTool(player.getItemInHand(), new QueryTool());
session.setTool(player.getItemInHand(), new QueryTool(), player);
BBC.TOOL_INFO.send(player, ItemType.toHeldName(player.getItemInHand()));
}
@ -110,7 +110,7 @@ public class ToolCommands {
return;
}
session.setTool(player.getItemInHand(), new TreePlanter(new TreeGenerator(type)));
session.setTool(player.getItemInHand(), new TreePlanter(new TreeGenerator(type)), player);
BBC.TOOL_TREE.send(player, ItemType.toHeldName(player.getItemInHand()));
}
@ -124,7 +124,7 @@ public class ToolCommands {
@CommandPermissions("worldedit.tool.replacer")
public void repl(Player player, LocalSession session, CommandContext args) throws WorldEditException {
BaseBlock targetBlock = we.getBlock(player, args.getString(0));
session.setTool(player.getItemInHand(), new BlockReplacer(targetBlock));
session.setTool(player.getItemInHand(), new BlockReplacer(targetBlock), player);
BBC.TOOL_REPL.send(player, ItemType.toHeldName(player.getItemInHand()));
}
@ -138,7 +138,7 @@ public class ToolCommands {
@CommandPermissions("worldedit.tool.data-cycler")
public void cycler(Player player, LocalSession session, CommandContext args) throws WorldEditException {
session.setTool(player.getItemInHand(), new BlockDataCyler());
session.setTool(player.getItemInHand(), new BlockDataCyler(), player);
BBC.TOOL_CYCLER.send(player, ItemType.toHeldName(player.getItemInHand()));
}
@ -160,7 +160,7 @@ public class ToolCommands {
}
Pattern pattern = we.getBlockPattern(player, args.getString(0));
session.setTool(player.getItemInHand(), new FloodFillTool(range, pattern));
session.setTool(player.getItemInHand(), new FloodFillTool(range, pattern), player);
BBC.TOOL_FLOOD_FILL.send(player, ItemType.toHeldName(player.getItemInHand()));
}
@ -173,7 +173,7 @@ public class ToolCommands {
)
@CommandPermissions("worldedit.tool.deltree")
public void deltree(Player player, LocalSession session, CommandContext args) throws WorldEditException {
session.setTool(player.getItemInHand(), new FloatingTreeRemover());
session.setTool(player.getItemInHand(), new FloatingTreeRemover(), player);
BBC.TOOL_DELTREE.send(player, ItemType.toHeldName(player.getItemInHand()));
}
@ -186,7 +186,7 @@ public class ToolCommands {
)
@CommandPermissions("worldedit.tool.farwand")
public void farwand(Player player, LocalSession session, CommandContext args) throws WorldEditException {
session.setTool(player.getItemInHand(), new DistanceWand());
session.setTool(player.getItemInHand(), new DistanceWand(), player);
BBC.TOOL_FARWAND.send(player, ItemType.toHeldName(player.getItemInHand()));
}
@ -202,7 +202,7 @@ public class ToolCommands {
BaseBlock secondary = we.getBlock(player, args.getString(0));
BaseBlock primary = we.getBlock(player, args.getString(1));
session.setTool(player.getItemInHand(), new LongRangeBuildTool(primary, secondary));
session.setTool(player.getItemInHand(), new LongRangeBuildTool(primary, secondary), player);
BBC.TOOL_LRBUILD_BOUND.send(player, ItemType.toHeldName(player.getItemInHand()));
BBC.TOOL_LRBUILD_INFO.send(player, ItemType.toName(secondary.getType()), ItemType.toName(primary.getType()));
}

View File

@ -1,7 +1,6 @@
package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.brush.DoubleActionBrushTool;
import com.boydti.fawe.object.extent.DefaultTransformParser;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.sk89q.minecraft.util.commands.Command;
@ -77,8 +76,6 @@ public class ToolUtilCommands {
if (context == null || context.argsLength() == 0) {
if (tool instanceof BrushTool) {
((BrushTool) tool).setMask(null);
} else if (tool instanceof DoubleActionBrushTool) {
((DoubleActionBrushTool) tool).setMask(null);
}
BBC.BRUSH_MASK_DISABLED.send(player);
} else {
@ -90,8 +87,6 @@ public class ToolUtilCommands {
Mask mask = we.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext);
if (tool instanceof BrushTool) {
((BrushTool) tool).setMask(mask);
} else if (tool instanceof DoubleActionBrushTool) {
((DoubleActionBrushTool) tool).setMask(mask);
}
BBC.BRUSH_MASK.send(player);
}
@ -114,8 +109,6 @@ public class ToolUtilCommands {
if (context == null || context.argsLength() == 0) {
if (tool instanceof BrushTool) {
((BrushTool) tool).setSourceMask(null);
} else if (tool instanceof DoubleActionBrushTool) {
((DoubleActionBrushTool) tool).setMask(null);
}
BBC.BRUSH_SOURCE_MASK_DISABLED.send(player);
} else {
@ -127,8 +120,6 @@ public class ToolUtilCommands {
Mask mask = we.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext);
if (tool instanceof BrushTool) {
((BrushTool) tool).setSourceMask(mask);
} else if (tool instanceof DoubleActionBrushTool) {
((DoubleActionBrushTool) tool).setSourceMask(mask);
}
BBC.BRUSH_SOURCE_MASK.send(player);
}
@ -150,8 +141,6 @@ public class ToolUtilCommands {
if (context == null || context.argsLength() == 0) {
if (tool instanceof BrushTool) {
((BrushTool) tool).setTransform(null);
} else if (tool instanceof DoubleActionBrushTool) {
((DoubleActionBrushTool) tool).setTransform(null);
}
BBC.BRUSH_TRANSFORM_DISABLED.send(player);
} else {
@ -163,8 +152,6 @@ public class ToolUtilCommands {
ResettableExtent transform = transformParser.parseFromInput(context.getJoinedStrings(0), parserContext);
if (tool instanceof BrushTool) {
((BrushTool) tool).setTransform(transform);
} else if (tool instanceof DoubleActionBrushTool) {
((DoubleActionBrushTool) tool).setTransform(transform);
}
BBC.BRUSH_TRANSFORM.send(player);
}
@ -181,9 +168,7 @@ public class ToolUtilCommands {
public void material(Player player, LocalSession session, Pattern pattern) throws WorldEditException {
Tool tool = session.getTool(player.getItemInHand());
if (tool instanceof BrushTool) {
((BrushTool) tool).setMask(null);
} else if (tool instanceof DoubleActionBrushTool) {
((DoubleActionBrushTool) tool).setFill(pattern);
((BrushTool) tool).setFill(pattern);
}
BBC.BRUSH_MATERIAL.send(player);
}
@ -197,12 +182,10 @@ public class ToolUtilCommands {
)
@CommandPermissions("worldedit.brush.options.range")
public void range(Player player, LocalSession session, CommandContext args) throws WorldEditException {
int range = args.getInteger(0);
int range = Math.max(0, Math.min(256, args.getInteger(0)));
Tool tool = session.getTool(player.getItemInHand());
if (tool instanceof BrushTool) {
((BrushTool) tool).setMask(null);
} else if (tool instanceof DoubleActionBrushTool) {
((DoubleActionBrushTool) tool).setRange(range);
((BrushTool) tool).setRange(range);
}
BBC.BRUSH_RANGE.send(player);
}
@ -222,9 +205,7 @@ public class ToolUtilCommands {
Tool tool = session.getTool(player.getItemInHand());
if (tool instanceof BrushTool) {
((BrushTool) tool).setMask(null);
} else if (tool instanceof DoubleActionBrushTool) {
((DoubleActionBrushTool) tool).setSize(radius);
((BrushTool) tool).setSize(radius);
}
BBC.BRUSH_SIZE.send(player);
}

View File

@ -1,6 +1,8 @@
package com.sk89q.worldedit.command.tool;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.brush.DoubleActionBrush;
import com.boydti.fawe.object.brush.visualization.VisualBrush;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
@ -8,7 +10,6 @@ import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.command.tool.brush.SphereBrush;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
@ -22,17 +23,19 @@ import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Builds a shape at the place being looked at.
*/
public class BrushTool implements TraceTool {
public class BrushTool implements DoubleActionTraceTool {
public enum BrushAction {
PRIMARY,
SECONDARY
}
protected static int MAX_RANGE = 500;
protected int range = -1;
private Mask mask = null;
private Mask sourceMask = null;
private ResettableExtent transform = null;
private Brush brush = new SphereBrush();
private Brush brush = null;
@Nullable
private Pattern material;
private double size = 1;
@ -70,15 +73,6 @@ public class BrushTool implements TraceTool {
return mask;
}
/**
* Set the block filter used for identifying blocks to replace.
*
* @param filter the filter to set
*/
public void setMask(Mask filter) {
this.mask = filter;
}
/**
* Get the filter.
*
@ -88,6 +82,15 @@ public class BrushTool implements TraceTool {
return sourceMask;
}
/**
* Set the block filter used for identifying blocks to replace.
*
* @param filter the filter to set
*/
public void setMask(Mask filter) {
this.mask = filter;
}
/**
* Set the block filter used for identifying blocks to replace.
*
@ -104,6 +107,13 @@ public class BrushTool implements TraceTool {
* @param permission the permission
*/
public void setBrush(Brush brush, String permission) {
setBrush(brush, permission, null);
}
public void setBrush(Brush brush, String permission, Player player) {
if (player != null && brush instanceof VisualBrush) {
((VisualBrush) brush).clear(player);
}
this.brush = brush;
this.permission = permission;
}
@ -171,8 +181,10 @@ public class BrushTool implements TraceTool {
this.range = range;
}
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
public boolean act(BrushAction action, Platform server, LocalConfiguration config, Player player, LocalSession session) {
if (action == BrushAction.SECONDARY && !(brush instanceof DoubleActionBrush)) {
return false;
}
WorldVector target = null;
target = player.getBlockTrace(getRange(), true);
@ -199,7 +211,7 @@ public class BrushTool implements TraceTool {
}
}
if (sourceMask != null) {
Mask existingMask = editSession.getMask();
Mask existingMask = editSession.getSourceMask();
if (existingMask == null) {
editSession.setSourceMask(sourceMask);
@ -215,7 +227,11 @@ public class BrushTool implements TraceTool {
editSession.addTransform(transform);
}
try {
brush.build(editSession, target, material, size);
if (brush instanceof DoubleActionBrush) {
((DoubleActionBrush) brush).build(action, editSession, target, material, size);
} else {
brush.build(editSession, target, material, size);
}
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached."); // Never happens
} finally {
@ -224,11 +240,20 @@ public class BrushTool implements TraceTool {
}
session.remember(editSession);
}
return true;
}
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
return act(BrushAction.PRIMARY, server, config, player, session);
}
@Override
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
return act(BrushAction.SECONDARY, server, config, player, session);
}
public static Class<?> inject() {
return BrushTool.class;
}
}
}

View File

@ -447,14 +447,18 @@ public class PlatformManager {
}
}
} catch (Throwable e) {
FaweException faweException = FaweException.get(e);
if (faweException != null) {
BBC.WORLDEDIT_CANCEL_REASON.send(actor, faweException.getMessage());
} else {
actor.printError("Please report this error: [See console]");
actor.printRaw(e.getClass().getName() + ": " + e.getMessage());
MainUtil.handleError(e);
}
handleThrowable(e, actor);
}
}
public void handleThrowable(Throwable e, Actor actor) {
FaweException faweException = FaweException.get(e);
if (faweException != null) {
BBC.WORLDEDIT_CANCEL_REASON.send(actor, faweException.getMessage());
} else {
actor.printError("Please report this error: [See console]");
actor.printRaw(e.getClass().getName() + ": " + e.getMessage());
MainUtil.handleError(e);
}
}

View File

@ -204,7 +204,7 @@ public class BlockTransformExtent extends ResettableExtent {
if (value != null && value.getDirection() != null) {
StateValue newValue = getNewStateValue(state, transform, value.getDirection());
if (newValue != null) {
if (changedBlock.hasWildcardData()) {
if (changedBlock.isImmutable()) {
changedBlock = new BaseBlock(changedBlock.getId(), changedBlock.getData(), changedBlock.getNbtData());
}
newValue.set(changedBlock);

View File

@ -0,0 +1,59 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.function.mask;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import javax.annotation.Nullable;
/**
* Tests whether a given vector meets a criteria.
*/
public interface Mask extends com.sk89q.worldedit.masks.Mask {
/**
* Returns true if the criteria is met.
*
* @param vector the vector to test
* @return true if the criteria is met
*/
boolean test(Vector vector);
/**
* Get the 2D version of this mask if one exists.
*
* @return a 2D mask version or {@code null} if this mask can't be 2D
*/
@Nullable
Mask2D toMask2D();
default void prepare(LocalSession session, LocalPlayer player, Vector target) {}
default boolean matches(EditSession editSession, Vector position) {
return test(position);
}
public static Class<Mask> inject() {
return Mask.class;
}
}

View File

@ -17,39 +17,36 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.patterns;
package com.sk89q.worldedit.function.pattern;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
/**
* @deprecated See {@link com.sk89q.worldedit.function.pattern.Pattern}
* Returns a {@link BaseBlock} for a given position.
*/
@Deprecated
public interface Pattern { //extends com.sk89q.worldedit.function.pattern.Pattern {
public interface Pattern extends com.sk89q.worldedit.patterns.Pattern {
/**
* Get a block for a position. This return value of this method does
* not have to be consistent for the same position.
* Return a {@link BaseBlock} for the given position.
*
* @param position the position where a block is needed
* @param position the position
* @return a block
*/
public BaseBlock next(Vector position);
BaseBlock apply(Vector position);
/**
* Get a block for a position. This return value of this method does
* not have to be consistent for the same position.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
* @return a block
*/
public BaseBlock next(int x, int y, int z);
@Override
default BaseBlock next(Vector position) {
return apply(position);
}
// @Override
// default BaseBlock apply(Vector position) {
// return next(position);
// }
@Override
default BaseBlock next(int x, int y, int z) {
return apply(MutableBlockVector.get(x, y, z));
}
public static Class<Pattern> inject() {
return Pattern.class;
}
}

View File

@ -22,6 +22,9 @@ public final class Patterns {
* @return a new-style pattern
*/
public static Pattern wrap(final com.sk89q.worldedit.patterns.Pattern pattern) {
if (pattern instanceof Pattern) {
return (Pattern) pattern;
}
checkNotNull(pattern);
return new Pattern() {
@Override

View File

@ -14,11 +14,22 @@ import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.RunContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public abstract class BreadthFirstSearch implements Operation {
public static Vector[] DEFAULT_DIRECTIONS = new Vector[6];
static {
DEFAULT_DIRECTIONS[0] = (new MutableBlockVector(0, -1, 0));
DEFAULT_DIRECTIONS[1] = (new MutableBlockVector(0, 1, 0));
DEFAULT_DIRECTIONS[2] = (new MutableBlockVector(-1, 0, 0));
DEFAULT_DIRECTIONS[3] = (new MutableBlockVector(1, 0, 0));
DEFAULT_DIRECTIONS[4] = (new MutableBlockVector(0, 0, -1));
DEFAULT_DIRECTIONS[5] = (new MutableBlockVector(0, 0, 1));
}
private final RegionFunction function;
private final List<Vector> directions = new ArrayList<>();
private BlockVectorSet visited;
@ -41,12 +52,7 @@ public abstract class BreadthFirstSearch implements Operation {
this.queue = new BlockVectorSet();
this.visited = new BlockVectorSet();
this.function = function;
this.directions.add(new Vector(0, -1, 0));
this.directions.add(new Vector(0, 1, 0));
this.directions.add(new Vector(-1, 0, 0));
this.directions.add(new Vector(1, 0, 0));
this.directions.add(new Vector(0, 0, -1));
this.directions.add(new Vector(0, 0, 1));
this.directions.addAll(Arrays.asList(DEFAULT_DIRECTIONS));
this.maxDepth = maxDepth;
}

View File

@ -46,6 +46,7 @@ public class RegionVisitor implements Operation {
public final Iterable<? extends Vector> iterable;
public final RegionFunction function;
private final MappedFaweQueue queue;
private boolean useCuboidIterator = false;
public int affected = 0;
/**

View File

@ -44,6 +44,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
private Vector pos1;
private Vector pos2;
private boolean useOldIterator;
private int minX,minY,minZ,maxX,maxY,maxZ;
/**
@ -80,6 +81,10 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
recalculate();
}
public void setUseOldIterator(boolean useOldIterator) {
this.useOldIterator = useOldIterator;
}
/**
* Get the first cuboid-defining corner.
*
@ -400,7 +405,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
@Override
public Iterator<BlockVector> iterator() {
if (Settings.IMP.HISTORY.COMPRESSION_LEVEL >= 9) {
if (Settings.IMP.HISTORY.COMPRESSION_LEVEL >= 9 || useOldIterator) {
return iterator_old();
}
return new Iterator<BlockVector>() {
@ -445,7 +450,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
y = by;
if (x > tx) {
x = bx;
if (z >= tz) {
if (z > tz) {
if (!hasNext) {
throw new NoSuchElementException("End of iterator") {
@Override
@ -494,10 +499,11 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
private int nextX = min.getBlockX();
private int nextY = min.getBlockY();
private int nextZ = min.getBlockZ();
private boolean hasNext = true;
@Override
public boolean hasNext() {
return (nextZ != Integer.MIN_VALUE);
return hasNext;
}
@Override
@ -507,10 +513,10 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
mutable.mutZ(nextZ);
if (++nextX > max.getBlockX()) {
nextX = min.getBlockX();
if (++nextY > max.getBlockY()) {
nextY = min.getBlockY();
if (++nextZ > max.getBlockZ()) {
if (nextZ == Integer.MIN_VALUE) {
if (++nextZ > max.getBlockZ()) {
nextZ = min.getBlockZ();
if (++nextY > max.getBlockY()) {
if (!hasNext) {
throw new NoSuchElementException("End of iterator") {
@Override
public synchronized Throwable fillInStackTrace() {
@ -519,8 +525,9 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
};
}
nextX = max.getBlockX();
nextZ = max.getBlockZ();
nextY = max.getBlockY();
nextZ = Integer.MIN_VALUE;
hasNext = false;
}
}
}

View File

@ -0,0 +1,311 @@
info:
prefix: '&4&lFAWE:&f&7'
schematic_pasting: '&7Das Schematic wird eingefügt. Dies kann nicht rückgängig gemacht
werden.'
updated_lighting_selection: '&7Updates des Lichts werden in %s0 chunks durchgeführt.
(Es kann einige Sekunden dauern bis die Pakete gesendet wurden.)'
set_region: '&7Markierung wurde auf aktuelle WorldEdit Region übertragen.'
worldedit_command_limit: '&7Bitte warte bist deine momentane Aktion fertig gestellt
wurde.'
worldedit_delayed: '&7Bitte warte während wir deine aktuelle WorldEdit Aktion durchführen...'
worldedit_run: '&7Entschuldige die Verzögerung. Nun führen wir folgende Aktion von
dir aus: %s'
worldedit_complete: '&7WorldEdit Aktion fertiggestellt..'
require_selection_in_mask: '&7%s deiner Auswahl ist nicht innerhalb deiner Maske.
Du kannst du innerhalb erlaubter Regionen Veränderungen durchführen.'
worldedit_volume: '&7Du kannst keine %current% verändern. Die maximale Anzahl an
Blöcken die du verändern kannst ist %max%.'
worldedit_iterations: '&7Du kannst keine Aktion %current% Mal wiederholen. Die maximale
Anzahl an erlaubten Wiederholungen ist %max%.'
worldedit_unsafe: '&7Der Zugang zu diesem Befehl wurde verboten.'
worldedit_dangerous_worldedit: '&cFAWE führt unsicher WorldEdit Aktionen aus! Position:
%s0 Username: %s1'
worldedit_bypass: '&7&oUm deine Beschränkungen zu ignorieren nutze &c/wea'
worldedit_bypassed: '&7Beschränkungen werden nun ignoriert.'
worldedit_unmasked: '&6Deine WorldEdit Beschränkungen sind nun aufgehoben.'
worldedit_restricted: '&6Deine WorldEdit Beschränkungen sind nun aktiv.'
worldedit_oom_admin: |-
&cPossible options:
&8 - &7//fast
&8 - &7Do smaller edits
&8 - &7Allocate more memory
&8 - &7Disable this safeguard
compressed: WorldEdit Verlauf komprimiert. Saved ~ %s0b (%s1x smaller)
action_complete: Aktion fertiggestellt in %s0 Sekunden
lighting_propogate_selection: '&7Licht wurde berechnet in %s0 Chunks. (Info: Um
Licht zu entfernen nutze //removelight)'
worldedit_toggle_tips_on: '&7WorldEdit Tipps deaktiviert.'
worldedit_toggle_tips_off: '&7WorldEdit Tipps aktiviert.'
error:
worldedit_extend: '&cDeine WorldEdit Aktion überschreitet die erlaubte Region'
command_syntax: '&cBenutzung: &7%s0'
no_perm: '&cDir fehlt die Berechtigung: %s0'
setting_disable: '&cFehlende Einstellung: %s0'
schematic_not_found: '&cSchematic nicht gefunden: &7%s0'
no_region: '&cDu hast keine aktive WorldEdit Markierung'
no_mask: '&cDu hast keine Mask gesetzt'
not_player: '&cDieser Befehl kann nur von Spielern ausgeführt werden!'
player_not_found: '&cSpieler nicht gefunden:&7 %s0'
oom: |-
&8[&cCritical&8] &cDetected low memory i.e. < 1%. FAWE will take the following actions:
&8 - &7Terminate WE block placement
&8 - &7Clear WE history
&8 - &7Unload non essential chunks
&8 - &7Kill entities
&8 - &7Garbage collect
&cIgnore this if trying to crash server.
&7Note: Low memory is likely (but not necessarily) caused by WE
worldedit_some_fails: '&c%s0 Blöcke wurden nicht platziert, da sie ausserhalb der
erlaubten Region sind.'
worldedit_some_fails_blockbag: '&cFehlende Blöcke: %s0'
web:
generating_link: Upload %s, Bitte warten...
generating_link_failed: '&cErstellung eines Download-Links fehlgeschlagen!'
download_link: '%s'
worldedit:
general:
mask_disabled: Globale Maske deaktiviert
mask: Globale Maske gesetzt
transform_disabled: Globale Transformation deaktiviert
transform: Globale Transformation gesetzt
source_mask_disabled: Globale Quell-Maske deaktiviert
source_mask: Global Quell-Maske gesetzt
fast_enabled: Fast-Modus aktiviert. Verlauf und Beschränkungen werden ignoriert.
fast_disabled: Fast-Modus deaktiviert
place_enabled: 'Platziere nun an Pos. #1.'
place_disabled: Platziere nun an dem Block in dem du stehst.
copy:
command_copy: '%s0 Blöcke kopiert'
cut:
command_cut_slow: |-
%s0 blocks were cut.
Tip: lazycut is safer
command_cut_lazy: '%s0 Blöcke werden beim einfügen entfernt'
paste:
command_paste: Zwischenablage wurde bei Position %s0 eingefügt
rotate:
command_rotate: Zwischenablage wurde gedreht
flip:
command_flipped: Zwischenablage wurde gespiegelt
regen:
command_regen_0: |-
Region regenerated.
Tip: Use a biome with /regen [biome]
command_regen_1: |-
Region regenerated.
Tip: Use a seed with /regen [biome] [seed]
command_regen_2: Region regeneriert.
tree:
command_tree: '%s0 Bäume erstellt.'
command_pumpkin: '%s0 Kürbis-Patch erstellt.'
flora:
command_flora: '%s0 Pflanzen erstellt.'
history:
command_history_clear: Verlauf gelöscht
command_redo_success: Redo erfolgreich.
command_undo_success: Undo erfolgreich.
command_redo_error: Nothing left to redo. (See also `/inspect` and `/frb`)
command_undo_error: Nothing left to undo. (See also `/inspect` and `/frb`)
command_history_other_error: WorldEdit Verlauf für %s0 konnte nicht gefunden werden.
operation:
operation: Operation wird durchgeführt (%s0)
selection:
selection_wand: 'Linksklick: Markiere Position #1; Rechtsklick: Markiere Position
#2'
selection_wand_disable: Bearbeitungs-Tool deaktiviert.
selection_wand_enable: Bearbeitungs-Tool aktiviert.
selection_chunk: Chunk ausgewählt (%s0)
selection_chunks: Chunks ausgewählt (%s0) - (%s1)
selection_contract: Markierung verkleinert um %s0 Blöcke.
selection_count: '%s0 Blöcke wurden gezählt.'
selection_distr: '# Gesamtanzahl Blöcke: %s0'
selection_expand: Markierung erweitert um %s0 Blöcke
selection_expand_vert: Markierung erweitert um %s0 Blöcke (Maximaler Baubereich)
selection_inset: Markierung verkleinert
selection_outset: Markierung vergößert
selection_shift: Region verschoben
selection_cleared: Auswahl gelöscht
brush:
brush_butcher: Butcher Pinsel ausgerüstet (%s0)
brush_clipboard: Clipboard Pinsel Format ausgerüstet
brush_cylinder: Cylinder Pinsel Format ausgerüstet (%s0 by %s1).
brush_extinguisher: Extinguisher ausgerüstet (%s0).
brush_gravity: Gravity Pinsel ausgerüstet (%s0)
brush_height: Height Pinsel ausgerüstet (%s0)
brush_copy: Copy Pinsel ausgerüstet (%s0)
brush_command: Command Pinsel ausgerüstet (%s0)
brush_height_invalid: Invalid height map file (%s0)
brush_smooth: Smooth Pinsel ausgerüstet (%s0 x %s1 using %s2).
brush_sphere: Sphere Pinsel Format ausgerüstet (%s0).
brush_line: Linien Pinsel Format ausgerüstet (%s0).
brush_spline: Linien Pinsel Format ausgerüstet (%s0). Rechstklicke ein Ende um ein Format hinzuzufügen
brush_spline_primary: Position hinzugefügt, Linksklick zum verbinden!
brush_spline_secondary_error: Nicht genügend Positionen gesetzt!
brush_spline_secondary: Kurve erstellt
brush_blend_ball: Blend ball Pinsel ausgerüstet (%s0).
brush_erode: Erode Pinsel ausgerüstet (%s0).
brush_paste_none: Zwischenablage leer! Nichts zum einfügen!
brush_size: Pinsel Größe gesetzt
brush_range: Pinsel Größe gesetzt
brush_mask_disabled: Pinsel Maske deaktiviert
brush_mask: Pinsel Maske gesetzt
brush_transform_disabled: Pinsel Transformation deaktiviert
brush_transform: Pinsel Transformation gesetzt
brush_material: Pinsel Material gesetzt
brush_recursive: Rekursiver Pinsel ausgerüstet (%s0).
brush_try_other: |-
&cFAWE adds other, more suitable brushes e.g.
&8 - &7//br height [radius=5] [#clipboard|file=null] [rotation=0] [yscale=1.00]
brush_none: You aren't holding a brush!
brush_source_mask_disabled: Pinsel Quell-Maske deaktiviert
brush_source_mask: Pinsel Quell-Maske gesetzt
rollback:
rollback_element: annullierend %s0
tool:
tool_inspect: Inpektions-Tool gebunden an %s0.
tool_inspect_info: '&7%s0 änderte %s1 zu %s2 %s3 zuvor'
tool_inspect_info_footer: '&6Total: &7%s0 Änderungen'
tool_none: Tool vom aktuellen Item entfernt.
tool_info: Info-Tool gebunden an %s0.
tool_tree: Tree-Tool gebunden an %s0.
tool_tree_error: Baum Typ %s0 ist unbekannt.
tool_repl: Block Replacer-Tool gebunden an %s0.
tool_cycler: Block Data Cycler-Tool gebunden an %s0.
tool_flood_fill: Block Flood Fill-Tool gebunden an %s0.
tool_deltree: Floating Tree Remover-Tool gebunden an %s0.
tool_farwand: Far Wand-Tool gebunden an%s0.
tool_lrbuild_bound: Long-range Building-Tool gebunden an %s0.
tool_lrbuild_info: 'Linksklick: Setze Position %s0; Rechtsklick: Setze Position
%s1'
superpickaxe_enabled: Super Pickaxe aktiviert.
superpickaxe_disabled: Super Pickaxe deaktiviert.
tool_range_error: 'Maximale Reichweite: %s0.'
tool_radius_error: 'Maximal erlaubter Pinsel Radius: %s0.'
superpickaxe_area_enabled: Modus geändert. Linksklick mit einer Spitzhacke. // zum deaktivieren.
schematic:
schematic_delete: Schematic %s0 wurde gelöscht.
schematic_format: 'Verfügbare Zwischenspeicher Formate (Name: Suche Namen)'
schematic_loaded: Schematic %s0 geladen. Platziere es mit //paste
schematic_saved: Schematic %s0 gespeichert.
schematic_page: Seite muss %s sein
schematic_none: Keine Schematics gefunden.
schematic_list: 'Verfügbare Schematics (Filename: Format) [%s0/%s1]:'
clipboard:
clipboard_cleared: Zwischenablage geleert
clipboard_invalid_format: 'Unbekanntes Zwischenspeicher Format: %s0'
visitor:
visitor_block: '%s0 Blöcke betroffen'
visitor_entity: '%s0 Entities betroffen'
visitor_flat: '%s0 Rubriken betroffen'
selector:
selector_cuboid_pos1: Pos 1 gesetzt %s0 %s1.
selector_cuboid_pos2: Pos 2 gesetzt %s0 %s1.
selector_invalid_coordinates: Ungültige Koordinaten %s0
selector_already_set: Position bereits gesetzt.
selector_fuzzy_pos1: Region gesetzt und expandiert von %s0 %s1.
selector_fuzzy_pos2: Erweiterung hinzugefügt um %s0 %s1.
selector_set_default: Dein Standard Auswahl-Tool ist nun %s0.
command:
command_invalid_syntax: The command was not used properly (no more help available).
snapshot:
snapshot_loaded: Snapshot '%s0' loaded; now restoring...
snapshot_set: 'Snapshot set to: %s0'
snapshot_newest: Now using newest snapshot.
snapshot_list_header: 'Snapshots for world (%s0):'
snapshot_list_footer: Use /snap use [snapshot] or /snap use latest.
biome:
biome_list_header: 'Biome (page %s0/%s1):'
biome_changed: Biome wurden geändert in %s0 Bezirken.
utility:
kill_success: '%s0 Entities in einem Radius von %s1 getötet.'
timezone:
timezone_set: 'Zeitzone für diese Sitzung gesetzt auf: %s0'
timezone_display: 'Aktuelle Zeit in dieser Zeitzone: %s0'
progress:
progress_message: '[ Zwischenspeicher: %s0 | Erledigt: %s1 ]'
progress_finished: '[ Fertiggestellt! ]'
cancel:
worldedit_cancel_count: '&c%s0 Veränderungen abgebrochen.'
worldedit_cancel_reason: '&cDeine WorldEdit Aktion wurde abgebrochen:&7 %s0&c.'
worldedit_cancel_reason_manual: Manueller Abbruch
worldedit_cancel_reason_low_memory: Zu wenig Speicher
worldedit_cancel_reason_max_changes: Zu viele Blöcke bearbeitet
worldedit_cancel_reason_max_checks: Zu viele Blöcke gecheckt
worldedit_cancel_reason_max_tiles: Zu viele Blockstatus
worldedit_cancel_reason_max_entities: Zu viele Entities
worldedit_cancel_reason_max_iterations: Maximale Wiederholungen
worldedit_cancel_reason_max_fails: Ausserhalb erlaubter Regionen (Bypass mit /wea)
worldedit_cancel_reason_no_region: Keine erlaubte Region (Bypass mit /wea)
worldedit_failed_load_chunk: '&cÜberspringe das Laden von Chunk: &7%s0;%s1&c. Versuche
chunk-wait zu erhöhen.'
history:
loading_clipboard: Lade Zwischenablage bitte warten.
indexing_history: Indiziere %s Verlauf auf der Platte, Bitte warten.
indexing_complete: 'Indizierung vollständig. Dauer: %s Sekunden!'
navigation:
ascend_fail: Kein freier Platz über dir gefunden.
ascended_plural: '%s0 Schichten aufgestiegen.'
ascended_singular: Eine Schicht aufgestiegen.
unstuck: Auf gehts!
descend_fail: Kein freier Platz unter dir gefunden.
descend_plural: '%s0 Schichten abgestiegen.'
descend_singular: Eine Schicht abgestiegen.
whoosh: Whoosh!
poof: Poof!
thru_fail: Kein freier Platz vor dir gefunden.
up_fail: Du würdest einen Block treffen!
no_block: Kein Block in Sichweite! (oder zu weit entfernt)
selection:
sel_cuboid: 'Quader: Linksklick für Position1, Rechtsklick für Position2'
sel_cuboid_extend: 'Quader: Linksklick für einen Startpunkt, Rechtsklick zum erweitern'
sel_2d_polygon: '2D Polygon Selektierer: Links/Rechtsklick um eine Markierung hinzuzufügen.'
sel_ellipsiod: 'Ellipsen Selektierer: Linksklick=Mitte, Rechtsklick zum erweitern'
sel_sphere: 'Kugel Selektierer : Linksklick=Mitte, Rechtsklick um den Radius zu
setzen'
sel_cylindrical: 'Zylinder Selektierer: Linksklick=Mitte, Rechtsklick zum erweitern'
sel_max: '%s0 Punkte maximal.'
sel_fuzzy: 'Fuzzy Selektierer: Linksklick um alle verbundenen Blöcke zu markieren,
Rechtsklick zum hinzufügen'
sel_convex_polyhedral: 'Convex polyhedral selector: Left click=First vertex, right
click to add more.'
sel_list: Für eine Liste der Selektoren nutze:&c //sel
sel_modes: 'Wähle einen der unten aufgelisteten Modi:'
tips:
tip_cancel: 'Tip: Du kannst eine Aktion abbrechen mit `//cancel`'
tip_download: 'Tip: Du kannst deinen Zwischenspeicher mit`//download` herunterladen'
tip_sel_list: 'Tip: Liste die verschiedenen Selektoren auf mit &c//sel list'
tip_select_connected: 'Tip: Wähle alle verbundenen Blöcke mit //sel fuzzy'
tip_set_pos1: 'Tip: Nutze pos1 als Muster &c//set pos1'
tip_farwand: 'Tip: Markiere entferne Blöcke mit &c//farwand'
tip_fast: '&7Tip: Platziere schnell und ohne Undo-Historie &c//fast'
tip_mask: '&7Tip: Setze eine Globale Zielmaske mit &c/gmask'
tip_mask_angle: 'Tip: Ersetze aufwärts Steigungen von 3-20 Blöcken mit&c //replace
/-20:-3 bedrock'
tip_set_linear: '&7Tip: Setze Blöcke linear mit&c //set #l3d:wood,bedrock'
tip_surface_spread: '&7Tip: Streue einen flachen Untergrund mit&c //set #surfacespread:5:0:5:#existing'
tip_set_hand: '&7Tip: Setze das Item in deiner Hand mit&c//set hand'
tip_replace_id: '&7Tip: Ersetze nur die Block-ID:&c //replace woodenstair #id:cobblestair'
tip_replace_light: 'Tip: Entferne Licht-Quellen&c //replace #brightness:1:15 0'
tip_tab_complete: 'Tip: Der Replace-Befehl unterstützt Tab-Vervollständigung'
tip_flip: 'Tip: Spiegeln mit &c//flip'
tip_deform: 'Tip: Forme um mit &c//deform'
tip_transform: 'Tip: Platziere eine Umformung mit &c//gtransform'
tip_copypaste: 'Tip: Füge durch Klick ein mit &c//br copypaste'
tip_source_mask: 'Tip: Setze eine Quell-Maske &c/gsmask <mask>&7'
tip_replace_marker: 'Tip: Ersetze einen Block mit deinem vollständigen Zwischenspeicher
mit &c//replace wool #fullcopy'
tip_paste: 'Tip: Füge deine Zwischeneinlage mit &c//paste ein'
tip_lazycopy: 'Tip: lazycopy ist schneller'
tip_rotate: 'Tip: Ausrichten mit &c//rotate'
tip_copy_pattern: 'Tip: Um ein Muster zu verwenden nutze &c#copy'
tip_brush_spline: '&7Tip Der spline &c//brush &7verbindet multiple Formen miteinander'
tip_brush_height: '&7Tip: Der Höhe &c//brush &7erhöht oder senkt Terrain sanft'
tip_brush_copy: '&7Tip: Der copypaste &c//brush &7erlaubt dir leichtes kopieren
und einfügen von Objekten.'
tip_brush_mask: '&7Tip: Setze eine brush Ziel-Maske mit &c/mask'
tip_brush_mask_source: '&7Tip: Setze eine brush Quell-Maske mit &c/smask'
tip_brush_transform: '&7Tip: Setze eine brush Transformation mit &c/transform'
tip_brush_relative: '&7Tip: Nutze ein relatives Zwischenspeicher-Muster mit //br
sphere #~:#copy'
tip_brush_command: '&7Tip: Probiere den Befehl &c//br cmd <radius> <cmd1;cmd2>'
tip_lazycut: '&7Tip: Es ist sicherer den Befehl &c//lazycut zu verwenden.'

View File

@ -21,9 +21,6 @@ dependencies {
compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
maven {
name = 'forge'

View File

@ -71,7 +71,7 @@ public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
}
@Override
public Player getPlayer() {
public Player toWorldEditPlayer() {
return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
}
}

View File

@ -21,9 +21,6 @@ dependencies {
compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
maven {
name = 'forge'

View File

@ -71,7 +71,7 @@ public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
}
@Override
public Player getPlayer() {
public Player toWorldEditPlayer() {
return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
}
}

View File

@ -21,9 +21,6 @@ dependencies {
compile 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
}
sourceCompatibility = 1.7
targetCompatibility = 1.7
repositories {
maven {
name = 'forge'

View File

@ -73,7 +73,7 @@ public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
}
@Override
public Player getPlayer() {
public Player toWorldEditPlayer() {
return ForgeWorldEdit.inst.wrap(this.parent);
}
}

View File

@ -21,9 +21,6 @@ dependencies {
compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
maven {
name = 'forge'

View File

@ -74,7 +74,7 @@ public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
}
@Override
public Player getPlayer() {
public Player toWorldEditPlayer() {
return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
}
}

View File

@ -20,9 +20,6 @@ dependencies {
compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
maven {
name = 'forge'

View File

@ -22,10 +22,12 @@ public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
@Override
public void sendTitle(String head, String sub) { // Not supported
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
}
@Override
public void resetTitle() { // Not supported
Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false";
}
@Override
@ -71,7 +73,7 @@ public class ForgePlayer extends FawePlayer<EntityPlayerMP> {
}
@Override
public Player getPlayer() {
public Player toWorldEditPlayer() {
return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent));
}
}

View File

@ -14,6 +14,7 @@ import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.brush.visualization.VisualChunk;
import com.boydti.fawe.regions.FaweMaskManager;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.world.World;
@ -30,6 +31,7 @@ public class FaweNukkit implements IFawe, Listener {
public FaweNukkit(NukkitWorldEdit mod) {
this.plugin = mod;
FaweChunk.HEIGHT = 256;
VisualChunk.VISUALIZE_BLOCK = 241 << 4;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}

View File

@ -66,7 +66,7 @@ public class FaweNukkitPlayer extends FawePlayer<Player> {
}
@Override
public com.sk89q.worldedit.entity.Player getPlayer() {
public com.sk89q.worldedit.entity.Player toWorldEditPlayer() {
return new NukkitPlayer((NukkitPlatform) Fawe.<FaweNukkit> imp().getPlugin().getPlatform(), parent);
}

View File

@ -52,9 +52,6 @@ dependencies {
compile name: 'worldedit-core-6.1.7-SNAPSHOT-dist'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
minecraft {
version = "1.11"
mappings = "snapshot_20161116"

View File

@ -73,7 +73,7 @@ public class SpongePlayer extends FawePlayer<Player> {
}
@Override
public com.sk89q.worldedit.entity.Player getPlayer() {
public com.sk89q.worldedit.entity.Player toWorldEditPlayer() {
if (WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.USER_COMMANDS) != null) {
for (Platform platform : WorldEdit.getInstance().getPlatformManager().getPlatforms()) {
return platform.matchPlayer(new FakePlayer(getName(), getUUID(), null));