Various major

New building mode (using CFI):
- CFI world is generated around the player in realtime
- Use WorldEdit/VS brushes while editing
- This is still being optimized
- Use a 1K radius height brush with near instant results
- https://github.com/boy0001/FastAsyncWorldedit/wiki/CreateFromImage

Early example: https://www.youtube.com/watch?v=jp1SjanWN70
This commit is contained in:
Jesse Boyd 2017-12-26 22:15:24 +11:00
parent 0dbb6171ef
commit 395b46c842
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
75 changed files with 4782 additions and 1363 deletions

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.IFawe;
import com.boydti.fawe.bukkit.chat.BukkitChatManager;
import com.boydti.fawe.bukkit.listener.BrushListener;
import com.boydti.fawe.bukkit.listener.CFIPacketListener;
import com.boydti.fawe.bukkit.listener.RenderListener;
import com.boydti.fawe.bukkit.regions.FactionsFeature;
import com.boydti.fawe.bukkit.regions.FactionsOneFeature;
@ -19,7 +20,7 @@ import com.boydti.fawe.bukkit.util.ItemUtil;
import com.boydti.fawe.bukkit.util.VaultUtil;
import com.boydti.fawe.bukkit.util.cui.CUIListener;
import com.boydti.fawe.bukkit.util.cui.StructureCUI;
import com.boydti.fawe.bukkit.util.image.BukkitImageListener;
import com.boydti.fawe.bukkit.listener.BukkitImageListener;
import com.boydti.fawe.bukkit.util.image.BukkitImageViewer;
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
@ -80,6 +81,7 @@ public class FaweBukkit implements IFawe, Listener {
private boolean listeningImages;
private BukkitImageListener imageListener;
private CFIPacketListener packetListener;
private boolean listeningCui;
private CUIListener cuiListener;
@ -136,10 +138,15 @@ public class FaweBukkit implements IFawe, Listener {
MainUtil.handleError(e);
Bukkit.getServer().shutdown();
}
// Registered delayed Event Listeners
TaskManager.IMP.task(new Runnable() {
@Override
public void run() {
// This class
Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin);
// The tick limiter
new ChunkListener();
}
});
@ -169,6 +176,10 @@ public class FaweBukkit implements IFawe, Listener {
try {
listeningImages = true;
PluginManager manager = Bukkit.getPluginManager();
if (manager.getPlugin("ProtocolLib") != null) {
packetListener = new CFIPacketListener(plugin);
}
if (manager.getPlugin("PacketListenerApi") == null) {
File output = new File(plugin.getDataFolder().getParentFile(), "PacketListenerAPI_v3.6.0-SNAPSHOT.jar");
byte[] jarData = Jars.PL_v3_6_0.download();

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.bukkit.util.image;
package com.boydti.fawe.bukkit.listener;
import com.boydti.fawe.bukkit.util.image.BukkitImageViewer;
import com.boydti.fawe.command.CFICommands;
import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator;
import com.boydti.fawe.object.FawePlayer;
@ -60,17 +61,21 @@ public class BukkitImageListener implements Listener {
Iterator<Player> iter = recipients.iterator();
while (iter.hasNext()) {
Player player = iter.next();
if (player.equals(event.getPlayer())) continue;
FawePlayer<Object> fp = FawePlayer.wrap(player);
if (!fp.hasMeta()) continue;
CFICommands.CFISettings settings = fp.getMeta("CFISettings");
if (settings != null && settings.hasGenerator()) {
String name = player.getName().toLowerCase();
if (!event.getMessage().toLowerCase().contains(name)) {
ArrayDeque<String> buffered = fp.getMeta("CFIBufferedMessages");
if (buffered == null) fp.setMeta("CFIBufferedMessaged", buffered = new ArrayDeque<String>());
String full = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage());
buffered.add(full);
iter.remove();
}
if (settings == null || !settings.hasGenerator()) continue;
String name = player.getName().toLowerCase();
if (!event.getMessage().toLowerCase().contains(name)) {
ArrayDeque<String> buffered = fp.getMeta("CFIBufferedMessages");
if (buffered == null) fp.setMeta("CFIBufferedMessaged", buffered = new ArrayDeque<String>());
String full = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage());
buffered.add(full);
iter.remove();
}
}
}
@ -183,7 +188,7 @@ public class BukkitImageListener implements Listener {
TaskManager.IMP.laterAsync(new Runnable() {
@Override
public void run() {
viewer.view(generator.draw());
viewer.view(generator);
}
}, 1);
return;
@ -263,7 +268,7 @@ public class BukkitImageListener implements Listener {
e.printStackTrace();
}
es.flushQueue();
viewer.view(generator.draw());
viewer.view(generator);
}
}, true, true);
@ -274,11 +279,5 @@ public class BukkitImageListener implements Listener {
}
}
}
}
}

View File

@ -0,0 +1,329 @@
package com.boydti.fawe.bukkit.listener;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.command.CFICommands;
import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal3;
import com.boydti.fawe.util.SetQueue;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.injector.netty.WirePacket;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.BlockPosition;
import com.comphenix.protocol.wrappers.ChunkCoordIntPair;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.WrappedBlockData;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.event.platform.BlockInteractEvent;
import com.sk89q.worldedit.event.platform.Interaction;
import com.sk89q.worldedit.extension.platform.PlatformManager;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.plugin.Plugin;
/**
* The CFIPacketListener handles packets for editing the HeightMapMCAGenerator
* The generator is a virtual world which only the creator can see
* - The virtual world is displayed inside the current world
* - Block/Chunk/Movement packets need to be handled properly
*/
public class CFIPacketListener implements Listener {
private final Plugin plugin;
private final ProtocolManager protocolmanager;
public CFIPacketListener(Plugin plugin) {
this.plugin = plugin;
this.protocolmanager = ProtocolLibrary.getProtocolManager();
// Direct digging to the virtual world
registerBlockEvent(PacketType.Play.Client.BLOCK_DIG, false, new RunnableVal3<PacketEvent, HeightMapMCAGenerator, Vector>() {
@Override
public void run(PacketEvent event, HeightMapMCAGenerator gen, Vector pt) {
try {
Player plr = event.getPlayer();
Vector realPos = pt.add(gen.getOrigin());
if (!sendBlockChange(plr, gen, pt, Interaction.HIT)) {
gen.setBlock(pt, EditSession.nullBlock);
}
} catch (WorldEditException e) {
e.printStackTrace();
}
}
});
// Direct placing to the virtual world
RunnableVal3<PacketEvent, HeightMapMCAGenerator, Vector> placeTask = new RunnableVal3<PacketEvent, HeightMapMCAGenerator, Vector>() {
@Override
public void run(PacketEvent event, HeightMapMCAGenerator gen, Vector pt) {
try {
Player plr = event.getPlayer();
List<EnumWrappers.Hand> hands = event.getPacket().getHands().getValues();
EnumWrappers.Hand enumHand = hands.isEmpty() ? EnumWrappers.Hand.MAIN_HAND : hands.get(0);
PlayerInventory inv = plr.getInventory();
ItemStack hand = enumHand == EnumWrappers.Hand.MAIN_HAND ? inv.getItemInMainHand() : inv.getItemInOffHand();
if (hand != null && hand.getType().isBlock() && hand.getTypeId() != 0) {
BaseBlock block = FaweCache.getBlock(hand.getTypeId(), hand.getDurability());
gen.setBlock(pt, block);
} else {
pt = getRelPos(event, gen);
sendBlockChange(plr, gen, pt, Interaction.OPEN);
}
} catch (WorldEditException e) {
e.printStackTrace();
}
}
};
registerBlockEvent(PacketType.Play.Client.BLOCK_PLACE, true, placeTask);
registerBlockEvent(PacketType.Play.Client.USE_ITEM, true, placeTask);
// Cancel block change packets where the real world overlaps with the virtual one
registerBlockEvent(PacketType.Play.Server.BLOCK_CHANGE, false, new RunnableVal3<PacketEvent, HeightMapMCAGenerator, Vector>() {
@Override
public void run(PacketEvent event, HeightMapMCAGenerator gen, Vector pt) {
// Do nothing
}
});
// Modify chunk packets where the real world overlaps with the virtual one
protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.MAP_CHUNK) {
@Override
public void onPacketSending(PacketEvent event) {
if (!event.isServerPacket()) return;
HeightMapMCAGenerator gen = getGenerator(event);
if (gen != null) {
Vector origin = gen.getOrigin();
PacketContainer packet = event.getPacket();
StructureModifier<Integer> ints = packet.getIntegers();
int cx = ints.read(0);
int cz = ints.read(1);
int ocx = origin.getBlockX() >> 4;
int ocz = origin.getBlockZ() >> 4;
if (gen.contain(new Vector((cx - ocx) << 4, 0, (cz - ocz) << 4))) {
event.setCancelled(true);
Player plr = event.getPlayer();
FaweQueue queue = SetQueue.IMP.getNewQueue(plr.getWorld().getName(), true, false);
FaweChunk toSend = gen.getSnapshot(cx - ocx, cz - ocz);
toSend.setLoc(gen, cx, cz);
queue.sendChunkUpdate(toSend, FawePlayer.wrap(plr));
}
}
}
});
// The following few listeners are to ignore block collisions where the virtual and real world overlap
protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_VELOCITY) {
@Override
public void onPacketSending(PacketEvent event) {
if (!event.isServerPacket()) return;
Player player = event.getPlayer();
Location pos = player.getLocation();
HeightMapMCAGenerator gen = getGenerator(event);
if (gen != null) {
Vector origin = gen.getOrigin();
Vector pt = new Vector(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
StructureModifier<Integer> ints = event.getPacket().getIntegers();
int id = ints.read(0);
int mx = ints.read(1);
int my = ints.read(2);
int mz = ints.read(3);
if (gen.contain(pt.subtract(origin)) && mx == 0 && my == 0 && mz == 0) {
event.setCancelled(true);
}
}
}
});
protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.POSITION) {
@Override
public void onPacketSending(PacketEvent event) {
if (!event.isServerPacket()) return;
Player player = event.getPlayer();
Location pos = player.getLocation();
HeightMapMCAGenerator gen = getGenerator(event);
if (gen != null) {
Vector origin = gen.getOrigin();
Vector from = new Vector(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
PacketContainer packet = event.getPacket();
StructureModifier<Double> doubles = packet.getDoubles();
Vector to = new Vector(doubles.read(0), doubles.read(1), doubles.read(2));
if (gen.contain(to.subtract(origin)) && from.distanceSq(to) < 8) {
int id = packet.getIntegers().read(0);
PacketContainer reply = new PacketContainer(PacketType.Play.Client.TELEPORT_ACCEPT);
reply.getIntegers().write(0, id);
try {
protocolmanager.recieveClientPacket(player, reply);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
event.setCancelled(true);
}
}
}
});
protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.MULTI_BLOCK_CHANGE) {
@Override
public void onPacketSending(PacketEvent event) {
if (!event.isServerPacket()) return;
HeightMapMCAGenerator gen = getGenerator(event);
if (gen != null) {
PacketContainer packet = event.getPacket();
ChunkCoordIntPair chunk = packet.getChunkCoordIntPairs().read(0);
Vector origin = gen.getOrigin();
int cx = chunk.getChunkX() - (origin.getBlockX() >> 4);
int cz = chunk.getChunkZ() - (origin.getBlockX() >> 4);
if (gen.contain(new Vector(cx << 4, 0, cz << 4))) {
event.setCancelled(true);
}
}
}
});
}
@EventHandler
public void onTeleport(PlayerTeleportEvent event) {
final Player player = event.getPlayer();
HeightMapMCAGenerator gen = getGenerator(player);
if (gen != null) {
Location from = event.getFrom();
Location to = event.getTo();
if (to.getWorld().equals(from.getWorld()) && to.distanceSquared(from) < 8) {
event.setTo(player.getLocation());
event.setCancelled(true);
player.setVelocity(player.getVelocity());
}
}
}
private boolean sendBlockChange(Player plr, HeightMapMCAGenerator gen, Vector pt, Interaction action) {
PlatformManager platform = WorldEdit.getInstance().getPlatformManager();
com.sk89q.worldedit.entity.Player actor = FawePlayer.wrap(plr).getPlayer();
com.sk89q.worldedit.util.Location location = new com.sk89q.worldedit.util.Location(actor.getWorld(), pt);
BlockInteractEvent toCall = new BlockInteractEvent(actor, location, action);
platform.handleBlockInteract(toCall);
if (toCall.isCancelled() || action == Interaction.OPEN) {
Vector realPos = pt.add(gen.getOrigin());
BaseBlock block = gen.getBlock(pt);
sendBlockChange(plr, realPos, block);
return true;
}
return false;
}
private void sendBlockChange(Player plr, Vector pt, BaseBlock block) {
PacketContainer container = new PacketContainer(PacketType.Play.Server.BLOCK_CHANGE);
// Block position
// block combined id
container.getBlockPositionModifier().write(0, new BlockPosition(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()));
WrappedBlockData bd = WrappedBlockData.createData(Material.getMaterial(block.getId()), block.getData());
container.getBlockData().write(0, bd);
try {
protocolmanager.sendWirePacket(plr, WirePacket.fromPacket(container));
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
private HeightMapMCAGenerator getGenerator(PacketEvent event) {
return getGenerator(event.getPlayer());
}
private HeightMapMCAGenerator getGenerator(Player player) {
CFICommands.CFISettings settings = FawePlayer.wrap(player).getMeta("CFISettings");
if (settings != null && settings.hasGenerator() && settings.getGenerator().hasPacketViewer()) {
return settings.getGenerator();
}
return null;
}
private Vector getRelPos(PacketEvent event, HeightMapMCAGenerator generator) {
PacketContainer packet = event.getPacket();
StructureModifier<BlockPosition> position = packet.getBlockPositionModifier();
BlockPosition loc = position.readSafely(0);
if (loc == null) return null;
Vector origin = generator.getOrigin();
Vector pt = new Vector(loc.getX() - origin.getBlockX(), loc.getY() - origin.getBlockY(), loc.getZ() - origin.getBlockZ());
return pt;
}
private void handleBlockEvent(PacketEvent event, boolean relative, RunnableVal3<PacketEvent, HeightMapMCAGenerator, Vector> task) {
HeightMapMCAGenerator gen = getGenerator(event);
if (gen != null) {
Vector pt = getRelPos(event, gen);
if (pt != null) {
if (relative) pt = getRelative(event, pt);
if (gen.contain(pt)) {
event.setCancelled(true);
task.run(event, gen, pt);
}
}
}
}
private void registerBlockEvent(PacketType type, boolean relative, RunnableVal3<PacketEvent, HeightMapMCAGenerator, Vector> task) {
protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, type) {
@Override
public void onPacketReceiving(final PacketEvent event) {
if (type.isClient() || event.isServerPacket()) handleBlockEvent(event, relative, task);
}
@Override
public void onPacketSending(PacketEvent event) {
onPacketReceiving(event);
}
});
}
private Vector getRelative(PacketEvent container, Vector pt) {
PacketContainer packet = container.getPacket();
StructureModifier<EnumWrappers.Direction> dirs = packet.getDirections();
EnumWrappers.Direction dir = dirs.readSafely(0);
if (dir == null) return pt;
switch (dir.ordinal()) {
case 0: return pt.add(0, -1, 0);
case 1: return pt.add(0, 1, 0);
case 2: return pt.add(0, 0, -1);
case 3: return pt.add(0, 0, 1);
case 4: return pt.add(-1, 0, 0);
case 5: return pt.add(1, 0, 0);
default: return pt;
}
}
}

View File

@ -1,19 +1,24 @@
package com.boydti.fawe.bukkit.util.image;
import com.boydti.fawe.util.image.Drawable;
import com.boydti.fawe.util.image.ImageUtil;
import com.boydti.fawe.util.image.ImageViewer;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Collection;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Rotation;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.inventivetalent.mapmanager.MapManagerPlugin;
import org.inventivetalent.mapmanager.controller.MapController;
import org.inventivetalent.mapmanager.controller.MultiMapController;
@ -27,7 +32,6 @@ public class BukkitImageViewer implements ImageViewer {
private ItemFrame[][] frames;
private boolean reverse;
public BukkitImageViewer(Player player) {
mapManager = ((MapManagerPlugin) Bukkit.getPluginManager().getPlugin("MapManager")).getMapManager();
this.player = player;
@ -124,9 +128,17 @@ public class BukkitImageViewer implements ImageViewer {
}
@Override
public void view(BufferedImage image) {
last = image;
public void view(Drawable drawable) {
view(null, drawable);
}
private void view(@Nullable BufferedImage image, @Nullable Drawable drawable) {
if (image == null && drawable == null) throw new IllegalArgumentException("An image or drawable must be provided. Both cannot be null");
boolean initializing = last == null;
if (this.frames != null) {
if (image == null && drawable != null) image = drawable.draw();
last = image;
int width = frames.length;
int height = frames[0].length;
BufferedImage scaled = ImageUtil.getScaledInstance(image, 128 * width, 128 * height, RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
@ -136,6 +148,18 @@ public class BukkitImageViewer implements ImageViewer {
controller.sendContent(player);
controller.showInFrames(player, frames, true);
} else {
int slot = getMapSlot(player);
if (slot == -1) {
if (initializing) {
player.getInventory().setItemInMainHand(new ItemStack(Material.MAP));
} else {
return;
}
} else if (player.getInventory().getHeldItemSlot() != slot) {
player.getInventory().setHeldItemSlot(slot);
}
if (image == null && drawable != null) image = drawable.draw();
last = image;
BufferedImage scaled = ImageUtil.getScaledInstance(image, 128, 128, RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
MapWrapper mapWrapper = mapManager.wrapImage(scaled);
MapController controller = mapWrapper.getController();
@ -145,8 +169,19 @@ public class BukkitImageViewer implements ImageViewer {
}
}
private int getMapSlot(Player player) {
PlayerInventory inventory = player.getInventory();
for (int i = 0; i < 9; i++) {
ItemStack item = inventory.getItem(i);
if (item != null && item.getType() == Material.MAP) {
return i;
}
}
return -1;
}
public void refresh() {
if (last != null) view(last);
if (last != null) view(last, null);
}
@Override

View File

@ -56,14 +56,11 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
if (shallow) {
copy = new BukkitChunk_All(getParent(), getX(), getZ(), ids, count, air, heightMap);
copy.biomes = biomes;
copy.chunk = chunk;
} else {
copy = new BukkitChunk_All(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
copy.biomes = biomes;
copy.chunk = chunk;
copy.biomes = biomes.clone();
copy.chunk = chunk;
}
copy.chunk = chunk;
return copy;
}

View File

@ -4,14 +4,23 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.bukkit.BukkitPlayer;
import com.boydti.fawe.bukkit.FaweBukkit;
import com.boydti.fawe.bukkit.v1_12.packet.FaweChunkPacket;
import com.boydti.fawe.bukkit.v1_12.packet.MCAChunkPacket;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.jnbt.anvil.MCAChunk;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.queue.LazyFaweChunk;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.ReflectionUtils;
import com.boydti.fawe.util.TaskManager;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.injector.netty.WirePacket;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
@ -36,14 +45,26 @@ import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.plugin.Plugin;
public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMappedFaweQueue<World, CHUNK, CHUNKSECTIONS, SECTION> implements Listener {
protected static boolean PAPER = true;
private static BukkitImplAdapter adapter;
private static FaweAdapter_All backupAdaper;
private static Method methodToNative;
private static Method methodFromNative;
private static boolean setupAdapter = false;
private static Method methodGetHandle;
static {
Class<?> classCraftChunk = ReflectionUtils.getCbClass("CraftChunk");
try {
methodGetHandle = ReflectionUtils.setAccessible(classCraftChunk.getDeclaredMethod("getHandle"));
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public BukkitQueue_0(final com.sk89q.worldedit.world.World world) {
super(world);
@ -63,6 +84,86 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
}
}
@Override
public boolean supports(Capability capability) {
switch (capability) {
case CHUNK_PACKETS:
Plugin plib = Bukkit.getPluginManager().getPlugin("ProtocolLib");
return plib != null && plib.isEnabled();
}
return super.supports(capability);
}
@Override
public void sendChunkUpdate(FaweChunk chunk, FawePlayer... players) {
if (supports(Capability.CHUNK_PACKETS)) {
sendChunkUpdatePLIB(chunk, players);
} else {
sendBlockUpdate(chunk, players);
}
}
public void sendChunkUpdatePLIB(FaweChunk chunk, FawePlayer... players) {
ProtocolManager manager = ProtocolLibrary.getProtocolManager();
WirePacket packet = null;
int viewDistance = Bukkit.getViewDistance();
try {
for (int i = 0; i < players.length; i++) {
int cx = chunk.getX();
int cz = chunk.getZ();
Player player = ((BukkitPlayer) players[i]).parent;
Location loc = player.getLocation();
if (Math.abs((loc.getBlockX() >> 4) - cx) <= viewDistance && Math.abs((loc.getBlockZ() >> 4) - cz) <= viewDistance) {
if (packet == null) {
byte[] data;
byte[] buffer = new byte[8192];
if (chunk instanceof LazyFaweChunk) {
chunk = (FaweChunk) chunk.getChunk();
}
if (chunk instanceof MCAChunk) {
data = new MCAChunkPacket((MCAChunk) chunk, true, true, hasSky()).apply(buffer);
} else {
data = new FaweChunkPacket(chunk, true, true, hasSky()).apply(buffer);
}
packet = new WirePacket(PacketType.Play.Server.MAP_CHUNK, data);
}
manager.sendWirePacket(player, packet);
}
}
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean queueChunkLoad(int cx, int cz, RunnableVal<CHUNK> operation) {
if (PAPER) {
try {
getImpWorld().getChunkAtAsync(cx, cz, new World.ChunkLoadCallback() {
@Override
public void onLoad(Chunk bukkitChunk) {
try {
CHUNK chunk = (CHUNK) methodGetHandle.invoke(bukkitChunk);
try {
operation.run(chunk);
} catch (Throwable e) {
e.printStackTrace();
}
} catch (Throwable e) {
PAPER = false;
}
}
});
return true;
} catch (Throwable ignore) {
PAPER = false;
}
}
return super.queueChunkLoad(cx, cz);
}
public static BukkitImplAdapter getAdapter() {
if (adapter == null) setupAdapter(null);
if (adapter == null) return backupAdaper;

View File

@ -30,7 +30,6 @@ import org.bukkit.block.Biome;
public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot, ChunkSnapshot> {
public static int ALLOCATE;
private static int LIGHT_MASK = 0x739C0;
private ConcurrentMap<Long, ChunkSnapshot> chunkCache = new MapMaker()
.weakValues()
.makeMap();
@ -53,6 +52,29 @@ public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot,
}
}
@Override
public boolean queueChunkLoad(int cx, int cz, RunnableVal<ChunkSnapshot> operation) {
if (PAPER) {
try {
getImpWorld().getChunkAtAsync(cx, cz, new World.ChunkLoadCallback() {
@Override
public void onLoad(Chunk chunk) {
try {
ChunkSnapshot snapshot = chunk.getChunkSnapshot();
operation.run(snapshot);
} catch (Throwable e) {
e.printStackTrace();
}
}
});
return true;
} catch (Throwable ignore) {
PAPER = false;
}
}
return super.queueChunkLoad(cx, cz);
}
@Override
public Relighter getRelighter() {
return NullRelighter.INSTANCE;
@ -307,8 +329,11 @@ public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot,
}
@Override
public boolean supportsChangeTask() {
return getAdapter() != null;
public boolean supports(Capability capability) {
switch (capability) {
case CHANGE_TASKS: return getAdapter() != null;
}
return super.supports(capability);
}
private int skip;

View File

@ -4,18 +4,26 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.bukkit.BukkitPlayer;
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.bukkit.v1_12.packet.FaweChunkPacket;
import com.boydti.fawe.bukkit.v1_12.packet.MCAChunkPacket;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.jnbt.anvil.MCAChunk;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.brush.visualization.VisualChunk;
import com.boydti.fawe.object.queue.LazyFaweChunk;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.ReflectionUtils;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.injector.netty.WirePacket;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
@ -566,6 +574,37 @@ public class BukkitQueue_1_12 extends BukkitQueue_0<net.minecraft.server.v1_12_R
}
}
@Override
public void sendChunkUpdatePLIB(FaweChunk chunk, FawePlayer... players) {
PlayerChunkMap playerManager = ((CraftWorld) getWorld()).getHandle().getPlayerChunkMap();
ProtocolManager manager = ProtocolLibrary.getProtocolManager();
WirePacket packet = null;
try {
for (int i = 0; i < players.length; i++) {
CraftPlayer bukkitPlayer = ((CraftPlayer) ((BukkitPlayer) players[i]).parent);
EntityPlayer player = bukkitPlayer.getHandle();
if (playerManager.a(player, chunk.getX(), chunk.getZ())) {
if (packet == null) {
byte[] data;
byte[] buffer = new byte[8192];
if (chunk instanceof LazyFaweChunk) {
chunk = (FaweChunk) chunk.getChunk();
}
if (chunk instanceof MCAChunk) {
data = new MCAChunkPacket((MCAChunk) chunk, true, true, hasSky()).apply(buffer);
} else {
data = new FaweChunkPacket(chunk, true, true, hasSky()).apply(buffer);
}
packet = new WirePacket(PacketType.Play.Server.MAP_CHUNK, data);
}
manager.sendWirePacket(bukkitPlayer, packet);
}
}
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
@Override
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
try {

View File

@ -1,81 +1,92 @@
package com.boydti.fawe.bukkit.v1_12.packet;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.jnbt.anvil.MCAChunk;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.nbt.NbtBase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
public class FaweChunkPacket {
public class FaweChunkPacket implements Function<byte[], byte[]> {
private final MCAChunk chunk;
private final FaweChunk chunk;
private final boolean full;
private final boolean biomes;
private final boolean sky;
public FaweChunkPacket(MCAChunk fc, boolean replaceAllSections, boolean sendBiomeData, boolean hasSky) {
public FaweChunkPacket(FaweChunk fc, boolean replaceAllSections, boolean sendBiomeData, boolean hasSky) {
this.chunk = fc;
this.full = replaceAllSections;
this.biomes = sendBiomeData;
this.sky = hasSky;
}
public void write(PacketContainer packet) throws IOException {
@Override
public byte[] apply(byte[] buffer) {
try {
StructureModifier<Integer> ints = packet.getIntegers();
StructureModifier<byte[]> byteArray = packet.getByteArrays();
StructureModifier<Boolean> bools = packet.getBooleans();
ints.write(0, this.chunk.getX());
ints.write(1, this.chunk.getZ());
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
FaweOutputStream fos = new FaweOutputStream(baos);
bools.write(0, this.full);
ints.write(2, this.chunk.getBitMask()); // writeVarInt
fos.writeInt(this.chunk.getX());
fos.writeInt(this.chunk.getZ());
FastByteArrayOutputStream fbaos = new FastByteArrayOutputStream();
FaweOutputStream buffer = new FaweOutputStream(fbaos);
byte[][] ids = chunk.ids;
fos.writeBoolean(this.full);
fos.writeVarInt(this.chunk.getBitMask()); // writeVarInt
FastByteArrayOutputStream sectionByteArray = new FastByteArrayOutputStream(buffer);
FaweOutputStream sectionWriter = new FaweOutputStream(sectionByteArray);
char[][] ids = chunk.getCombinedIdArrays();
byte[][] blockLight = chunk.getBlockLightArray();
byte[][] skyLight = chunk.getSkyLightArray();
for (int layer = 0; layer < ids.length; layer++) {
byte[] layerIds = ids[layer];
char[] layerIds = ids[layer];
if (layerIds == null) {
continue;
}
byte[] layerData = chunk.data[layer];
int num = 9;
buffer.write(num); // num blocks, anything > 8 - doesn't need to be accurate
buffer.writeVarInt(0); // varint 0 - data palette global
int num = 13;
sectionWriter.write(num); // num blocks, anything > 8 - doesn't need to be accurate
sectionWriter.writeVarInt(0); // varint 0 - data palette global
BitArray bits = new BitArray(num, 4096);
for (int i = 0; i < 4096; i++) {
int id = layerIds[i];
if (id != 0) {
int data = FaweCache.hasData(id) ? chunk.getNibble(i, layerData) : 0;
int combined = FaweCache.getCombined(id, data);
bits.setAt(i, combined);
char combinedId = layerIds[i];
if (combinedId != 0) {
bits.setAt(i, combinedId);
}
}
buffer.write(bits.getBackingLongArray());
sectionWriter.write(bits.getBackingLongArray());
buffer.write(chunk.blockLight[layer]);
if (blockLight != null && blockLight[layer] != null) {
sectionWriter.write(blockLight[layer]);
} else {
sectionWriter.write(0, 2048);
}
if (sky) {
buffer.write(chunk.skyLight[layer]);
if (skyLight != null && skyLight[layer] != null) {
sectionWriter.write(skyLight[layer]);
} else {
sectionWriter.write((byte) 255, 2048);
}
}
}
if (this.biomes && chunk.biomes != null) {
buffer.write(chunk.biomes);
if (this.biomes) {
byte[] biomeArr = chunk.getBiomeArray();
if (biomeArr != null) {
sectionWriter.write(biomeArr);
}
}
byteArray.write(0, fbaos.toByteArray());
// TODO - empty
StructureModifier<List<NbtBase<?>>> list = packet.getListNbtModifier();
list.write(0, new ArrayList<>());
fos.writeVarInt(sectionByteArray.getSize());
for (byte[] arr : sectionByteArray.toByteArrays()) {
fos.write(arr);
}
fos.writeVarInt(0);
fos.close();
sectionWriter.close();
return baos.toByteArray();
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,83 @@
package com.boydti.fawe.bukkit.v1_12.packet;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.jnbt.anvil.MCAChunk;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import java.util.function.Function;
public class MCAChunkPacket implements Function<byte[], byte[]> {
private final MCAChunk chunk;
private final boolean full;
private final boolean biomes;
private final boolean sky;
public MCAChunkPacket(MCAChunk fc, boolean replaceAllSections, boolean sendBiomeData, boolean hasSky) {
this.chunk = fc;
this.full = replaceAllSections;
this.biomes = sendBiomeData;
this.sky = hasSky;
}
@Override
public byte[] apply(byte[] buffer) {
try {
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
FaweOutputStream fos = new FaweOutputStream(baos);
fos.writeInt(this.chunk.getX());
fos.writeInt(this.chunk.getZ());
fos.writeBoolean(this.full);
fos.writeVarInt(this.chunk.getBitMask()); // writeVarInt
FastByteArrayOutputStream sectionByteArray = new FastByteArrayOutputStream(buffer);
FaweOutputStream sectionWriter = new FaweOutputStream(sectionByteArray);
byte[][] ids = chunk.ids;
for (int layer = 0; layer < ids.length; layer++) {
byte[] layerIds = ids[layer];
if (layerIds == null) {
continue;
}
byte[] layerData = chunk.data[layer];
int num = 13;
sectionWriter.write(num); // num blocks, anything > 8 - doesn't need to be accurate
sectionWriter.writeVarInt(0); // varint 0 - data palette global
BitArray bits = new BitArray(num, 4096);
bits.setAt(0, 0);
for (int i = 0; i < 4096; i++) {
int id = layerIds[i] & 0xFF;
if (id != 0) {
int data = FaweCache.hasData(id) ? chunk.getNibble(i, layerData) : 0;
int combined = FaweCache.getCombined(id, data);
bits.setAt(i, combined);
}
}
sectionWriter.write(bits.getBackingLongArray());
sectionWriter.write(chunk.blockLight[layer]);
if (sky) {
sectionWriter.write(chunk.skyLight[layer]);
}
}
if (this.biomes && chunk.biomes != null) {
sectionWriter.write(chunk.biomes);
}
fos.writeVarInt(sectionByteArray.getSize());
for (byte[] arr : sectionByteArray.toByteArrays()) {
fos.write(arr);
}
fos.writeVarInt(0);
fos.close();
sectionWriter.close();
return baos.toByteArray();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}

View File

@ -517,11 +517,11 @@ public class BukkitQueue17 extends BukkitQueue_0<net.minecraft.server.v1_7_R4.Ch
for (EntityPlayer player : players) {
int currentVersion = player.playerConnection.networkManager.getVersion();
if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, true, 65280, currentVersion);
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, false, 65280, currentVersion);
player.playerConnection.sendPacket(packet);
mask = 255;
}
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, true, mask, currentVersion);
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, false, mask, currentVersion);
player.playerConnection.sendPacket(packet);
}
if (empty) {

View File

@ -5,7 +5,7 @@ import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.HasFaweQueue;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.DelegateFaweQueue;
import com.boydti.fawe.object.queue.DelegateFaweQueue;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.TaskManager;

View File

@ -6,6 +6,7 @@ authors: [Empire92]
loadbefore: [WorldEdit,AsyncWorldEdit,AsyncWorldEditInjector]
load: STARTUP
database: false
softdepend: [ProtocolLib]
#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones]
commands:
fcancel:

View File

@ -1,15 +1,19 @@
package com.boydti.fawe.command;
import com.boydti.fawe.config.Commands;
import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.changeset.CFIChangeSet;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.MethodCommands;
import com.sk89q.worldedit.util.command.SimpleDispatcher;
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
import java.io.IOException;
public class CFICommand extends MethodCommands {
@ -32,9 +36,20 @@ public class CFICommand extends MethodCommands {
desc = "Start CreateFromImage"
)
@CommandPermissions("worldedit.anvil.cfi")
public void cfi(FawePlayer fp, CommandContext context) throws CommandException {
public void cfi(FawePlayer fp, CommandContext context) throws CommandException, IOException {
CFICommands.CFISettings settings = child.getSettings(fp);
settings.popMessages(fp);
dispatch(fp, settings, context);
HeightMapMCAGenerator gen = settings.getGenerator();
if (gen != null && gen.isModified()) {
gen.update();
CFIChangeSet set = new CFIChangeSet(gen, fp.getUUID());
LocalSession session = fp.getSession();
session.remember(fp.getPlayer(), gen, set, fp.getLimit());
}
}
private void dispatch(FawePlayer fp, CFICommands.CFISettings settings, CommandContext context) throws CommandException {
if (!settings.hasGenerator()) {
switch (context.argsLength()) {
case 0: {

View File

@ -34,11 +34,13 @@ import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.EmptyClipboardException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.MethodCommands;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
@ -64,6 +66,7 @@ import java.net.URL;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import javax.imageio.ImageIO;
@Command(aliases = {"/cfi"}, desc = "Create a world from images: [More Info](https://git.io/v5iDy)")
@ -81,6 +84,10 @@ public class CFICommands extends MethodCommands {
this.dispathcer= dispatcher;
}
private File getFolder(String worldName) {
return new File(PS.imp().getWorldContainer(), worldName + File.separator + "region");
}
@Command(
aliases = {"heightmap"},
usage = "<url>",
@ -88,7 +95,7 @@ public class CFICommands extends MethodCommands {
)
@CommandPermissions("worldedit.anvil.cfi")
public void heightmap(FawePlayer fp, BufferedImage image) {
HeightMapMCAGenerator generator = new HeightMapMCAGenerator(image, null);
HeightMapMCAGenerator generator = new HeightMapMCAGenerator(image, getFolder("CFI-" + UUID.randomUUID()));
setup(generator, fp);
}
@ -99,14 +106,16 @@ public class CFICommands extends MethodCommands {
)
@CommandPermissions("worldedit.anvil.cfi")
public void heightmap(FawePlayer fp, int width, int length) {
HeightMapMCAGenerator generator = new HeightMapMCAGenerator(width, length, null);
HeightMapMCAGenerator generator = new HeightMapMCAGenerator(width, length, getFolder("CFI-" + UUID.randomUUID()));
setup(generator, fp);
}
private void setup(HeightMapMCAGenerator generator, FawePlayer fp) {
CFISettings settings = getSettings(fp);
settings.remove().setGenerator(generator).bind();
generator.setPacketViewer(fp);
generator.setImageViewer(Fawe.imp().getImageViewer(fp));
generator.update();
mainMenu(fp);
}
@ -202,12 +211,14 @@ public class CFICommands extends MethodCommands {
});
if (plot == null) return;
File folder = new File(PS.imp().getWorldContainer(), plot.getWorldName() + File.separator + "region");
File folder = getFolder(plot.getWorldName());
HeightMapMCAGenerator generator = settings.getGenerator();
generator.setFolder(folder);
fp.sendMessage(BBC.getPrefix() + "Generating");
generator.generate();
generator.setPacketViewer(null);
generator.setImageViewer(null);
settings.remove();
fp.sendMessage(BBC.getPrefix() + "Done!");
TaskManager.IMP.sync(new RunnableVal<Object>() {
@ -555,6 +566,60 @@ public class CFICommands extends MethodCommands {
component(fp);
}
@Command(
aliases = {"baseid", "bedrockid"},
usage = "<block>",
desc = "Change the block used for the base\n" +
"e.g. Bedrock"
)
@CommandPermissions("worldedit.anvil.cfi")
public void baseId(FawePlayer fp, BaseBlock block) throws ParameterException, WorldEditException {
CFISettings settings = assertSettings(fp);
settings.getGenerator().setBedrockId(block.getId());
msg("Set base id!").send(fp);
settings.resetComponent();
component(fp);
}
@Command(
aliases = {"thickness", "width", "floorthickness"},
usage = "<height>",
desc = "Set the thickness of the generated world from the floor\n" +
" - A value of 0 is the default and will only set the top block"
)
@CommandPermissions("worldedit.anvil.cfi")
public void floorthickness(FawePlayer fp, int height) throws ParameterException, WorldEditException {
assertSettings(fp).getGenerator().setFloorThickness(height);
msg("Set world thickness!").send(fp);
component(fp);
}
@Command(
aliases = {"update", "refresh", "resend"},
desc = "Resend the CFI chunks"
)
@CommandPermissions("worldedit.anvil.cfi")
public void update(FawePlayer fp) throws ParameterException, WorldEditException {
assertSettings(fp).getGenerator().update();
msg("Chunks refreshed!").send(fp);
mainMenu(fp);
}
@Command(
aliases = {"tp", "visit", "home"},
desc = "Teleport to the CFI virtual world"
)
@CommandPermissions("worldedit.anvil.cfi")
public void tp(FawePlayer fp) throws ParameterException, WorldEditException {
HeightMapMCAGenerator gen = assertSettings(fp).getGenerator();
msg("Teleporting...").send(fp);
Vector origin = gen.getOrigin();
Player player = fp.getPlayer();
player.setPosition(origin.subtract(16, 0, 16));
player.findFreePosition();
mainMenu(fp);
}
@Command(
aliases = {"waterheight", "sealevel", "setwaterheight"},
usage = "<height>",
@ -565,7 +630,7 @@ public class CFICommands extends MethodCommands {
@CommandPermissions("worldedit.anvil.cfi")
public void waterheight(FawePlayer fp, int height) throws ParameterException, WorldEditException {
assertSettings(fp).getGenerator().setWaterHeight(height);
msg("Set height!").send(fp);
msg("Set water height!").send(fp);
component(fp);
}
@ -877,6 +942,8 @@ public class CFICommands extends MethodCommands {
.newline()
.text("&7[&aWaterHeight&7]").suggestTip(alias() + " " + alias("waterheight") + " 60").text(" - Sea level for whole map")
.newline()
.text("&7[&aFloorThickness&7]").suggestTip(alias() + " " + alias("floorthickness") + " 60").text(" - Floor thickness of entire map")
.newline()
.text("&7[&aSnow&7]").suggestTip(alias() + " " + alias("snow") + maskArgs).text(" - Set snow in the masked areas")
.newline();
@ -884,6 +951,7 @@ public class CFICommands extends MethodCommands {
String disabled = "You must specify a pattern";
msg
.text("&7[&cWaterId&7]").tooltip(disabled).newline()
.text("&7[&cBedrockId&7]").tooltip(disabled).newline()
.text("&7[&cFloor&7]").tooltip(disabled).newline()
.text("&7[&cMain&7]").tooltip(disabled).newline()
.text("&7[&cColumn&7]").tooltip(disabled).newline()
@ -894,6 +962,7 @@ public class CFICommands extends MethodCommands {
msg
.text("&7[&aWaterId&7]").cmdTip(alias() + " waterId " + pattern).text(" - Water id for whole map").newline()
.text("&7[&aBedrockId&7]").cmdTip(alias() + " baseId " + pattern).text(" - Bedrock id for whole map").newline()
.text("&7[&aFloor&7]").cmdTip(alias() + " floor" + compArgs).text(" - Set the floor in the masked areas").newline()
.text("&7[&aMain&7]").cmdTip(alias() + " main" + compArgs).text(" - Set the main block in the masked areas").newline()
.text("&7[&aColumn&7]").cmdTip(alias() + " column" + compArgs).text(" - Set the columns in the masked areas").newline()
@ -1012,8 +1081,14 @@ public class CFICommands extends MethodCommands {
}
public CFISettings remove() {
popMessages(fp);
fp.deleteMeta("CFISettings");
HeightMapMCAGenerator gen = this.generator;
if (gen != null) {
gen.close();
LocalSession session = fp.getSession();
session.clearHistory();
}
popMessages(fp);
generator = null;
image = null;
imageArg = null;

View File

@ -7,7 +7,6 @@ import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.util.SetQueue;
import com.sk89q.worldedit.EditSession;
import java.util.Collection;
import java.util.Set;
import java.util.UUID;
public class Cancel extends FaweCommand {
@ -26,7 +25,7 @@ public class Cancel extends FaweCommand {
int cancelled = 0;
player.clearActions();
for (FaweQueue queue : queues) {
Set<EditSession> sessions = queue.getEditSessions();
Collection<EditSession> sessions = queue.getEditSessions();
for (EditSession session : sessions) {
FawePlayer currentPlayer = session.getPlayer();
if (currentPlayer == player) {

View File

@ -290,7 +290,9 @@ public class Settings extends Config {
}
@Comment({
"Experimental options, use at your own risk"
"Experimental options, use at your own risk",
" - UNSAFE = Can cause permanent damage to the server",
" - SAFE = Can be buggy but unlikely to cause any damage"
})
public static class EXPERIMENTAL {
@Comment({
@ -307,11 +309,11 @@ public class Settings extends Config {
})
public boolean DYNAMIC_CHUNK_RENDERING = false;
@Comment({
"Allows brushes to be persistent",
"[SAFE] Allows brushes to be persistent",
})
public boolean PERSISTENT_BRUSHES = false;
@Comment({
"Enable CUI without needing the mod installed (Requires ProtocolLib)",
"[SAFE] Enable CUI without needing the mod installed (Requires ProtocolLib)",
})
public boolean VANILLA_CUI = false;

View File

@ -1,12 +1,14 @@
package com.boydti.fawe.example;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.IntegerPair;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.extent.LightingExtent;
import com.boydti.fawe.util.MainUtil;
@ -14,17 +16,20 @@ import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.HashSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> extends FaweQueue implements LightingExtent {
public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> implements LightingExtent, FaweQueue {
private WORLD impWorld;
@ -37,6 +42,17 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> exte
public CHUNKSECTIONS lastChunkSections;
public SECTION lastSection;
private World weWorld;
private String world;
private ConcurrentLinkedDeque<EditSession> sessions;
private long modified = System.currentTimeMillis();
private RunnableVal2<FaweChunk, FaweChunk> changeTask;
private RunnableVal2<ProgressType, Integer> progressTask;
private SetQueue.QueueStage stage;
private Settings settings = Settings.IMP;
public ConcurrentLinkedDeque<Runnable> tasks = new ConcurrentLinkedDeque<>();
private CHUNK cachedLoadChunk;
public final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
@ -55,12 +71,12 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> exte
}
public MappedFaweQueue(final String world) {
super(world);
this.world = world;
map = Settings.IMP.PREVENT_CRASHES ? new WeakFaweQueueMap(this) : new DefaultFaweQueueMap(this);
}
public MappedFaweQueue(final String world, IFaweQueueMap map) {
super(world);
this.world = world;
if (map == null) {
map = Settings.IMP.PREVENT_CRASHES ? new WeakFaweQueueMap(this) : new DefaultFaweQueueMap(this);
}
@ -68,13 +84,19 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> exte
}
public MappedFaweQueue(final World world, IFaweQueueMap map) {
super(world);
this.weWorld = world;
if (world != null) this.world = Fawe.imp().getWorldName(world);
if (map == null) {
map = Settings.IMP.PREVENT_CRASHES ? new WeakFaweQueueMap(this) : new DefaultFaweQueueMap(this);
}
this.map = map;
}
@Override
public int getMaxY() {
return weWorld == null ? 255 : weWorld.getMaxY();
}
public IFaweQueueMap getFaweQueueMap() {
return map;
}
@ -212,7 +234,26 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> exte
@Override
public void runTasks() {
super.runTasks();
synchronized (this) {
this.notifyAll();
}
if (getProgressTask() != null) {
try {
getProgressTask().run(ProgressType.DONE, 1);
} catch (Throwable e) {
e.printStackTrace();
}
}
while (!tasks.isEmpty()) {
Runnable task = tasks.poll();
if (task != null) {
try {
task.run();
} catch (Throwable e) {
MainUtil.handleError(e);
}
}
}
if (getProgressTask() != null) {
try {
getProgressTask().run(ProgressType.DONE, 1);
@ -231,6 +272,94 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> exte
}
}
public Settings getSettings() {
return settings;
}
public void setSettings(Settings settings) {
this.settings = settings == null ? Settings.IMP : settings;
}
public void setWorld(String world) {
this.world = world;
this.weWorld = null;
}
public World getWEWorld() {
return weWorld != null ? weWorld : (weWorld = FaweAPI.getWorld(world));
}
public String getWorldName() {
return world;
}
@Override
public Collection<EditSession> getEditSessions() {
Collection<EditSession> tmp = sessions;
if (tmp == null) tmp = new HashSet<>();
return tmp;
}
@Override
public void addEditSession(EditSession session) {
ConcurrentLinkedDeque<EditSession> tmp = sessions;
if (tmp == null) tmp = new ConcurrentLinkedDeque<>();
tmp.add(session);
this.sessions = tmp;
}
@Override
public boolean supports(Capability capability) {
switch (capability) {
case CHANGE_TASKS: return true;
}
return false;
}
public void setSessions(ConcurrentLinkedDeque<EditSession> sessions) {
this.sessions = sessions;
}
public long getModified() {
return modified;
}
public void setModified(long modified) {
this.modified = modified;
}
public RunnableVal2<ProgressType, Integer> getProgressTask() {
return progressTask;
}
public void setProgressTask(RunnableVal2<ProgressType, Integer> progressTask) {
this.progressTask = progressTask;
}
public void setChangeTask(RunnableVal2<FaweChunk, FaweChunk> changeTask) {
this.changeTask = changeTask;
}
public RunnableVal2<FaweChunk, FaweChunk> getChangeTask() {
return changeTask;
}
public SetQueue.QueueStage getStage() {
return stage;
}
public void setStage(SetQueue.QueueStage stage) {
this.stage = stage;
}
public void addNotifyTask(Runnable runnable) {
this.tasks.add(runnable);
}
public void addTask(Runnable whenFree) {
tasks.add(whenFree);
}
@Override
public int size() {
int size = map.size();
@ -262,6 +391,15 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> exte
public abstract int getCombinedId4Data(SECTION section, int x, int y, int z);
public int getLocalCombinedId4Data(CHUNK chunk, int x, int y, int z) {
CHUNKSECTIONS sections = getSections(lastChunk);
SECTION section = getCachedSection(sections, y >> 4);
if (section == null) {
return 0;
}
return getCombinedId4Data(lastSection, x, y, z);
}
public abstract int getBiome(CHUNK chunk, int x, int z);
public abstract CompoundTag getTileEntity(CHUNK chunk, int x, int y, int z);
@ -299,6 +437,23 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, CHUNKSECTIONS, SECTION> exte
return false;
}
public boolean queueChunkLoad(final int cx, final int cz, RunnableVal<CHUNK> operation) {
operation.value = getCachedChunk(getWorld(), cx, cz);
if (operation.value == null) {
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
operation.value = loadChunk(getWorld(), cx, cz, true);
if (operation.value != null) TaskManager.IMP.async(operation);
}
});
return true;
} else {
TaskManager.IMP.async(operation);
}
return false;
}
@Override
public boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException {
int cx = x >> 4;

View File

@ -0,0 +1,40 @@
package com.boydti.fawe.example;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.util.MainUtil;
public class SimpleCharFaweChunk extends CharFaweChunk {
public SimpleCharFaweChunk(FaweQueue parent, int x, int z) {
super(parent, x, z);
}
public SimpleCharFaweChunk(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
super(parent, x, z, ids, count, air, heightMap);
}
@Override
public Object getNewChunk() {
return this;
}
@Override
public CharFaweChunk copy(boolean shallow) {
SimpleCharFaweChunk copy;
if (shallow) {
copy = new SimpleCharFaweChunk(getParent(), getX(), getZ(), ids, count, air, heightMap);
copy.biomes = biomes;
} else {
copy = new SimpleCharFaweChunk(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
copy.biomes = biomes.clone();
}
return copy;
}
@Override
public FaweChunk call() {
getParent().setChunk(this);
return this;
}
}

View File

@ -27,11 +27,12 @@ public final class HeightMapMCADrawer {
public BufferedImage draw() {
BufferedImage img = new BufferedImage(gen.getWidth(), gen.getLength(), BufferedImage.TYPE_INT_RGB);
final char[] overlay = gen.overlay == null ? gen.floor : gen.overlay;
final char[] floor = gen.floor;
final char[] main = gen.main;
final byte[] heights = gen.heights;
final int waterHeight = gen.waterHeight;
final char[] overlay = gen.overlay == null ? gen.floor.get() : gen.overlay.get();
final char[] floor = gen.floor.get();
final char[] main = gen.main.get();
final byte[] heights = gen.heights.get();
final byte[] biomes = gen.biomes.get();
final int waterHeight = gen.primtives.waterHeight;
final int width = gen.getWidth();
final int length = gen.getLength();
@ -58,7 +59,7 @@ public final class HeightMapMCADrawer {
int color;
switch (combined >> 4) {
case 2:
color = getAverageBiomeColor(gen.biomes, width, index);
color = getAverageBiomeColor(biomes, width, index);
break;
case 78:
color = (0xDD << 16) + (0xDD << 8) + (0xDD << 0);
@ -76,7 +77,7 @@ public final class HeightMapMCADrawer {
color = (r << 16) + (g << 8) + (b << 0);
}
if (height + 1 < waterHeight) {
byte waterId = gen.waterId;
byte waterId = gen.primtives.waterId;
int waterColor = 0;
switch (waterId) {
case BlockID.WATER:

View File

@ -619,6 +619,14 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
});
}
@Override
public boolean supports(Capability capability) {
switch (capability) {
case CHANGE_TASKS: return false;
}
return super.supports(capability);
}
@Override
public void relight(int x, int y, int z) {
throw new UnsupportedOperationException("Not supported");
@ -819,4 +827,4 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
parentNMS.sendBlockUpdate(chunk, players);
}
}
}
}

View File

@ -2,7 +2,7 @@ package com.boydti.fawe.object;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.util.DelegateFaweQueue;
import com.boydti.fawe.object.queue.DelegateFaweQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.biome.BaseBiome;

View File

@ -19,7 +19,7 @@ public abstract class FaweChunk<T> implements Callable<FaweChunk> {
private int x, z;
public static int HEIGHT = 256;
private final ArrayDeque<Runnable> tasks = new ArrayDeque<Runnable>();
private final ArrayDeque<Runnable> tasks = new ArrayDeque<Runnable>(0);
/**
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
@ -154,6 +154,14 @@ public abstract class FaweChunk<T> implements Callable<FaweChunk> {
return ids;
}
public byte[][] getBlockLightArray() {
return null;
}
public byte[][] getSkyLightArray() {
return null;
}
public abstract byte[] getBiomeArray();
public void forEachQueuedBlock(FaweChunkVisitor onEach) {

View File

@ -42,6 +42,28 @@ public class FaweInputStream extends DataInputStream {
return nbtIn.readNamedTag();
}
public Object readPrimitive(Class<?> clazz) throws IOException {
if (clazz == long.class || clazz == Long.class) {
return readLong();
} else if (clazz == double.class || clazz == Double.class) {
return readDouble();
} else if (clazz == float.class || clazz == Float.class) {
return readFloat();
} else if (clazz == int.class || clazz == Integer.class) {
return readInt();
} else if (clazz == short.class || clazz == Short.class) {
return readShort();
} else if (clazz == char.class || clazz == Character.class) {
return readChar();
} else if (clazz == byte.class || clazz == Byte.class) {
return readByte();
} else if (clazz == boolean.class || clazz == Boolean.class) {
return readBoolean();
} else {
throw new UnsupportedOperationException("Unknown class " + clazz);
}
}
public int readVarInt() throws IOException {
int i = 0;
int offset = 0;

View File

@ -61,6 +61,29 @@ public class FaweOutputStream extends DataOutputStream {
nbtOut.writeNamedTag(name, tag);
}
public void writePrimitive(Object value) throws IOException {
Class<? extends Object> clazz = value.getClass();
if (clazz == long.class || clazz == Long.class) {
writeLong((long) value);
} else if (clazz == double.class || clazz == Double.class) {
writeDouble((double) value);
} else if (clazz == float.class || clazz == Float.class) {
writeFloat((float) value);
} else if (clazz == int.class || clazz == Integer.class) {
writeInt((int) value);
} else if (clazz == short.class || clazz == Short.class) {
writeShort((short) value);
} else if (clazz == char.class || clazz == Character.class) {
writeChar((char) value);
} else if (clazz == byte.class || clazz == Byte.class) {
writeByte((byte) value);
} else if (clazz == boolean.class || clazz == Boolean.class) {
writeBoolean((boolean) value);
} else {
throw new UnsupportedOperationException("Unknown class " + clazz);
}
}
@Override
public void close() throws IOException {
if (nbtOut != null) {

View File

@ -2,11 +2,14 @@ package com.boydti.fawe.object;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.command.CFICommands;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.regions.FaweMaskManager;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
@ -26,7 +29,10 @@ import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.CommandManager;
import com.sk89q.worldedit.extension.platform.PlatformManager;
import com.sk89q.worldedit.extension.platform.PlayerProxy;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
@ -39,9 +45,9 @@ import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
@ -350,8 +356,21 @@ public abstract class FawePlayer<T> extends Metadatable {
return FaweAPI.getWorld(getLocation().world);
}
public FaweQueue getFaweQueue(boolean autoQueue) {
return getFaweQueue(true, autoQueue);
}
public FaweQueue getFaweQueue(boolean fast, boolean autoQueue) {
CFICommands.CFISettings settings = this.getMeta("CFISettings");
if (settings != null && settings.hasGenerator()) {
return settings.getGenerator();
} else {
return SetQueue.IMP.getNewQueue(getWorld(), true, autoQueue);
}
}
public FaweQueue getMaskedFaweQueue(boolean autoQueue) {
FaweQueue queue = SetQueue.IMP.getNewQueue(getWorld(), true, autoQueue);
FaweQueue queue = getFaweQueue(autoQueue);
RegionWrapper[] allowedRegions = getCurrentRegions();
if (allowedRegions.length == 1 && allowedRegions[0].isGlobal()) {
return queue;
@ -574,7 +593,43 @@ public abstract class FawePlayer<T> extends Metadatable {
* Get a new EditSession from this player
*/
public EditSession getNewEditSession() {
return WorldEdit.getInstance().getEditSessionFactory().getEditSession(getWorld(), -1, toWorldEditPlayer());
return new EditSessionBuilder(getWorld()).player(this).build();
}
/**
* Get the World the player is editing in (may not match the world they are in)<br/>
* - e.g. If they are editing a CFI world.<br/>
* @return Editing world
*/
public World getWorldForEditing() {
CFICommands.CFISettings cfi = getMeta("CFISettings");
if (cfi != null && cfi.hasGenerator() && cfi.getGenerator().hasPacketViewer()) {
return cfi.getGenerator();
}
return WorldEdit.getInstance().getPlatformManager().getWorldForEditing(getWorld());
}
public PlayerProxy createProxy() {
Player player = getPlayer();
World world = getWorldForEditing();
PlatformManager platformManager = WorldEdit.getInstance().getPlatformManager();
Player permActor = platformManager.queryCapability(Capability.PERMISSIONS).matchPlayer(player);
if (permActor == null) {
permActor = player;
}
Player cuiActor = platformManager.queryCapability(Capability.WORLDEDIT_CUI).matchPlayer(player);
if (cuiActor == null) {
cuiActor = player;
}
PlayerProxy proxy = new PlayerProxy(player, permActor, cuiActor, world);
if (world instanceof HeightMapMCAGenerator) {
proxy.setOffset(Vector.ZERO.subtract(((HeightMapMCAGenerator) world).getOrigin()));
}
return proxy;
}
@ -589,7 +644,7 @@ public abstract class FawePlayer<T> extends Metadatable {
Map<EditSession, SetQueue.QueueStage> map = new ConcurrentHashMap<>(8, 0.9f, 1);
if (requiredStage == null || requiredStage == SetQueue.QueueStage.ACTIVE) {
for (FaweQueue queue : SetQueue.IMP.getActiveQueues()) {
Set<EditSession> sessions = queue.getEditSessions();
Collection<EditSession> sessions = queue.getEditSessions();
for (EditSession session : sessions) {
FawePlayer currentPlayer = session.getPlayer();
if (currentPlayer == this) {
@ -600,7 +655,7 @@ public abstract class FawePlayer<T> extends Metadatable {
}
if (requiredStage == null || requiredStage == SetQueue.QueueStage.INACTIVE) {
for (FaweQueue queue : SetQueue.IMP.getInactiveQueues()) {
Set<EditSession> sessions = queue.getEditSessions();
Collection<EditSession> sessions = queue.getEditSessions();
for (EditSession session : sessions) {
FawePlayer currentPlayer = session.getPlayer();
if (currentPlayer == this) {

View File

@ -1,7 +1,6 @@
package com.boydti.fawe.object;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
@ -27,50 +26,51 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedDeque;
import javax.annotation.Nullable;
public abstract class FaweQueue implements HasFaweQueue, Extent {
/**
* A queue based Extent capable of queing chunk and region changes
*/
public interface FaweQueue extends HasFaweQueue, Extent {
private World weWorld;
private String world;
private ConcurrentLinkedDeque<EditSession> sessions;
private long modified = System.currentTimeMillis();
private RunnableVal2<FaweChunk, FaweChunk> changeTask;
private RunnableVal2<ProgressType, Integer> progressTask;
private SetQueue.QueueStage stage;
private Settings settings = Settings.IMP;
public FaweQueue(String world) {
this.world = world;
enum ProgressType {
QUEUE,
DISPATCH,
DONE,
}
public FaweQueue(World world) {
if (world != null) {
this.weWorld = world;
this.world = Fawe.imp().getWorldName(world);
}
enum RelightMode {
NONE,
OPTIMAL,
ALL,
}
public Relighter getRelighter() {
enum Capability {
// If history can be recorded in an async task by the dispatcher
CHANGE_TASKS,
// If custom chunk packets can be sent
CHUNK_PACKETS
//
}
default Relighter getRelighter() {
return NullRelighter.INSTANCE;
}
@Override
public Vector getMinimumPoint() {
default Vector getMinimumPoint() {
return new Vector(-30000000, 0, -30000000);
}
@Override
public Vector getMaximumPoint() {
default Vector getMaximumPoint() {
return new Vector(30000000, getMaxY(), 30000000);
}
@Override
public BaseBlock getLazyBlock(int x, int y, int z) {
default BaseBlock getLazyBlock(int x, int y, int z) {
int combinedId4Data = getCachedCombinedId4Data(x, y, z, 0);
int id = FaweCache.getId(combinedId4Data);
if (!FaweCache.hasNBT(id)) {
@ -90,76 +90,43 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
}
@Override
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
default boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
return setBlock(x, y, z, block.getId(), block.getData(), block.getNbtData());
}
@Override
public BaseBlock getBlock(Vector position) {
default BaseBlock getBlock(Vector position) {
return getLazyBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ());
}
@Override
public BaseBiome getBiome(Vector2D position) {
default BaseBiome getBiome(Vector2D position) {
return null;
}
@Override
public boolean setBlock(Vector position, BaseBlock block) throws WorldEditException {
default boolean setBlock(Vector position, BaseBlock block) throws WorldEditException {
return setBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ(), block);
}
@Override
public boolean setBiome(Vector2D position, BaseBiome biome) {
default boolean setBiome(Vector2D position, BaseBiome biome) {
return setBiome(position.getBlockX(), position.getBlockZ(), biome);
}
public enum ProgressType {
QUEUE,
DISPATCH,
DONE,
}
public enum RelightMode {
NONE,
OPTIMAL,
ALL,
}
@Override
public FaweQueue getQueue() {
default FaweQueue getQueue() {
return this;
}
public Settings getSettings() {
return settings;
}
public void setSettings(Settings settings) {
this.settings = settings == null ? Settings.IMP : settings;
}
public void setWorld(String world) {
this.world = world;
this.weWorld = null;
}
public void addEditSession(EditSession session) {
default void addEditSession(EditSession session) {
if (session == null) {
return;
}
if (this.getSessions() == null) {
setSessions(new ConcurrentLinkedDeque<EditSession>());
}
getSessions().add(session);
}
public World getWEWorld() {
return weWorld != null ? weWorld : (weWorld = FaweAPI.getWorld(world));
}
public String getWorldName() {
return world;
Collection<EditSession> sessions = getEditSessions();
sessions.add(session);
}
/**
@ -169,54 +136,21 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
*
* @param progressTask
*/
public void setProgressTracker(RunnableVal2<ProgressType, Integer> progressTask) {
default void setProgressTracker(RunnableVal2<ProgressType, Integer> progressTask) {
this.setProgressTask(progressTask);
}
public Set<EditSession> getEditSessions() {
return getSessions() == null ? new HashSet<EditSession>() : new HashSet<>(getSessions());
default Collection<EditSession> getEditSessions() {
return Collections.emptySet();
}
public ConcurrentLinkedDeque<EditSession> getSessions() {
return sessions;
default boolean supports(Capability capability) {
return false;
}
public void setSessions(ConcurrentLinkedDeque<EditSession> sessions) {
this.sessions = sessions;
}
default void optimize() {}
public long getModified() {
return modified;
}
public void setModified(long modified) {
this.modified = modified;
}
public RunnableVal2<ProgressType, Integer> getProgressTask() {
return progressTask;
}
public void setProgressTask(RunnableVal2<ProgressType, Integer> progressTask) {
this.progressTask = progressTask;
}
public boolean supportsChangeTask() {
return true;
}
public void setChangeTask(RunnableVal2<FaweChunk, FaweChunk> changeTask) {
this.changeTask = changeTask;
}
public RunnableVal2<FaweChunk, FaweChunk> getChangeTask() {
return changeTask;
}
public void optimize() {
}
public int setBlocks(CuboidRegion cuboid, final int id, final int data) {
default int setBlocks(CuboidRegion cuboid, final int id, final int data) {
RegionWrapper current = new RegionWrapper(cuboid.getMinimumPoint(), cuboid.getMaximumPoint());
final int minY = cuboid.getMinimumY();
final int maxY = cuboid.getMaximumY();
@ -258,13 +192,13 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
return cuboid.getArea();
}
public abstract boolean setBlock(final int x, final int y, final int z, final int id, final int data);
boolean setBlock(final int x, final int y, final int z, final int id, final int data);
public boolean setBlock(int x, int y, int z, int id) {
default boolean setBlock(int x, int y, int z, int id) {
return setBlock(x, y, z, id, 0);
}
public boolean setBlock(int x, int y, int z, int id, int data, CompoundTag nbt) {
default boolean setBlock(int x, int y, int z, int id, int data, CompoundTag nbt) {
if (nbt != null) {
if (setBlock(x, y, z, id, data)) {
MainUtil.setPosition(nbt, x, y, z);
@ -277,32 +211,69 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
}
}
public abstract void setTile(int x, int y, int z, CompoundTag tag);
void setTile(int x, int y, int z, CompoundTag tag);
public abstract void setEntity(int x, int y, int z, CompoundTag tag);
void setEntity(int x, int y, int z, CompoundTag tag);
public abstract void removeEntity(int x, int y, int z, UUID uuid);
void removeEntity(int x, int y, int z, UUID uuid);
public abstract boolean setBiome(final int x, final int z, final BaseBiome biome);
boolean setBiome(final int x, final int z, final BaseBiome biome);
public abstract FaweChunk getFaweChunk(int x, int z);
FaweChunk getFaweChunk(int x, int z);
public abstract Collection<FaweChunk> getFaweChunks();
Collection<FaweChunk> getFaweChunks();
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean save, boolean load) {
default boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean save, boolean load) {
if (whileLocked != null) whileLocked.run();
return true;
}
public abstract void setChunk(final FaweChunk chunk);
void setChunk(final FaweChunk chunk);
public abstract File getSaveFolder();
File getSaveFolder();
public int getMaxY() {
default int getMaxY() {
World weWorld = getWEWorld();
return weWorld == null ? 255 : weWorld.getMaxY();
}
public void forEachBlockInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
default Settings getSettings() {
return Settings.IMP;
}
default void setSettings(Settings settings) {
}
void setWorld(String world);
World getWEWorld();
String getWorldName();
long getModified();
void setModified(long modified);
RunnableVal2<ProgressType, Integer> getProgressTask();
void setProgressTask(RunnableVal2<ProgressType, Integer> progressTask);
void setChangeTask(RunnableVal2<FaweChunk, FaweChunk> changeTask);
RunnableVal2<FaweChunk, FaweChunk> getChangeTask();
SetQueue.QueueStage getStage();
void setStage(SetQueue.QueueStage stage);
void addNotifyTask(Runnable runnable);
void runTasks();
void addTask(Runnable whenFree);
default void forEachBlockInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
int bx = cx << 4;
int bz = cz << 4;
MutableBlockVector mutable = new MutableBlockVector(0, 0, 0);
@ -331,7 +302,7 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
}
}
public void forEachTileInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
default void forEachTileInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
int bx = cx << 4;
int bz = cz << 4;
MutableBlockVector mutable = new MutableBlockVector(0, 0, 0);
@ -359,22 +330,22 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
}
@Deprecated
public boolean regenerateChunk(int x, int z) {
default boolean regenerateChunk(int x, int z) {
return regenerateChunk(x, z, null, null);
}
public abstract boolean regenerateChunk(int x, int z, @Nullable BaseBiome biome, @Nullable Long seed);
boolean regenerateChunk(int x, int z, @Nullable BaseBiome biome, @Nullable Long seed);
public void startSet(boolean parallel) {
default void startSet(boolean parallel) {
}
public void endSet(boolean parallel) {
default void endSet(boolean parallel) {
}
public int cancel() {
default int cancel() {
clear();
int count = 0;
for (EditSession session : getSessions()) {
for (EditSession session : getEditSessions()) {
if (session.cancel()) {
count++;
}
@ -382,10 +353,14 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
return count;
}
public abstract void sendBlockUpdate(FaweChunk chunk, FawePlayer... players);
void sendBlockUpdate(FaweChunk chunk, FawePlayer... players);
default void sendChunkUpdate(FaweChunk chunk, FawePlayer... players) {
sendBlockUpdate(chunk, players);
}
@Deprecated
public boolean next() {
default boolean next() {
int amount = Settings.IMP.QUEUE.PARALLEL_THREADS;
long time = 20; // 30ms
return next(amount, time);
@ -396,9 +371,9 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
*
* @return
*/
public abstract boolean next(int amount, long time);
boolean next(int amount, long time);
public void saveMemory() {
default void saveMemory() {
MainUtil.sendAdmin(BBC.OOM.s());
// Set memory limited
MemUtil.memoryLimitedTask();
@ -411,28 +386,28 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
// Unload chunks
}
public abstract void sendChunk(FaweChunk chunk);
void sendChunk(FaweChunk chunk);
public abstract void sendChunk(int x, int z, int bitMask);
void sendChunk(int x, int z, int bitMask);
/**
* This method is called when the server is < 1% available memory
*/
public abstract void clear();
void clear();
public abstract void addNotifyTask(int x, int z, Runnable runnable);
void addNotifyTask(int x, int z, Runnable runnable);
public boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException {
default boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException {
return getCombinedId4Data(x, y, z) != 0;
}
public abstract int getBiomeId(int x, int z) throws FaweException.FaweChunkLoadException;
int getBiomeId(int x, int z) throws FaweException.FaweChunkLoadException;
public abstract int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException;
int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException;
public abstract int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException;
int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException;
public int getAdjacentLight(int x, int y, int z) {
default int getAdjacentLight(int x, int y, int z) {
int light = 0;
if ((light = Math.max(light, getSkyLight(x - 1, y, z))) == 15) {
return light;
@ -446,22 +421,22 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
return Math.max(light, getSkyLight(x, y, z + 1));
}
public abstract boolean hasSky();
boolean hasSky();
public abstract int getSkyLight(int x, int y, int z);
int getSkyLight(int x, int y, int z);
public int getLight(int x, int y, int z) {
default int getLight(int x, int y, int z) {
if (!hasSky()) {
return getEmmittedLight(x, y, z);
}
return Math.max(getSkyLight(x, y, z), getEmmittedLight(x, y, z));
}
public abstract int getEmmittedLight(int x, int y, int z);
int getEmmittedLight(int x, int y, int z);
public abstract CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException;
CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException;
public int getCombinedId4Data(int x, int y, int z, int def) {
default int getCombinedId4Data(int x, int y, int z, int def) {
try {
return getCombinedId4Data(x, y, z);
} catch (FaweException ignore) {
@ -469,7 +444,7 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
}
}
public int getCachedCombinedId4Data(int x, int y, int z, int def) {
default int getCachedCombinedId4Data(int x, int y, int z, int def) {
try {
return getCachedCombinedId4Data(x, y, z);
} catch (FaweException ignore) {
@ -477,7 +452,7 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
}
}
public int getCombinedId4DataDebug(int x, int y, int z, int def, EditSession session) {
default int getCombinedId4DataDebug(int x, int y, int z, int def, EditSession session) {
try {
return getCombinedId4Data(x, y, z);
} catch (FaweException ignore) {
@ -488,7 +463,7 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
}
}
public int getBrightness(int x, int y, int z) {
default int getBrightness(int x, int y, int z) {
int combined = getCombinedId4Data(x, y, z);
if (combined == 0) {
return 0;
@ -500,11 +475,11 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
return block.getLightValue();
}
public int getOpacityBrightnessPair(int x, int y, int z) {
default int getOpacityBrightnessPair(int x, int y, int z) {
return MathMan.pair16(Math.min(15, getOpacity(x, y, z)), getBrightness(x, y, z));
}
public int getOpacity(int x, int y, int z) {
default int getOpacity(int x, int y, int z) {
int combined = getCombinedId4Data(x, y, z);
if (combined == 0) {
return 0;
@ -516,31 +491,23 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
return block.getLightOpacity();
}
public abstract int size();
int size();
public boolean isEmpty() {
default boolean isEmpty() {
return size() == 0;
}
/**
* Lock the thread until the queue is empty
*/
public void flush() {
default void flush() {
flush(10000);
}
public SetQueue.QueueStage getStage() {
return stage;
}
public void setStage(SetQueue.QueueStage stage) {
this.stage = stage;
}
/**
* Lock the thread until the queue is empty
*/
public void flush(int time) {
default void flush(int time) {
if (size() > 0) {
if (Fawe.isMainThread()) {
SetQueue.IMP.flush(this);
@ -560,45 +527,11 @@ public abstract class FaweQueue implements HasFaweQueue, Extent {
}
}
public ConcurrentLinkedDeque<Runnable> tasks = new ConcurrentLinkedDeque<>();
public void addNotifyTask(Runnable runnable) {
this.tasks.add(runnable);
}
public void runTasks() {
synchronized (this) {
this.notifyAll();
}
if (getProgressTask() != null) {
try {
getProgressTask().run(ProgressType.DONE, 1);
} catch (Throwable e) {
e.printStackTrace();
}
}
while (!tasks.isEmpty()) {
Runnable task = tasks.poll();
if (task != null) {
try {
task.run();
} catch (Throwable e) {
MainUtil.handleError(e);
}
}
}
}
public void addTask(Runnable whenFree) {
tasks.add(whenFree);
}
public boolean enqueue() {
default boolean enqueue() {
return SetQueue.IMP.enqueue(this);
}
public void dequeue() {
default void dequeue() {
SetQueue.IMP.dequeue(this);
}
}

View File

@ -4,7 +4,7 @@ import com.boydti.fawe.object.extent.FaweRegionExtent;
import com.boydti.fawe.object.extent.HeightBoundExtent;
import com.boydti.fawe.object.extent.MultiRegionExtent;
import com.boydti.fawe.object.extent.SingleRegionExtent;
import com.boydti.fawe.util.DelegateFaweQueue;
import com.boydti.fawe.object.queue.DelegateFaweQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;

View File

@ -21,6 +21,10 @@ public class Metadatable {
return (T) this.meta.put(key, value);
}
public boolean hasMeta() {
return !meta.isEmpty();
}
/**
* Get the metadata for a key.
*

View File

@ -1,14 +1,18 @@
package com.boydti.fawe.object.brush;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.brush.heightmap.HeightMap;
import com.boydti.fawe.object.brush.heightmap.RotatableHeightMap;
import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
@ -66,12 +70,85 @@ public class HeightBrush implements Brush {
@Override
public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
int size = (int) sizeDouble;
HeightMap map = getHeightMap();
map.setSize(size);
FaweQueue queue = editSession.getQueue();
// Optimized application of height map
if (queue instanceof HeightMapMCAGenerator) {
HeightMapMCAGenerator hmmg = (HeightMapMCAGenerator) queue;
byte[] metaHeight = hmmg.getMetaData().getMeta("PRECISION_HEIGHT");
if (metaHeight == null) {
hmmg.getMetaData().setMeta("PRECISION_HEIGHT", metaHeight = new byte[hmmg.getArea()]);
}
Vector origin = hmmg.getOrigin();
int bx = position.getBlockX();
int bz = position.getBlockZ();
int minIndex = -(size * 2) - 1;
int width = hmmg.getWidth();
int minX = Math.max(-size, origin.getBlockX() - bx);
int minZ = Math.max(-size, origin.getBlockZ() - bz);
int maxX = Math.min(size, origin.getBlockX() + hmmg.getWidth() - 1 - bx);
int maxZ = Math.min(size, origin.getBlockZ() + hmmg.getLength() - 1 - bz);
int zIndex = (bz + minZ) * width;
for (int z = minZ; z <= maxZ; z++, zIndex += width) {
int zz = bz + z;
int index = zIndex + (bx + minX);
if (index < minIndex) continue;
if (index >= metaHeight.length) break;
for (int x = maxX; x <= maxX; x++, index++) {
if (index < 0) continue;
if (index >= metaHeight.length) break;
int xx = bx + x;
int currentBlockHeight = hmmg.getHeight(index);
int currentLayer = metaHeight[index] & 0xFF;
double addHeight = heightMap.getHeight(x, z) * yscale;
int addBlockHeight = (int) addHeight;
int addLayer = (int) ((addHeight - addBlockHeight) * 256);
int newLayer = addLayer + currentLayer;
int newBlockHeight = currentBlockHeight + addBlockHeight;
int newLayerAbs = MathMan.absByte(newLayer);
if (newLayerAbs >= 256) {
int newLayerBlocks = (newLayer >> 8);
newBlockHeight += newLayerBlocks;
newLayer -= newLayerBlocks << 8;
}
hmmg.setHeight(index, newBlockHeight);
metaHeight[index] = (byte) newLayer;
}
}
if (smooth) {
Vector2D min = new Vector2D(Math.max(0, bx - size), Math.max(0, bz - size));
Vector2D max = new Vector2D(Math.min(hmmg.getWidth() - 1, bx + size), Math.min(hmmg.getLength() - 1, bz + size));
hmmg.smooth(min, max, 8, 1);
if (size > 20) {
int smoothSize = size + 8;
min = new Vector2D(Math.max(0, bx - smoothSize), Math.max(0, bz - smoothSize));
max = new Vector2D(Math.min(hmmg.getWidth() - 1, bx + smoothSize), Math.min(hmmg.getLength() - 1, bz + smoothSize));
hmmg.smooth(min, max, 1, 1);
}
}
return;
}
Mask mask = editSession.getMask();
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
mask = null;
}
HeightMap map = getHeightMap();
map.setSize(size);
map.perform(editSession, mask, position, size, rotation, yscale, smooth, false, layers);
}
}

View File

@ -55,7 +55,7 @@ public interface HeightMap {
}
}
default int[][] generateHeightData(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards, final boolean layers) {
default int[][] generateHeightData(EditSession session, Mask mask, Vector pos, int size, final int rotationMode, double yscale, boolean smooth, boolean towards, final boolean layers) {
Vector top = session.getMaximumPoint();
int maxY = top.getBlockY();
int diameter = 2 * size + 1;
@ -72,7 +72,7 @@ public interface HeightMap {
}
Vector mutablePos = new Vector(0, 0, 0);
if (towards) {
double sizePow = Math.pow(size, yscale);
double sizePowInv = 1d / Math.pow(size, yscale);
int targetY = pos.getBlockY();
int tmpY = targetY;
for (int x = -size; x <= size; x++) {
@ -110,7 +110,7 @@ public interface HeightMap {
}
double raisePow = Math.pow(raise, yscale);
int diff = targetY - height;
double raiseScaled = diff * (raisePow / sizePow);
double raiseScaled = diff * (raisePow * sizePowInv);
double raiseScaledAbs = Math.abs(raiseScaled);
int random = PseudoRandom.random.random(256) < (int) ((Math.ceil(raiseScaledAbs) - Math.floor(raiseScaledAbs)) * 256) ? (diff > 0 ? 1 : -1) : 0;
int raiseScaledInt = (int) raiseScaled + random;

View File

@ -43,7 +43,7 @@ public class ScalableHeightMap implements com.boydti.fawe.object.brush.heightmap
if (d2 > size2) {
return 0;
}
return size - MathMan.sqrtApprox(d2);
return Math.max(0, size - MathMan.sqrtApprox(d2));
}
public static ScalableHeightMap fromShape(Shape shape) {

View File

@ -0,0 +1,60 @@
package com.boydti.fawe.object.change;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.HasFaweQueue;
import com.boydti.fawe.util.ExtentTraverser;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.history.UndoContext;
import com.sk89q.worldedit.history.change.Change;
import java.io.File;
import java.io.IOException;
import static com.google.common.base.Preconditions.checkNotNull;
public class CFIChange implements Change {
private final File file;
public CFIChange(File file) {
checkNotNull(file);
this.file = file;
}
private HeightMapMCAGenerator getQueue(UndoContext context) {
ExtentTraverser found = new ExtentTraverser(context.getExtent()).find(HasFaweQueue.class);
if (found != null) {
FaweQueue queue = ((HasFaweQueue) found.get()).getQueue();
if (queue instanceof HeightMapMCAGenerator) return (HeightMapMCAGenerator) queue;
}
Fawe.debug("FAWE does not support: " + context.getExtent() + " for " + getClass() + " (bug Empire92)");
return null;
}
@Override
public void undo(UndoContext context) throws WorldEditException {
HeightMapMCAGenerator queue = getQueue(context);
if (queue != null) {
try {
queue.undoChanges(file);
} catch (IOException e) {
e.printStackTrace();
}
queue.update();
}
}
@Override
public void redo(UndoContext context) throws WorldEditException {
HeightMapMCAGenerator queue = getQueue(context);
if (queue != null) {
try {
queue.redoChanges(file);
} catch (IOException e) {
e.printStackTrace();
}
queue.update();
}
}
}

View File

@ -0,0 +1,51 @@
package com.boydti.fawe.object.change;
import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
public interface StreamChange {
public void flushChanges(FaweOutputStream out) throws IOException;
public void undoChanges(FaweInputStream in) throws IOException;
public void redoChanges(FaweInputStream in) throws IOException;
default void flushChanges(File file) throws IOException {
try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
try (LZ4BlockOutputStream compressed = new LZ4BlockOutputStream(out)) {
// compressed.setLevel(Deflater.BEST_SPEED);
try (FaweOutputStream fos = new FaweOutputStream(compressed)) {
flushChanges(fos);
}
}
}
}
default void undoChanges(File file) throws IOException {
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) {
try (LZ4BlockInputStream compressed = new LZ4BlockInputStream(in)) {
try (FaweInputStream fis = new FaweInputStream(compressed)) {
undoChanges(fis);
}
}
}
}
default void redoChanges(File file) throws IOException {
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) {
try (LZ4BlockInputStream compressed = new LZ4BlockInputStream(in)) {
try (FaweInputStream fis = new FaweInputStream(compressed)) {
redoChanges(fis);
}
}
}
}
}

View File

@ -0,0 +1,81 @@
package com.boydti.fawe.object.changeset;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator;
import com.boydti.fawe.object.change.CFIChange;
import com.boydti.fawe.util.MainUtil;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.history.change.Change;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.UUID;
public class CFIChangeSet extends FaweChangeSet {
private final File file;
public CFIChangeSet(HeightMapMCAGenerator hmmg, UUID uuid) throws IOException {
super(hmmg);
File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + uuid + File.separator + hmmg.getWorldName());
int max = MainUtil.getMaxFileId(folder);
this.file = new File(folder, Integer.toString(max) + ".cfi");
File parent = this.file.getParentFile();
if (!parent.exists()) this.file.getParentFile().mkdirs();
if (!this.file.exists()) this.file.createNewFile();
hmmg.flushChanges(file);
}
@Override
public boolean close() {
return true;
}
@Override
public boolean closeAsync() {
return true;
}
@Override
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
throw new UnsupportedOperationException("Only CFI operations are supported");
}
@Override
public void addTileCreate(CompoundTag tag) {
throw new UnsupportedOperationException("Only CFI operations are supported");
}
@Override
public void addTileRemove(CompoundTag tag) {
throw new UnsupportedOperationException("Only CFI operations are supported");
}
@Override
public void addEntityRemove(CompoundTag tag) {
throw new UnsupportedOperationException("Only CFI operations are supported");
}
@Override
public void addEntityCreate(CompoundTag tag) {
throw new UnsupportedOperationException("Only CFI operations are supported");
}
@Override
public void addBiomeChange(int x, int z, BaseBiome from, BaseBiome to) {
throw new UnsupportedOperationException("Only CFI operations are supported");
}
@Override
public Iterator<Change> getIterator(boolean redo) {
return Collections.<Change>singleton(new CFIChange(file)).iterator();
}
@Override
public int size() {
return 1;
}
}

View File

@ -159,7 +159,6 @@ public abstract class FaweChangeSet implements ChangeSet {
builder.allowedRegionsEverywhere();
}
EditSession editSession = builder.build();
editSession.setSize(1);
return editSession;
}

View File

@ -107,7 +107,7 @@ public class MultiClipboardHolder extends URIClipboardHolder {
@Override
public List<ClipboardHolder> getHolders() {
ArrayList<ClipboardHolder> holders = new ArrayList<>();
for (ClipboardHolder holder : holders) {
for (ClipboardHolder holder : this.holders) {
holders.addAll(holder.getHolders());
}
return holders;

View File

@ -0,0 +1,237 @@
package com.boydti.fawe.object.collection;
import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.io.serialize.Serialize;
import com.boydti.fawe.util.MainUtil;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Records changes made through the {@link #setByte(int, byte)} or {@link #setChar(int, char)} method<br/>
* If you are editing the raw data, use {@link #record(Runnable)}
* @param <T>
*/
public final class DifferentialArray<T> implements DifferentialCollection<T> {
private final byte[] dataBytes;
private byte[] changesBytes;
private final char[] dataChars;
private char[] changesChars;
@Serialize private final T data;
private T changes;
private boolean changed;
private int length;
public DifferentialArray(T array) {
checkNotNull(array);
Class<? extends Object> clazz = array.getClass();
checkArgument(clazz.isArray(), "Data must be an array");
checkArgument(clazz.getComponentType().isPrimitive(), "Data must be a primitive array");
this.data = array;
if (array instanceof byte[]) {
dataBytes = (byte[]) array;
length = dataBytes.length;
} else {
dataBytes = null;
}
if (array instanceof char[]) {
dataChars = (char[]) array;
length = dataChars.length;
} else {
dataChars = null;
}
}
public void record(Runnable task) {
if (changes == null) {
if (data instanceof byte[]) {
changes = (T) (changesBytes = new byte[length]);
} else if (data instanceof char[]) {
changes = (T) (changesChars = new char[length]);
}
}
boolean changed = false;
T tmp;
if (changed) {
tmp = (T) MainUtil.copyNd(data);
} else {
tmp = changes;
System.arraycopy(data, 0, tmp, 0, Array.getLength(data));
}
Throwable caught = null;
try {
task.run();
} catch (Throwable e) {
caught = e;
task.run();
}
if (tmp instanceof char[]) {
char[] tmpChars = (char[]) tmp;
for (int i = 0; i < tmpChars.length; i++) {
char tmpChar = tmpChars[i];
char dataChar = dataChars[i];
if (tmpChar != dataChar) {
this.changed = true;
tmpChars[i] -= dataChar;
}
}
if (tmp != changes) {
for (int i = 0; i < tmpChars.length; i++) {
changesChars[i] += tmpChars[i];
}
}
} else if (tmp instanceof byte[]) {
byte[] tmpBytes = (byte[]) tmp;
for (int i = 0; i < tmpBytes.length; i++) {
byte tmpByte = tmpBytes[i];
byte dataByte = dataBytes[i];
if (tmpByte != dataByte) {
this.changed = true;
tmpBytes[i] -= dataByte;
}
}
if (tmp != changes) {
for (int i = 0; i < tmpBytes.length; i++) {
changesBytes[i] += tmpBytes[i];
}
}
}
if (caught != null) {
if (caught instanceof RuntimeException) throw (RuntimeException) caught;
else throw new RuntimeException(caught);
}
}
@Override
public void flushChanges(FaweOutputStream out) throws IOException {
boolean modified = isModified();
out.writeBoolean(modified);
if (modified) {
if (dataBytes != null) {
out.write(changesBytes);
} else if (dataChars != null) {
for (char c : changesChars) {
out.writeChar(c);
}
}
}
clearChanges();
}
@Override
public void undoChanges(FaweInputStream in) throws IOException {
boolean modified = in.readBoolean();
if (modified) {
if (dataBytes != null) {
if (changesBytes != null) {
for (int i = 0; i < dataBytes.length; i++) {
dataBytes[i] += changesBytes[i];
}
}
for (int i = 0; i < dataBytes.length; i++) {
int read = in.read();
dataBytes[i] += read;
}
} else if (dataChars != null) {
if (changesChars != null) {
for (int i = 0; i < dataChars.length; i++) {
dataChars[i] += changesChars[i];
}
}
for (int i = 0; i < dataChars.length; i++) {
dataChars[i] += in.readChar();
}
}
}
clearChanges();
}
@Override
public void redoChanges(FaweInputStream in) throws IOException {
boolean modified = in.readBoolean();
if (modified) {
if (dataBytes != null) {
for (int i = 0; i < dataBytes.length; i++) {
int read = in.read();
dataBytes[i] -= read;
}
} else if (dataChars != null) {
for (int i = 0; i < dataChars.length; i++) {
dataChars[i] -= in.readChar();
}
}
}
clearChanges();
}
public void clearChanges() {
if (changed) {
changed = false;
if (changes != null) {
if (changesBytes != null) {
Arrays.fill(changesBytes, (byte) 0);
}
if (changesChars != null) {
Arrays.fill(changesChars, (char) 0);
}
}
}
}
public byte[] getByteArray() {
return dataBytes;
}
public char[] getCharArray() {
return dataChars;
}
public boolean isModified() {
return changed;
}
@Override
public T get() {
return data;
}
public byte getByte(int index) {
return dataBytes[index];
}
public char getChar(int index) {
return dataChars[index];
}
public void setByte(int index, byte value) {
changed = true;
try {
changesBytes[index] += (dataBytes[index] - value);
} catch (NullPointerException ignore) {
changes = (T) (changesBytes = new byte[dataBytes.length]);
changesBytes[index] += (dataBytes[index] - value);
}
dataBytes[index] = value;
}
public void setChar(int index, char value) {
changed = true;
try {
changesChars[index] += dataChars[index] - value;
} catch (NullPointerException ignore) {
changes = (T) (changesChars = new char[dataChars.length]);
changesChars[index] += dataChars[index] - value;
}
dataChars[index] = value;
}
}

View File

@ -0,0 +1,212 @@
package com.boydti.fawe.object.collection;
import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
/**
* Records changes made through the {@link #set(int, int, int, char)} method<br/>
* Changes are not recorded if you edit the raw data
*/
public final class DifferentialBlockBuffer implements DifferentialCollection<char[][][][][]> {
private final int width, length;
private final int t1, t2;
private char[][][][][] data;
private char[][][][][] changes;
public DifferentialBlockBuffer(int width, int length) {
this.width = width;
this.length = length;
this.t1 = (length + 15) >> 4;
this.t2 = (width + 15) >> 4;
}
@Override
public char[][][][][] get() {
return data;
}
@Override
public void flushChanges(FaweOutputStream out) throws IOException {
boolean modified = isModified();
out.writeBoolean(modified);
if (modified) {
writeArray(changes, 0, 0, out);
}
clearChanges();
}
private void writeArray(Object arr, int level, int index, FaweOutputStream out) throws IOException {
if (level == 4) {
if (arr != null) {
char[] level4 = (char[]) arr;
out.writeVarInt(level4.length);
for (char c : level4) {
out.writeChar(c);
}
} else {
out.writeVarInt(0);
}
} else {
int len = arr == null ? 0 : Array.getLength(arr);
out.writeVarInt(len);
for (int i = 0; i < len; i++) {
Object elem = Array.get(arr, i);
writeArray(elem, level + 1, i, out);
}
}
}
@Override
public void undoChanges(FaweInputStream in) throws IOException {
if (changes != null && changes.length != 0) throw new IllegalStateException("There are uncommitted changes, please flush first");
boolean modified = in.readBoolean();
if (modified) {
int len = in.readVarInt();
if (len == 0) {
data = null;
} else {
for (int i = 0; i < len; i++) {
readArray(data, i, 1, in);
}
}
}
clearChanges();
}
@Override
public void redoChanges(FaweInputStream in) throws IOException {
clearChanges();
throw new UnsupportedOperationException("Not implemented");
}
private void readArray(Object dataElem, int index, int level, FaweInputStream in) throws IOException {
int len = in.readVarInt();
if (level == 4) {
char[][] castedElem = (char[][]) dataElem;
if (len == 0) {
castedElem[index] = null;
} else {
char[] current = castedElem[index];
for (int i = 0; i < len; i++) {
current[i] = in.readChar();
}
}
} else {
if (len == 0) {
Array.set(dataElem, index, null);
} else {
Object nextElem = Array.get(dataElem, index);
for (int i = 0; i < len; i++) {
readArray(nextElem, i, level + 1, in);
}
}
}
}
public boolean isModified() {
return changes != null;
}
public void clearChanges() {
changes = null;
}
public void set(int x, int y, int z, char combined) {
if (combined == 0) combined = 1;
int localX = x & 15;
int localZ = z & 15;
int chunkX = x >> 4;
int chunkZ = z >> 4;
if (data == null) {
data = new char[t1][][][][];
changes = new char[0][][][][];
}
char[][][][] arr = data[chunkZ];
if (arr == null) {
arr = data[chunkZ] = new char[t2][][][];
}
char[][][] arr2 = arr[chunkX];
if (arr2 == null) {
arr2 = arr[chunkX] = new char[256][][];
}
char[][] yMap = arr2[y];
if (yMap == null) {
arr2[y] = yMap = new char[16][];
}
boolean newSection;
char current;
char[] zMap = yMap[localZ];
if (zMap == null) {
yMap[localZ] = zMap = new char[16];
if (changes == null) {
changes = new char[t1][][][][];
} else if (changes != null && changes.length != 0) {
initialChange(changes, chunkX, chunkZ, localX, localZ, y, (char) -combined);
}
} else {
if (changes == null || changes.length == 0) changes = new char[t1][][][][];
appendChange(changes, chunkX, chunkZ, localX, localZ, y, (char) (zMap[localX] - combined));
}
zMap[localX] = combined;
}
private void initialChange(char[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, char combined) {
char[][][][] arr = src[chunkZ];
if (arr == null) {
src[chunkZ] = new char[0][][][];
return;
} else if (arr.length == 0) return;
char[][][] arr2 = arr[chunkX];
if (arr2 == null) {
arr[chunkX] = new char[0][][];
return;
} else if (arr2.length == 0) return;
char[][] yMap = arr2[y];
if (yMap == null) {
arr2[y] = new char[0][];
return;
} else if (yMap.length == 0) return;
char[] zMap = yMap[localZ];
if (zMap == null) {
yMap[localZ] = new char[0];
return;
} else if (zMap.length == 0) return;
char current = zMap[localX];
zMap[localX] = combined;
}
private void appendChange(char[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, char combined) {
char[][][][] arr = src[chunkZ];
if (arr == null || arr.length == 0) {
arr = src[chunkZ] = new char[t2][][][];
}
char[][][] arr2 = arr[chunkX];
if (arr2 == null || arr2.length == 0) {
arr2 = arr[chunkX] = new char[256][][];
}
char[][] yMap = arr2[y];
if (yMap == null || yMap.length == 0) {
arr2[y] = yMap = new char[16][];
}
char[] zMap = yMap[localZ];
if (zMap == null || zMap.length == 0) {
yMap[localZ] = zMap = new char[16];
}
zMap[localX] = combined;
}
}

View File

@ -0,0 +1,7 @@
package com.boydti.fawe.object.collection;
import com.boydti.fawe.object.change.StreamChange;
public interface DifferentialCollection<T> extends StreamChange {
public T get();
}

View File

@ -62,7 +62,11 @@ public abstract class IterableThreadLocal<T> extends ThreadLocal<T> implements I
methodRemove = tlm.getClass().getDeclaredMethod("remove", ThreadLocal.class);
methodRemove.setAccessible(true);
}
methodRemove.invoke(tlm, instance);
if (methodRemove != null) {
try {
methodRemove.invoke(tlm, instance);
} catch (Throwable ignore) {}
}
}
}
}

View File

@ -39,6 +39,11 @@ public class FastWorldEditExtent extends AbstractDelegateExtent implements HasFa
return queue;
}
@Override
public int getMaxY() {
return queue.getMaxY();
}
@Override
public int getLight(int x, int y, int z) {
return queue.getLight(x, y, z);

View File

@ -0,0 +1,12 @@
package com.boydti.fawe.object.io.serialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Serialize {
}

View File

@ -0,0 +1,50 @@
package com.boydti.fawe.object.io.serialize;
import com.boydti.fawe.util.ReflectionUtils;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
/**
* Call serialize(stream) to serialize any field with @Serialize<br/>
* Call deserialize(stream) to deserialize any field with @Serialize<br/>
*/
public interface Serializer extends Serializable {
default void serialize(java.io.ObjectOutputStream stream) throws IOException {
try {
for (Field field : getClass().getDeclaredFields()) {
field.setAccessible(true);
if (field.getDeclaredAnnotation(Serialize.class) != null) {
Class<?> type = field.getType();
boolean primitive = type.isPrimitive();
Object value = field.get(this);
if (primitive) {
stream.writeObject(value);
} else if (value == null){
stream.writeByte(0);
} else {
stream.writeByte(1);
stream.writeObject(value);
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
default void deserialize(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
for (Field field : getClass().getDeclaredFields()) {
if (field.getDeclaredAnnotation(Serialize.class) != null) {
Class<?> type = field.getType();
boolean primitive = type.isPrimitive();
if (primitive) {
ReflectionUtils.setField(field, this, stream.readObject());
} else if (stream.readByte() == 1) {
ReflectionUtils.setField(field, this, stream.readObject());
}
}
}
}
}

View File

@ -20,13 +20,14 @@ public class MaskedTargetBlock extends TargetBlock {
boolean searchForLastBlock = true;
BlockWorldVector lastBlock = null;
while (getNextBlock() != null) {
if (!mask.test(getCurrentBlock())) {
BlockWorldVector current = getCurrentBlock();
if (!mask.test(current)) {
if (searchForLastBlock) {
lastBlock = getCurrentBlock();
lastBlock = current;
if (lastBlock.getBlockY() <= 0 || lastBlock.getBlockY() >= world.getMaxY()) {
searchForLastBlock = false;
}
}
} else if (current.getBlockY() <= 0) break;
} else {
break;
}
@ -34,4 +35,4 @@ public class MaskedTargetBlock extends TargetBlock {
BlockWorldVector currentBlock = getCurrentBlock();
return (currentBlock != null || !useLastBlock ? currentBlock : lastBlock);
}
}
}

View File

@ -0,0 +1,25 @@
package com.boydti.fawe.object.queue;
import com.boydti.fawe.object.FaweQueue;
public class DelegateFaweQueue implements IDelegateFaweQueue {
private FaweQueue parent;
public DelegateFaweQueue(FaweQueue parent) {
this.parent = parent;
}
public FaweQueue getParent() {
return parent;
}
public void setParent(FaweQueue parent) {
this.parent = parent;
setWorld(getQueue().getWorldName());
}
@Override
public FaweQueue getQueue() {
return parent;
}
}

View File

@ -3,7 +3,6 @@ package com.boydti.fawe.object.queue;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.DelegateFaweQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.MutableBlockVector2D;
import com.sk89q.worldedit.Vector;

View File

@ -0,0 +1,515 @@
package com.boydti.fawe.object.queue;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.example.Relighter;
import com.boydti.fawe.jnbt.anvil.generator.GenBase;
import com.boydti.fawe.jnbt.anvil.generator.Resource;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.SetQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
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.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.WorldData;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
public interface IDelegateFaweQueue extends FaweQueue {
FaweQueue getQueue();
@Override
default void dequeue() {
getQueue().dequeue();
}
@Override
default Relighter getRelighter() {
return getQueue().getRelighter();
}
@Override
default Vector getMinimumPoint() {
return getQueue().getMinimumPoint();
}
@Override
default Vector getMaximumPoint() {
return getQueue().getMaximumPoint();
}
@Override
default BaseBlock getLazyBlock(int x, int y, int z) {
return getQueue().getLazyBlock(x, y, z);
}
@Override
default boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
return getQueue().setBlock(x, y, z, block);
}
@Override
default BaseBlock getBlock(Vector position) {
return getQueue().getBlock(position);
}
@Override
default BaseBiome getBiome(Vector2D position) {
return getQueue().getBiome(position);
}
@Override
default boolean setBlock(Vector position, BaseBlock block) throws WorldEditException {
return getQueue().setBlock(position, block);
}
@Override
default boolean setBiome(Vector2D position, BaseBiome biome) {
return getQueue().setBiome(position, biome);
}
@Override
default void addEditSession(EditSession session) {
getQueue().addEditSession(session);
}
@Override
default void setProgressTracker(RunnableVal2<ProgressType, Integer> progressTask) {
getQueue().setProgressTracker(progressTask);
}
@Override
default Collection<EditSession> getEditSessions() {
return getQueue().getEditSessions();
}
@Override
default boolean supports(Capability capability) {
return getQueue().supports(capability);
}
@Override
default void optimize() {
getQueue().optimize();
}
@Override
default int setBlocks(CuboidRegion cuboid, int id, int data) {
return getQueue().setBlocks(cuboid, id, data);
}
@Override
default boolean setBlock(int x, int y, int z, int id, int data) {
return getQueue().setBlock(x, y, z, id, data);
}
@Override
default boolean setBlock(int x, int y, int z, int id) {
return getQueue().setBlock(x, y, z, id);
}
@Override
default boolean setBlock(int x, int y, int z, int id, int data, CompoundTag nbt) {
return getQueue().setBlock(x, y, z, id, data, nbt);
}
@Override
default void setTile(int x, int y, int z, CompoundTag tag) {
getQueue().setTile(x, y, z, tag);
}
@Override
default void setEntity(int x, int y, int z, CompoundTag tag) {
getQueue().setEntity(x, y, z, tag);
}
@Override
default void removeEntity(int x, int y, int z, UUID uuid) {
getQueue().removeEntity(x, y, z, uuid);
}
@Override
default boolean setBiome(int x, int z, BaseBiome biome) {
return getQueue().setBiome(x, z, biome);
}
@Override
default FaweChunk getFaweChunk(int x, int z) {
return getQueue().getFaweChunk(x, z);
}
@Override
default Collection<FaweChunk> getFaweChunks() {
return getQueue().getFaweChunks();
}
@Override
default boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean save, boolean load) {
return getQueue().setMCA(mcaX, mcaZ, region, whileLocked, save, load);
}
@Override
default void setChunk(FaweChunk chunk) {
getQueue().setChunk(chunk);
}
@Override
default File getSaveFolder() {
return getQueue().getSaveFolder();
}
@Override
default int getMaxY() {
return getQueue().getMaxY();
}
@Override
default Settings getSettings() {
return getQueue().getSettings();
}
@Override
default void setSettings(Settings settings) {
getQueue().setSettings(settings);
}
@Override
default void setWorld(String world) {
getQueue().setWorld(world);
}
@Override
default World getWEWorld() {
return getQueue().getWEWorld();
}
@Override
default String getWorldName() {
return getQueue().getWorldName();
}
@Override
default long getModified() {
return getQueue().getModified();
}
@Override
default void setModified(long modified) {
getQueue().setModified(modified);
}
@Override
default RunnableVal2<ProgressType, Integer> getProgressTask() {
return getQueue().getProgressTask();
}
@Override
default void setProgressTask(RunnableVal2<ProgressType, Integer> progressTask) {
getQueue().setProgressTask(progressTask);
}
@Override
default void setChangeTask(RunnableVal2<FaweChunk, FaweChunk> changeTask) {
getQueue().setChangeTask(changeTask);
}
@Override
default RunnableVal2<FaweChunk, FaweChunk> getChangeTask() {
return getQueue().getChangeTask();
}
@Override
default SetQueue.QueueStage getStage() {
return getQueue().getStage();
}
@Override
default void setStage(SetQueue.QueueStage stage) {
getQueue().setStage(stage);
}
@Override
default void addNotifyTask(Runnable runnable) {
getQueue().addNotifyTask(runnable);
}
@Override
default void runTasks() {
getQueue().runTasks();
}
@Override
default void addTask(Runnable whenFree) {
getQueue().addTask(whenFree);
}
@Override
default void forEachBlockInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
getQueue().forEachBlockInChunk(cx, cz, onEach);
}
@Override
default void forEachTileInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
getQueue().forEachTileInChunk(cx, cz, onEach);
}
@Override
@Deprecated
default boolean regenerateChunk(int x, int z) {
return getQueue().regenerateChunk(x, z);
}
@Override
default boolean regenerateChunk(int x, int z, @Nullable BaseBiome biome, @Nullable Long seed) {
return getQueue().regenerateChunk(x, z, biome, seed);
}
@Override
default void startSet(boolean parallel) {
getQueue().startSet(parallel);
}
@Override
default void endSet(boolean parallel) {
getQueue().endSet(parallel);
}
@Override
default int cancel() {
return getQueue().cancel();
}
@Override
default void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
getQueue().sendBlockUpdate(chunk, players);
}
@Override
@Deprecated
default boolean next() {
return getQueue().next();
}
@Override
default boolean next(int amount, long time) {
return getQueue().next(amount, time);
}
@Override
default void saveMemory() {
getQueue().saveMemory();
}
@Override
default void sendChunk(FaweChunk chunk) {
getQueue().sendChunk(chunk);
}
@Override
default void sendChunk(int x, int z, int bitMask) {
getQueue().sendChunk(x, z, bitMask);
}
@Override
default void clear() {
getQueue().clear();
}
@Override
default void addNotifyTask(int x, int z, Runnable runnable) {
getQueue().addNotifyTask(x, z, runnable);
}
@Override
default boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException {
return getQueue().hasBlock(x, y, z);
}
@Override
default int getBiomeId(int x, int z) throws FaweException.FaweChunkLoadException {
return getQueue().getBiomeId(x, z);
}
@Override
default int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
return getQueue().getCombinedId4Data(x, y, z);
}
@Override
default int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
return getQueue().getCachedCombinedId4Data(x, y, z);
}
@Override
default int getAdjacentLight(int x, int y, int z) {
return getQueue().getAdjacentLight(x, y, z);
}
@Override
default boolean hasSky() {
return getQueue().hasSky();
}
@Override
default int getSkyLight(int x, int y, int z) {
return getQueue().getSkyLight(x, y, z);
}
@Override
default int getLight(int x, int y, int z) {
return getQueue().getLight(x, y, z);
}
@Override
default int getEmmittedLight(int x, int y, int z) {
return getQueue().getEmmittedLight(x, y, z);
}
@Override
default CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException {
return getQueue().getTileEntity(x, y, z);
}
@Override
default int getCombinedId4Data(int x, int y, int z, int def) {
return getQueue().getCombinedId4Data(x, y, z, def);
}
@Override
default int getCachedCombinedId4Data(int x, int y, int z, int def) {
return getQueue().getCachedCombinedId4Data(x, y, z, def);
}
@Override
default int getCombinedId4DataDebug(int x, int y, int z, int def, EditSession session) {
return getQueue().getCombinedId4DataDebug(x, y, z, def, session);
}
@Override
default int getBrightness(int x, int y, int z) {
return getQueue().getBrightness(x, y, z);
}
@Override
default int getOpacityBrightnessPair(int x, int y, int z) {
return getQueue().getOpacityBrightnessPair(x, y, z);
}
@Override
default int getOpacity(int x, int y, int z) {
return getQueue().getOpacity(x, y, z);
}
@Override
default int size() {
return getQueue().size();
}
@Override
default boolean isEmpty() {
return getQueue().isEmpty();
}
@Override
default void flush() {
getQueue().flush();
}
@Override
default void flush(int time) {
getQueue().flush(time);
}
@Override
default boolean enqueue() {
return getQueue().enqueue();
}
@Override
default List<? extends Entity> getEntities(Region region) {
return getQueue().getEntities(region);
}
@Override
default List<? extends Entity> getEntities() {
return getQueue().getEntities();
}
@Override
@Nullable
default Entity createEntity(Location location, BaseEntity entity) {
return getQueue().createEntity(location, entity);
}
@Override
default BaseBlock getLazyBlock(Vector position) {
return getQueue().getLazyBlock(position);
}
@Nullable
@Override
default Operation commit() {
return getQueue().commit();
}
@Override
default int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
return getQueue().getNearestSurfaceLayer(x, z, y, minY, maxY);
}
@Override
default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
return getQueue().getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
}
@Override
default void addCaves(Region region) throws WorldEditException {
getQueue().addCaves(region);
}
@Override
default void generate(Region region, GenBase gen) throws WorldEditException {
getQueue().generate(region, gen);
}
@Override
default void addSchems(Region region, Mask mask, WorldData worldData, List<ClipboardHolder> clipboards, int rarity, boolean rotate) throws WorldEditException {
getQueue().addSchems(region, mask, worldData, clipboards, rarity, rotate);
}
@Override
default void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException {
getQueue().spawnResource(region, gen, rarity, frequency);
}
@Override
default void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException {
getQueue().addOre(region, mask, material, size, frequency, rarity, minY, maxY);
}
@Override
default void addOres(Region region, Mask mask) throws WorldEditException {
getQueue().addOres(region, mask);
}
}

View File

@ -0,0 +1,219 @@
package com.boydti.fawe.object.queue;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
public abstract class LazyFaweChunk<T extends FaweChunk> extends FaweChunk {
private T parent;
public LazyFaweChunk(FaweQueue queue, int chunkX, int chunkZ) {
super(queue, chunkX, chunkZ);
}
private T internalGetOrCacheChunk() {
T tmp = parent;
if (tmp == null) parent = tmp = getChunk();
return tmp;
}
protected T getCachedChunk() {
return parent;
}
public abstract T getChunk();
@Override
public FaweQueue getParent() {
return internalGetOrCacheChunk().getParent();
}
@Override
public long longHash() {
return internalGetOrCacheChunk().longHash();
}
@Override
public int hashCode() {
return internalGetOrCacheChunk().hashCode();
}
@Override
public void addToQueue() {
internalGetOrCacheChunk().addToQueue();
}
@Override
public int getBitMask() {
return internalGetOrCacheChunk().getBitMask();
}
@Override
public int getBlockCombinedId(int x, int y, int z) {
return internalGetOrCacheChunk().getBlockCombinedId(x, y, z);
}
@Override
public void setBlock(int x, int y, int z, BaseBlock block) {
internalGetOrCacheChunk().setBlock(x, y, z, block);
}
@Override
public BaseBlock getBlock(int x, int y, int z) {
return internalGetOrCacheChunk().getBlock(x, y, z);
}
@Override
@Nullable
public char[] getIdArray(int layer) {
return internalGetOrCacheChunk().getIdArray(layer);
}
@Override
public byte[][] getBlockLightArray() {
return internalGetOrCacheChunk().getBlockLightArray();
}
@Override
public byte[][] getSkyLightArray() {
return internalGetOrCacheChunk().getSkyLightArray();
}
@Override
public byte[] getBiomeArray() {
return internalGetOrCacheChunk().getBiomeArray();
}
@Override
public void forEachQueuedBlock(FaweChunkVisitor onEach) {
internalGetOrCacheChunk().forEachQueuedBlock(onEach);
}
@Override
public char[][] getCombinedIdArrays() {
return internalGetOrCacheChunk().getCombinedIdArrays();
}
@Override
public void fill(int id, byte data) {
internalGetOrCacheChunk().fill(id, data);
}
@Override
public void fillCuboid(int x1, int x2, int y1, int y2, int z1, int z2, int id, byte data) {
internalGetOrCacheChunk().fillCuboid(x1, x2, y1, y2, z1, z2, id, data);
}
@Override
public void addNotifyTask(Runnable run) {
internalGetOrCacheChunk().addNotifyTask(run);
}
@Override
public boolean hasNotifyTasks() {
return internalGetOrCacheChunk().hasNotifyTasks();
}
@Override
public void executeNotifyTasks() {
internalGetOrCacheChunk().executeNotifyTasks();
}
@Override
public void setTile(int x, int y, int z, CompoundTag tile) {
internalGetOrCacheChunk().setTile(x, y, z, tile);
}
@Override
public void setEntity(CompoundTag entity) {
internalGetOrCacheChunk().setEntity(entity);
}
@Override
public void removeEntity(UUID uuid) {
internalGetOrCacheChunk().removeEntity(uuid);
}
@Override
public void setBlock(int x, int y, int z, int id) {
internalGetOrCacheChunk().setBlock(x, y, z, id);
}
@Override
public void setBlock(int x, int y, int z, int id, int data) {
internalGetOrCacheChunk().setBlock(x, y, z, id, data);
}
@Override
public Set<CompoundTag> getEntities() {
return internalGetOrCacheChunk().getEntities();
}
@Override
public Set<UUID> getEntityRemoves() {
return internalGetOrCacheChunk().getEntityRemoves();
}
@Override
public Map<Short, CompoundTag> getTiles() {
return internalGetOrCacheChunk().getTiles();
}
@Override
public CompoundTag getTile(int x, int y, int z) {
return internalGetOrCacheChunk().getTile(x, y, z);
}
@Override
public void setBiome(int x, int z, BaseBiome biome) {
internalGetOrCacheChunk().setBiome(x, z, biome);
}
@Override
public void setBiome(int x, int z, byte biome) {
internalGetOrCacheChunk().setBiome(x, z, biome);
}
@Override
public void setBiome(byte biome) {
internalGetOrCacheChunk().setBiome(biome);
}
@Override
public void optimize() {
internalGetOrCacheChunk().optimize();
}
@Override
public boolean equals(Object obj) {
return internalGetOrCacheChunk().equals(obj);
}
@Override
public FaweChunk copy(boolean shallow) {
return internalGetOrCacheChunk().copy(shallow);
}
@Override
public void start() {
internalGetOrCacheChunk().start();
}
@Override
public void end() {
internalGetOrCacheChunk().end();
}
@Override
public FaweChunk call() {
return internalGetOrCacheChunk().call();
}
}

View File

@ -17,6 +17,8 @@ public class CleanTextureUtil extends TextureUtil {
for (; minIndex > 0 && parent.distances[minIndex - 1] == min; minIndex--) ;
for (; maxIndex < parent.distances.length - 1 && parent.distances[maxIndex + 1] == max; maxIndex++) ;
int num = maxIndex - minIndex + 1;
this.validMixBiomeColors = parent.validMixBiomeColors;
this.validMixBiomeIds = parent.validMixBiomeIds;
this.validBiomes = parent.validBiomes;
this.blockColors = parent.blockColors;
this.blockDistance = parent.blockDistance;
@ -42,4 +44,4 @@ public class CleanTextureUtil extends TextureUtil {
public int getMax() {
return max;
}
}
}

View File

@ -1,465 +0,0 @@
package com.boydti.fawe.util;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.example.Relighter;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
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.regions.CuboidRegion;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.File;
import java.util.Collection;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedDeque;
import javax.annotation.Nullable;
public class DelegateFaweQueue extends FaweQueue {
private FaweQueue parent;
public DelegateFaweQueue(FaweQueue parent) {
super(parent == null ? null : parent.getWEWorld());
this.parent = parent;
}
public FaweQueue getParent() {
return parent;
}
public void setParent(FaweQueue parent) {
this.parent = parent;
setWorld(parent.getWorldName());
}
@Override
public void sendChunk(int x, int z, int bitMask) {
parent.sendChunk(x, z, bitMask);
}
@Override
public boolean setMCA(int mcaX, int mcaZ, RegionWrapper region, Runnable whileLocked, boolean save, boolean load) {
return parent.setMCA(mcaX, mcaZ, region, whileLocked, save, load);
}
@Override
public boolean supportsChangeTask() {
return parent.supportsChangeTask();
}
@Override
public String getWorldName() {
return parent.getWorldName();
}
@Override
public void addEditSession(EditSession session) {
parent.addEditSession(session);
}
@Override
public World getWEWorld() {
return parent.getWEWorld();
}
@Override
public void setProgressTracker(RunnableVal2<ProgressType, Integer> progressTask) {
parent.setProgressTracker(progressTask);
}
@Override
public Set<EditSession> getEditSessions() {
return parent.getEditSessions();
}
@Override
public ConcurrentLinkedDeque<EditSession> getSessions() {
return parent.getSessions();
}
@Override
public void setSessions(ConcurrentLinkedDeque<EditSession> sessions) {
parent.setSessions(sessions);
}
@Override
public long getModified() {
return parent.getModified();
}
@Override
public void setModified(long modified) {
parent.setModified(modified);
}
@Override
public RunnableVal2<ProgressType, Integer> getProgressTask() {
return parent.getProgressTask();
}
@Override
public void setProgressTask(RunnableVal2<ProgressType, Integer> progressTask) {
parent.setProgressTask(progressTask);
}
@Override
public int getBiomeId(int x, int z) throws FaweException.FaweChunkLoadException {
return parent.getBiomeId(x, z);
}
@Override
public void setChangeTask(RunnableVal2<FaweChunk, FaweChunk> changeTask) {
parent.setChangeTask(changeTask);
}
@Override
public RunnableVal2<FaweChunk, FaweChunk> getChangeTask() {
return parent.getChangeTask();
}
@Override
public void optimize() {
parent.optimize();
}
@Override
public int setBlocks(CuboidRegion cuboid, int id, int data) {
return parent.setBlocks(cuboid, id, data);
}
@Override
public boolean setBlock(int x, int y, int z, int id, int data) {
return parent.setBlock(x, y, z, id, data);
}
@Override
public boolean setBlock(int x, int y, int z, int id) {
return parent.setBlock(x, y, z, id);
}
@Override
public boolean setBlock(int x, int y, int z, int id, int data, CompoundTag nbt) {
return parent.setBlock(x, y, z, id, data, nbt);
}
@Override
public void setTile(int x, int y, int z, CompoundTag tag) {
parent.setTile(x, y, z, tag);
}
@Override
public void setEntity(int x, int y, int z, CompoundTag tag) {
parent.setEntity(x, y, z, tag);
}
@Override
public void removeEntity(int x, int y, int z, UUID uuid) {
parent.removeEntity(x, y, z, uuid);
}
@Override
public boolean setBiome(int x, int z, BaseBiome biome) {
return parent.setBiome(x, z, biome);
}
@Override
public FaweChunk<?> getFaweChunk(int x, int z) {
return parent.getFaweChunk(x, z);
}
@Override
public Collection<FaweChunk> getFaweChunks() {
return parent.getFaweChunks();
}
@Override
public void setChunk(FaweChunk chunk) {
parent.setChunk(chunk);
}
@Override
public File getSaveFolder() {
return parent.getSaveFolder();
}
@Override
public int getMaxY() {
return parent.getMaxY();
}
@Override
public void forEachBlockInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
parent.forEachBlockInChunk(cx, cz, onEach);
}
@Override
public void forEachTileInChunk(int cx, int cz, RunnableVal2<Vector, BaseBlock> onEach) {
parent.forEachTileInChunk(cx, cz, onEach);
}
@Override
@Deprecated
public boolean regenerateChunk(int x, int z) {
return parent.regenerateChunk(x, z);
}
@Override
public boolean regenerateChunk(int x, int z, @Nullable BaseBiome biome, Long seed) {
return parent.regenerateChunk(x, z, biome, seed);
}
@Override
public void startSet(boolean parallel) {
parent.startSet(parallel);
}
@Override
public void endSet(boolean parallel) {
parent.endSet(parallel);
}
@Override
public int cancel() {
return parent.cancel();
}
@Override
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
parent.sendBlockUpdate(chunk, players);
}
@Deprecated
@Override
public boolean next() {
return parent.next();
}
@Override
public boolean next(int amount, long time) {
return parent.next(amount, time);
}
@Override
public void saveMemory() {
parent.saveMemory();
}
@Override
public void sendChunk(FaweChunk chunk) {
parent.sendChunk(chunk);
}
@Override
public void clear() {
parent.clear();
}
@Override
public void addNotifyTask(int x, int z, Runnable runnable) {
parent.addNotifyTask(x, z, runnable);
}
@Override
public boolean hasBlock(int x, int y, int z) throws FaweException.FaweChunkLoadException {
return parent.hasBlock(x, y, z);
}
@Override
public void addNotifyTask(Runnable runnable) {
parent.addNotifyTask(runnable);
}
@Override
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
return parent.getCombinedId4Data(x, y, z);
}
@Override
public int getCachedCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
return parent.getCachedCombinedId4Data(x, y, z);
}
@Override
public int getAdjacentLight(int x, int y, int z) {
return parent.getAdjacentLight(x, y, z);
}
@Override
public boolean hasSky() {
return parent.hasSky();
}
@Override
public int getSkyLight(int x, int y, int z) {
return parent.getSkyLight(x, y, z);
}
@Override
public int getLight(int x, int y, int z) {
return parent.getLight(x, y, z);
}
@Override
public int getEmmittedLight(int x, int y, int z) {
return parent.getEmmittedLight(x, y, z);
}
@Override
public CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException {
return parent.getTileEntity(x, y, z);
}
@Override
public int getCombinedId4Data(int x, int y, int z, int def) {
return parent.getCombinedId4Data(x, y, z, def);
}
@Override
public int getCachedCombinedId4Data(int x, int y, int z, int def) {
return parent.getCachedCombinedId4Data(x, y, z, def);
}
@Override
public int getCombinedId4DataDebug(int x, int y, int z, int def, EditSession session) {
return parent.getCombinedId4DataDebug(x, y, z, def, session);
}
@Override
public int getBrightness(int x, int y, int z) {
return parent.getBrightness(x, y, z);
}
@Override
public int getOpacityBrightnessPair(int x, int y, int z) {
return parent.getOpacityBrightnessPair(x, y, z);
}
@Override
public int getOpacity(int x, int y, int z) {
return parent.getOpacity(x, y, z);
}
@Override
public int size() {
return parent.size();
}
@Override
public boolean isEmpty() {
return parent.isEmpty();
}
@Override
public void flush() {
parent.flush();
}
@Override
public SetQueue.QueueStage getStage() {
return parent.getStage();
}
@Override
public void setStage(SetQueue.QueueStage stage) {
parent.setStage(stage);
}
@Override
public void flush(int time) {
parent.flush(time);
}
@Override
public void runTasks() {
parent.runTasks();
}
@Override
public void addTask(Runnable whenFree) {
parent.addTask(whenFree);
}
@Override
public boolean enqueue() {
return parent.enqueue();
}
@Override
public void dequeue() {
parent.dequeue();
}
@Override
public Relighter getRelighter() {
return parent.getRelighter();
}
@Override
public Vector getMinimumPoint() {
return parent.getMinimumPoint();
}
@Override
public Vector getMaximumPoint() {
return parent.getMaximumPoint();
}
@Override
public BaseBlock getLazyBlock(int x, int y, int z) {
return parent.getLazyBlock(x, y, z);
}
@Override
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
return parent.setBlock(x, y, z, block);
}
@Override
public BaseBlock getBlock(Vector position) {
return parent.getBlock(position);
}
@Override
public BaseBiome getBiome(Vector2D position) {
return parent.getBiome(position);
}
@Override
public boolean setBlock(Vector position, BaseBlock block) throws WorldEditException {
return parent.setBlock(position, block);
}
@Override
public boolean setBiome(Vector2D position, BaseBiome biome) {
return parent.setBiome(position, biome);
}
@Override
public FaweQueue getQueue() {
return parent.getQueue();
}
@Override
public Settings getSettings() {
return parent.getSettings();
}
@Override
public void setSettings(Settings settings) {
parent.setSettings(settings);
}
@Override
public void setWorld(String world) {
parent.setWorld(world);
}
}

View File

@ -189,6 +189,6 @@ public class EditSessionBuilder {
}
public EditSession build() {
return new EditSession(worldName, world, queue, player, limit, changeSet, allowedRegions, autoQueue, fastmode, checkMemory, combineStages, blockBag, eventBus, event);
return new EditSession(worldName, world, queue, player, limit, changeSet, allowedRegions, autoQueue, fastmode, checkMemory, combineStages, blockBag, eventBus, event);
}
}

View File

@ -946,10 +946,14 @@ public class MainUtil {
int innerArrayLength = Array.getLength(arr);
Class component = arr.getClass().getComponentType();
Object newInnerArray = Array.newInstance(component, innerArrayLength);
//copy each elem of the array
for (int i = 0; i < innerArrayLength; i++) {
Object elem = copyNd(Array.get(arr, i));
Array.set(newInnerArray, i, elem);
if (component.isPrimitive()) {
System.arraycopy(arr, 0, newInnerArray, 0, innerArrayLength);
} else {
//copy each elem of the array
for (int i = 0; i < innerArrayLength; i++) {
Object elem = copyNd(Array.get(arr, i));
Array.set(newInnerArray, i, elem);
}
}
return newInnerArray;
} else {

View File

@ -530,6 +530,10 @@ public class MathMan {
return Math.sqrt(sd / array.length);
}
public static final int absByte(int value) {
return (value ^ (value >> 8)) - (value >> 8);
}
public static final int mod(int x, int y) {
if (isPowerOfTwo(y)) {
return x & (y - 1);

View File

@ -345,11 +345,16 @@ public class ReflectionUtils {
return null;
}
private static Method[] sortMethods(Method[] methods) {
public static Method[] sortMethods(Method[] methods) {
Arrays.sort(methods, (o1, o2) -> o1.getName().compareTo(o2.getName()));
return methods;
}
public static Field[] sortFields(Field[] fields) {
Arrays.sort(fields, (o1, o2) -> o1.getName().compareTo(o2.getName()));
return fields;
}
public static Method findMethod(final Class<?> clazz, int index, final Class<?> returnType, Class... params) {
return findMethod(clazz, index, 0, 0, returnType, params);
}

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.util;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.wrappers.WorldWrapper;
import com.sk89q.worldedit.world.World;
import java.util.ArrayList;
import java.util.Collection;
@ -242,6 +243,8 @@ public class SetQueue {
}
public FaweQueue getNewQueue(World world, boolean fast, boolean autoqueue) {
world = WorldWrapper.unwrap(world);
if (world instanceof FaweQueue) return (FaweQueue) world;
FaweQueue queue = Fawe.imp().getNewQueue(world, fast);
if (autoqueue) {
queue.setStage(QueueStage.INACTIVE);

View File

@ -0,0 +1,7 @@
package com.boydti.fawe.util.image;
import java.awt.image.BufferedImage;
public interface Drawable {
public BufferedImage draw();
}

View File

@ -1,8 +1,7 @@
package com.boydti.fawe.util.image;
import java.awt.image.BufferedImage;
import java.io.Closeable;
public interface ImageViewer extends Closeable{
public void view(BufferedImage image);
public void view(Drawable drawable);
}

View File

@ -3,15 +3,14 @@ package com.boydti.fawe.wrappers;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.BlockWorldVector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EditSessionFactory;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.PlayerDirection;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.WorldVectorFace;
@ -200,10 +199,9 @@ public class PlayerWrapper extends AbstractPlayerActor {
@Override
public void floatAt(final int x, final int y, final int z, final boolean alwaysGlass) {
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
RuntimeException caught = null;
try {
final EditSession edit = factory.getEditSession(parent.getWorld(), -1, null, this);
EditSession edit = new EditSessionBuilder(parent.getWorld()).player(FawePlayer.wrap(this)).build();
edit.setBlockFast(new Vector(x, y - 1, z), new BaseBlock(BlockType.GLASS.getID()));
edit.flushQueue();
LocalSession session = Fawe.get().getWorldEdit().getSession(this);

View File

@ -25,6 +25,7 @@ import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.example.MappedFaweQueue;
import com.boydti.fawe.jnbt.anvil.HeightMapMCAGenerator;
import com.boydti.fawe.jnbt.anvil.MCAQueue;
import com.boydti.fawe.jnbt.anvil.MCAWorld;
import com.boydti.fawe.logging.LoggingChangeSet;
@ -48,7 +49,6 @@ import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.extent.FastWorldEditExtent;
import com.boydti.fawe.object.extent.FaweRegionExtent;
import com.boydti.fawe.object.extent.HeightBoundExtent;
import com.boydti.fawe.object.extent.LightingExtent;
import com.boydti.fawe.object.extent.MultiRegionExtent;
import com.boydti.fawe.object.extent.NullExtent;
import com.boydti.fawe.object.extent.ProcessedWEExtent;
@ -102,7 +102,6 @@ import com.sk89q.worldedit.function.mask.NoiseFilter2D;
import com.sk89q.worldedit.function.mask.RegionMask;
import com.sk89q.worldedit.function.operation.ChangeSetExecutor;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.util.RegionOffset;
@ -137,7 +136,7 @@ import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.SimpleWorld;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.WorldData;
@ -168,7 +167,7 @@ import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
* {@link Extent}s that are chained together. For example, history is logged
* using the {@link ChangeSetExtent}.</p>
*/
public class EditSession extends AbstractWorld implements HasFaweQueue, LightingExtent {
public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, SimpleWorld {
/**
* Used by {@link #setBlock(Vector, BaseBlock, Stage)} to
* determine which {@link Extent}s should be bypassed.
@ -181,6 +180,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
private String worldName;
private FaweQueue queue;
private boolean wrapped;
private boolean fastMode;
private AbstractDelegateExtent extent;
private HistoryExtent history;
private AbstractDelegateExtent bypassHistory;
@ -214,9 +214,10 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
public EditSession(@Nullable String worldName, @Nullable World world, @Nullable FaweQueue queue, @Nullable FawePlayer player, @Nullable FaweLimit limit, @Nullable FaweChangeSet changeSet, @Nullable RegionWrapper[] allowedRegions, @Nullable Boolean autoQueue, @Nullable Boolean fastmode, @Nullable Boolean checkMemory, @Nullable Boolean combineStages, @Nullable BlockBag blockBag, @Nullable EventBus bus, @Nullable EditSessionEvent event) {
super(world);
this.worldName = worldName == null ? world == null ? queue == null ? "" : queue.getWorldName() : Fawe.imp().getWorldName(world) : worldName;
if (world == null && this.worldName != null) world = FaweAPI.getWorld(this.worldName);
this.world = world = WorldWrapper.wrap((AbstractWorld) world);
this.world = world = WorldWrapper.wrap(world);
if (bus == null) {
bus = WorldEdit.getInstance().getEventBus();
}
@ -235,11 +236,6 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
limit = player.getLimit();
}
}
if (allowedRegions == null) {
if (player != null && !player.hasWorldEditBypass()) {
allowedRegions = player.getCurrentRegions();
}
}
if (autoQueue == null) {
autoQueue = true;
}
@ -250,8 +246,9 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
fastmode = player.getSession().hasFastMode();
}
}
this.fastMode = fastmode;
if (checkMemory == null) {
checkMemory = player != null && !fastmode;
checkMemory = player != null && !this.fastMode;
}
if (checkMemory) {
if (MemUtil.isMemoryLimitedSlow()) {
@ -264,21 +261,30 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
this.originalLimit = limit;
this.blockBag = limit.INVENTORY_MODE != 0 ? blockBag : null;
this.limit = limit.copy();
if (queue == null) {
if (world instanceof MCAWorld) {
queue = ((MCAWorld) world).getQueue();
boolean placeChunks = this.fastMode || this.limit.FAST_PLACEMENT;
World unwrapped = WorldWrapper.unwrap(world);
if (unwrapped instanceof FaweQueue) {
queue = (FaweQueue) unwrapped;
} else if (unwrapped instanceof MCAWorld) {
queue = ((MCAWorld) unwrapped).getQueue();
} else if (player != null && world.equals(player.getWorld())) {
queue = player.getFaweQueue(placeChunks, autoQueue);
} else {
queue = SetQueue.IMP.getNewQueue(this, fastmode || this.limit.FAST_PLACEMENT, autoQueue);
queue = SetQueue.IMP.getNewQueue(world, placeChunks, autoQueue);
}
}
if (combineStages == null) {
combineStages = Settings.IMP.HISTORY.COMBINE_STAGES && !(queue instanceof MCAQueue);
}
if (!this.limit.FAST_PLACEMENT || !queue.supportsChangeTask()) {
combineStages = false;
}
if (this.blockBag != null) {
combineStages = false;
combineStages =
// If it's enabled in the settings
Settings.IMP.HISTORY.COMBINE_STAGES
// If fast placement is disabled, it's slower to perform a copy on each chunk
&& this.limit.FAST_PLACEMENT
// If the specific queue doesn't support it
&& queue.supports(FaweQueue.Capability.CHANGE_TASKS)
// If the edit uses items from the inventory we can't use a delayed task
&& this.blockBag == null;
}
if (Settings.IMP.EXPERIMENTAL.ANVIL_QUEUE_MODE && !(queue instanceof MCAQueue)) {
queue = new MCAQueue(queue);
@ -298,7 +304,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
this.bypassAll = wrapExtent(new FastWorldEditExtent(world, queue), bus, event, Stage.BEFORE_CHANGE);
this.bypassHistory = (this.extent = wrapExtent(bypassAll, bus, event, Stage.BEFORE_REORDER));
if (!fastmode || changeSet != null) {
if (!this.fastMode || changeSet != null) {
if (changeSet == null) {
if (Settings.IMP.HISTORY.USE_DISK) {
UUID uuid = player == null ? CONSOLE : player.getUUID();
@ -337,6 +343,11 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
}
}
if (allowedRegions == null) {
if (player != null && !player.hasWorldEditBypass() && !(queue instanceof HeightMapMCAGenerator)) {
allowedRegions = player.getCurrentRegions();
}
}
this.maxY = getWorld() == null ? 255 : world.getMaxY();
if (allowedRegions != null) {
if (allowedRegions.length == 0) {
@ -354,6 +365,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
this.extent = new HeightBoundExtent(this.extent, this.limit, 0, maxY);
}
this.extent = wrapExtent(this.extent, bus, event, Stage.BEFORE_HISTORY);
setExtent(this.extent);
}
/**
@ -603,13 +615,23 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
* @return the change set
*/
public ChangeSet getChangeSet() {
return history != null ? history.getChangeSet() : changeTask;
return changeTask != null ? changeTask : history != null ? history.getChangeSet() : null;
}
public FaweChangeSet getChangeTask() {
return changeTask;
}
/**
* Set the ChangeSet without hooking into any recording mechanism or triggering any actions.<br/>
* Used internally to set the ChangeSet during completion to record custom changes which aren't normally recorded
* @param set
*/
public void setRawChangeSet(@Nullable FaweChangeSet set) {
changeTask = set;
changes++;
}
/**
* Change the ChangeSet being used for this EditSession
* - If history is disabled, no changeset can be set
@ -819,6 +841,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
* @param enabled true to enable
*/
public void setFastMode(final boolean enabled) {
this.fastMode = enabled;
disableHistory(enabled);
}
@ -1150,6 +1173,17 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
}
@Override
public boolean setBlock(Vector position, BaseBlock block) throws MaxChangedBlocksException {
try {
return setBlock(position, block, Stage.BEFORE_HISTORY);
} catch (MaxChangedBlocksException e) {
throw e;
} catch (WorldEditException e) {
throw new RuntimeException("Unexpected exception", e);
}
}
public boolean setBlock(int x, int y, int z, BaseBlock block) {
this.changes++;
try {
@ -1367,13 +1401,6 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
}
}
@Override
public
@Nullable
Operation commit() {
return null;
}
/**
* Count the number of blocks of a given list of types in a region.
*

View File

@ -190,6 +190,7 @@ public class LocalSession {
if (Settings.IMP.HISTORY.USE_DISK) {
MAX_HISTORY_SIZE = Integer.MAX_VALUE;
}
world = WorldWrapper.unwrap(world);
if (!world.equals(currentWorld)) {
this.uuid = uuid;
// Save history
@ -354,6 +355,7 @@ public class LocalSession {
history.clear();
historyNegativeIndex = 0;
historySize = 0;
currentWorld = null;
}
/**
@ -440,7 +442,7 @@ public class LocalSession {
return;
}
// Don't store anything if no changes were made
if (editSession.size() == 0 || editSession.hasFastMode()) {
if (editSession.size() == 0) {
return;
}
FaweChangeSet changeSet = (FaweChangeSet) editSession.getChangeSet();
@ -510,10 +512,10 @@ public class LocalSession {
*/
public EditSession undo(@Nullable BlockBag newBlockBag, Player player) {
checkNotNull(player);
loadSessionHistoryFromDisk(player.getUniqueId(), player.getWorld());
FawePlayer fp = FawePlayer.wrap(player);
loadSessionHistoryFromDisk(player.getUniqueId(), fp.getWorldForEditing());
if (getHistoryNegativeIndex() < history.size()) {
FaweChangeSet changeSet = getChangeSet(history.get(getHistoryIndex()));
final FawePlayer fp = FawePlayer.wrap(player);
EditSession newEditSession = new EditSessionBuilder(changeSet.getWorld())
.allowedRegionsEverywhere()
.checkMemory(false)
@ -557,12 +559,12 @@ public class LocalSession {
*/
public EditSession redo(@Nullable BlockBag newBlockBag, Player player) {
checkNotNull(player);
loadSessionHistoryFromDisk(player.getUniqueId(), player.getWorld());
FawePlayer fp = FawePlayer.wrap(player);
loadSessionHistoryFromDisk(player.getUniqueId(), fp.getWorldForEditing());
if (getHistoryNegativeIndex() > 0) {
setDirty();
historyNegativeIndex--;
FaweChangeSet changeSet = getChangeSet(history.get(getHistoryIndex()));
final FawePlayer fp = FawePlayer.wrap(player);
EditSession newEditSession = new EditSessionBuilder(changeSet.getWorld())
.allowedRegionsEverywhere()
.checkMemory(false)
@ -1288,11 +1290,15 @@ public class LocalSession {
BlockBag blockBag = getBlockBag(player);
// Create an edit session
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(player.isPlayer() ? player.getWorld() : null,
getBlockChangeLimit(), blockBag, player);
editSession.setFastMode(fastMode);
World world = player.getWorld();
boolean isPlayer = player.isPlayer();
EditSessionBuilder builder = new EditSessionBuilder(world);
if (player.isPlayer()) builder.player(FawePlayer.wrap(player));
builder.blockBag(blockBag);
builder.fastmode(fastMode);
EditSession editSession = builder.build();
Request.request().setEditSession(editSession);
if (mask != null) {
editSession.setMask(mask);

View File

@ -474,10 +474,17 @@ public class BrushCommands extends MethodCommands {
try {
MultiClipboardHolder clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), clipboard, true);
if (clipboards == null) {
BBC.SCHEMATIC_NOT_FOUND.send(player, clipboard);
return null;
}
List<ClipboardHolder> holders = clipboards.getHolders();
if (holders == null) {
BBC.SCHEMATIC_NOT_FOUND.send(player, clipboard);
return null;
}
return get(context)
.setBrush(new PopulateSchem(mask, clipboards.getHolders(), (int) density, rotate))
.setBrush(new PopulateSchem(mask, holders, (int) density, rotate))
.setSize(radius);
} catch (IOException e) {
throw new RuntimeException(e);

View File

@ -25,9 +25,11 @@ public class BrushProcessor implements CallableProcessor<BrushSettings> {
LocalSession session = worldEdit.getSessionManager().get(actor);
session.setTool(null, (Player) actor);
BrushTool tool = session.getBrushTool((Player) actor);
tool.setPrimary(settings);
tool.setSecondary(settings);
BBC.BRUSH_EQUIPPED.send(actor, ((String) locals.get("arguments")).split(" ")[1]);
if (tool != null) {
tool.setPrimary(settings);
tool.setSecondary(settings);
BBC.BRUSH_EQUIPPED.send(actor, ((String) locals.get("arguments")).split(" ")[1]);
}
return null;
}
}

View File

@ -437,10 +437,7 @@ public class ClipboardCommands extends MethodCommands {
@Switch('a') final boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
@Switch('s') boolean selectPasted) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
System.out.println(holder);
final Clipboard clipboard = holder.getClipboard();
System.out.println(clipboard.getDimensions());
System.out.println(clipboard.getClass());
final Vector origin = clipboard.getOrigin();
final Vector to = atOrigin ? origin : session.getPlacementPosition(player);

View File

@ -30,7 +30,6 @@ import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.visitor.Fast2DIterator;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.SetQueue;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
@ -138,7 +137,7 @@ public class RegionCommands extends MethodCommands {
public void getlighting(Player player) throws WorldEditException {
FawePlayer fp = FawePlayer.wrap(player);
final FaweLocation loc = fp.getLocation();
FaweQueue queue = SetQueue.IMP.getNewQueue(loc.world, true, false);
FaweQueue queue = fp.getFaweQueue(false);
fp.sendMessage("Light: " + queue.getEmmittedLight(loc.x, loc.y, loc.z) + " | " + queue.getSkyLight(loc.x, loc.y, loc.z));
}
@ -193,7 +192,7 @@ public class RegionCommands extends MethodCommands {
final FaweLocation loc = fp.getLocation();
final int cx = loc.x >> 4;
final int cz = loc.z >> 4;
final NMSMappedFaweQueue queue = (NMSMappedFaweQueue) SetQueue.IMP.getNewQueue(fp.getWorld(), true, false);
final NMSMappedFaweQueue queue = (NMSMappedFaweQueue) fp.getFaweQueue(false);
for (Vector pt : region) {
queue.setBlockLight((int) pt.getX(), (int) pt.getY(), (int) pt.getZ(), value);
}
@ -217,7 +216,7 @@ public class RegionCommands extends MethodCommands {
final FaweLocation loc = fp.getLocation();
final int cx = loc.x >> 4;
final int cz = loc.z >> 4;
final NMSMappedFaweQueue queue = (NMSMappedFaweQueue) SetQueue.IMP.getNewQueue(fp.getWorld(), true, false);
final NMSMappedFaweQueue queue = (NMSMappedFaweQueue) fp.getFaweQueue(false);
for (Vector pt : region) {
queue.setSkyLight((int) pt.getX(), (int) pt.getY(), (int) pt.getZ(), value);
}

View File

@ -53,7 +53,6 @@ import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.eventbus.Subscribe;
import com.sk89q.worldedit.world.World;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.EnumMap;
@ -277,24 +276,8 @@ public class PlatformManager {
if (base instanceof Player) {
Player player = (Player) base;
Player permActor = queryCapability(Capability.PERMISSIONS).matchPlayer(player);
if (permActor == null) {
permActor = player;
}
Player cuiActor = queryCapability(Capability.WORLDEDIT_CUI).matchPlayer(player);
if (cuiActor == null) {
cuiActor = player;
}
try {
Class<?> clazz = Class.forName("com.sk89q.worldedit.extension.platform.PlayerProxy");
Constructor<?> constructor = clazz.getDeclaredConstructor(Player.class, Actor.class, Actor.class, World.class);
constructor.setAccessible(true);
return (T) constructor.newInstance(player, permActor, cuiActor, getWorldForEditing(player.getWorld()));
} catch (Throwable e) {
throw new RuntimeException(e);
}
FawePlayer fp = FawePlayer.wrap(player);
return (T) fp.createProxy();
} else {
return base;
}

View File

@ -8,6 +8,7 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.internal.LocalWorldAdapter;
import com.sk89q.worldedit.internal.cui.CUIEvent;
import com.sk89q.worldedit.session.SessionKey;
import com.sk89q.worldedit.util.Location;
@ -20,6 +21,7 @@ public class PlayerProxy extends AbstractPlayerActor {
private final Actor permActor;
private final Actor cuiActor;
private final World world;
private Vector offset = Vector.ZERO;
public PlayerProxy(Player basePlayer, Actor permActor, Actor cuiActor, World world) {
Preconditions.checkNotNull(basePlayer);
@ -32,6 +34,10 @@ public class PlayerProxy extends AbstractPlayerActor {
this.world = world;
}
public void setOffset(Vector position) {
this.offset = position;
}
public UUID getUniqueId() {
return this.basePlayer.getUniqueId();
}
@ -62,11 +68,13 @@ public class PlayerProxy extends AbstractPlayerActor {
}
public Location getLocation() {
return this.basePlayer.getLocation();
Location loc = this.basePlayer.getLocation();
return new Location(loc.getExtent(), loc.toVector().add(offset), loc.getDirection());
}
public WorldVector getPosition() {
return this.basePlayer.getPosition();
WorldVector wv = this.basePlayer.getPosition();
return new WorldVector(LocalWorldAdapter.wrap(world), wv.add(offset));
}
public double getPitch() {

View File

@ -46,6 +46,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class AbstractDelegateExtent implements LightingExtent {
private transient final Extent extent;
private MutableBlockVector mutable = new MutableBlockVector(0, 0, 0);
/**
* Create a new instance.
@ -64,6 +65,11 @@ public class AbstractDelegateExtent implements LightingExtent {
return 0;
}
@Override
public int getMaxY() {
return extent.getMaxY();
}
public int getBlockLight(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getBlockLight(x, y, z);
@ -115,8 +121,6 @@ public class AbstractDelegateExtent implements LightingExtent {
return extent.getLazyBlock(position);
}
private MutableBlockVector mutable = new MutableBlockVector(0, 0, 0);
@Override
public BaseBlock getLazyBlock(int x, int y, int z) {
mutable.mutX(x);
@ -188,6 +192,16 @@ public class AbstractDelegateExtent implements LightingExtent {
return super.toString() + ":" + extent.toString();
}
@Override
public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
return extent.getNearestSurfaceLayer(x, z, y, minY, maxY);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
}
@Override
public final
@Nullable

View File

@ -66,6 +66,10 @@ public interface Extent extends InputExtent, OutputExtent {
return getLazyBlock(MutableBlockVector.get(x, y, z));
}
default int getMaxY() {
return 255;
}
default public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
int clearanceAbove = maxY - y;
int clearanceBelow = y - minY;
@ -95,7 +99,12 @@ public interface Extent extends InputExtent, OutputExtent {
for (int layer = y - clearance - 1; layer >= minY; layer--) {
block = getLazyBlock(x, layer, z);
if (FaweCache.isLiquidOrGas(block.getId()) != state) {
return ((layer + offset) << 3) - (7 - (state ? block.getData() : data1));
// int blockHeight = (newHeight) >> 3;
// int layerHeight = (newHeight) & 0x7;
int data = (state ? block.getData() : data1);
return ((layer + offset) << 3) + 0;
}
data1 = block.getData();
}
@ -171,6 +180,12 @@ public interface Extent extends InputExtent, OutputExtent {
}
}
default boolean contain(Vector pt) {
Vector min = getMinimumPoint();
Vector max = getMaximumPoint();
return (pt.containedWithin(min, max));
}
default public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException {
spawnResource(region, new OreGen(this, mask, material, size, minY, maxY), rarity, frequency);
}

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.internal.command;
import com.boydti.fawe.object.FawePlayer;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
@ -85,7 +86,7 @@ public class WorldEditBinding extends BindingHelper {
public Object getSelection(ArgumentStack context, Selection selection) throws IncompleteRegionException, ParameterException {
Player sender = getPlayer(context);
LocalSession session = worldEdit.getSessionManager().get(sender);
return session.getSelection(sender.getWorld());
return session.getSelection(FawePlayer.wrap(sender).getWorldForEditing());
}
/**
@ -338,4 +339,4 @@ public class WorldEditBinding extends BindingHelper {
return WorldEditBinding.class;
}
}
}

View File

@ -84,9 +84,19 @@ public class HeightMap {
} else {
// Store current heightmap data
data = new int[width * height];
for (int z = 0; z < height; ++z) {
for (int x = 0; x < width; ++x) {
data[z * width + x] = session.getHighestTerrainBlock(x + minX, z + minZ, minY, maxY, naturalOnly);
int index = 0;
if (naturalOnly) {
for (int z = 0; z < height; ++z) {
for (int x = 0; x < width; ++x, index++) {
data[index] = session.getHighestTerrainBlock(x + minX, z + minZ, minY, maxY, naturalOnly);
}
}
} else {
int yTmp = 255;
for (int z = 0; z < height; ++z) {
for (int x = 0; x < width; ++x, index++) {
data[index] = yTmp = session.getNearestSurfaceTerrainBlock(x + minX, z + minZ, yTmp, minY, maxY);
}
}
}
}
@ -125,18 +135,7 @@ public class HeightMap {
return layers ? applyLayers(newData) : apply(newData);
}
// TODO
// public int averageFilter(int iterations) throws WorldEditException {
// Vector min = region.getMinimumPoint();
// Vector max = region.getMaximumPoint();
// int shift = layers ? 3 : 0;
// AverageHeightMapFilter filter = new AverageHeightMapFilter(data, width, height, min.getBlockY() << shift, max.getBlockY() << shift);
// int[] newData = filter.filter(iterations);
// return layers ? applyLayers(newData) : apply(newData);
// }
public int applyLayers(int[] data) throws WorldEditException {
System.out.println("Layers");
checkNotNull(data);
Vector minY = region.getMinimumPoint();
@ -154,6 +153,28 @@ public class HeightMap {
// Apply heightmap
int maxY4 = maxY << 4;
int index = 0;
if (!session.hasExtraExtents()) {
// TODO fast change height
// int chunkZLen = (height + 15) >> 4;
// int chunkXLen = (width + 15) >> 4;
// FaweQueue queue = session.getQueue();
// if (queue instanceof MappedFaweQueue) {
// MappedFaweQueue mfq = (MappedFaweQueue) queue;
// for (int cz = 0; cz < chunkZLen; cz++) {
// for (int cx = 0; cx < chunkXLen; cx++) {
// mfq.queueChunkLoad(cx, cz, new RunnableVal() {
// @Override
// public void run(Object chunk) {
// todo
// }
// });
// }
// }
// }
}
for (int z = 0; z < height; ++z) {
int zr = z + originZ;
for (int x = 0; x < width; ++x) {
@ -209,7 +230,6 @@ public class HeightMap {
}
}
}
return blocksChanged;
}

View File

@ -0,0 +1,214 @@
/*
* 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.util;
import com.boydti.fawe.wrappers.WorldWrapper;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.internal.LocalWorldAdapter;
/**
* This class uses an inefficient method to figure out what block a player
* is looking towards.
*
* <p>Originally written by toi. It was ported to WorldEdit and trimmed down by
* sk89q. Thanks to Raphfrk for optimization of toi's original class.</p>
*/
public class TargetBlock {
private LocalWorld world;
private int maxDistance;
private double checkDistance, curDistance;
private Vector targetPos = new Vector();
private Vector targetPosDouble = new Vector();
private Vector prevPos = new Vector();
private Vector offset = new Vector();
/**
* Constructor requiring a player, uses default values
*
* @param player player to work with
*/
public TargetBlock(LocalPlayer player) {
this.world = LocalWorldAdapter.adapt(player.getWorld());
this.setValues(player.getPosition(), player.getYaw(), player.getPitch(),
300, 1.65, 0.2);
}
/**
* Constructor requiring a player, max distance and a checking distance
*
* @param player LocalPlayer to work with
* @param maxDistance how far it checks for blocks
* @param checkDistance how often to check for blocks, the smaller the more precise
*/
public TargetBlock(LocalPlayer player, int maxDistance, double checkDistance) {
this((Player) player, maxDistance, checkDistance);
}
/**
* Constructor requiring a player, max distance and a checking distance
*
* @param player LocalPlayer to work with
* @param maxDistance how far it checks for blocks
* @param checkDistance how often to check for blocks, the smaller the more precise
*/
public TargetBlock(Player player, int maxDistance, double checkDistance) {
this.world = LocalWorldAdapter.adapt(player.getWorld());
this.setValues(player.getPosition(), player.getYaw(), player.getPitch(), maxDistance, 1.65, checkDistance);
}
/**
* Set the values, all constructors uses this function
*
* @param loc location of the view
* @param xRotation the X rotation
* @param yRotation the Y rotation
* @param maxDistance how far it checks for blocks
* @param viewHeight where the view is positioned in y-axis
* @param checkDistance how often to check for blocks, the smaller the more precise
*/
private void setValues(Vector loc, double xRotation, double yRotation,
int maxDistance, double viewHeight, double checkDistance) {
this.maxDistance = maxDistance;
this.checkDistance = checkDistance;
this.curDistance = 0;
xRotation = (xRotation + 90) % 360;
yRotation = yRotation * -1;
double h = (checkDistance * Math.cos(Math.toRadians(yRotation)));
offset = new Vector((h * Math.cos(Math.toRadians(xRotation))),
(checkDistance * Math.sin(Math.toRadians(yRotation))),
(h * Math.sin(Math.toRadians(xRotation))));
targetPosDouble = loc.add(0, viewHeight, 0);
targetPos = targetPosDouble.toBlockPoint();
prevPos = targetPos;
}
/**
* Returns any block at the sight. Returns null if out of range or if no
* viable target was found. Will try to return the last valid air block it finds.
*
* @return Block
*/
public BlockWorldVector getAnyTargetBlock() {
boolean searchForLastBlock = true;
BlockWorldVector lastBlock = null;
while (getNextBlock() != null) {
if (world.getBlockType(getCurrentBlock()) == BlockID.AIR) {
if (searchForLastBlock) {
lastBlock = getCurrentBlock();
if (lastBlock.getBlockY() <= 0 || lastBlock.getBlockY() >= world.getMaxY()) {
searchForLastBlock = false;
}
}
} else {
break;
}
}
BlockWorldVector currentBlock = getCurrentBlock();
return (currentBlock != null ? currentBlock : lastBlock);
}
/**
* Returns the block at the sight. Returns null if out of range or if no
* viable target was found
*
* @return Block
*/
public BlockWorldVector getTargetBlock() {
while (getNextBlock() != null && world.getBlockType(getCurrentBlock()) == 0) ;
return getCurrentBlock();
}
/**
* Returns the block at the sight. Returns null if out of range or if no
* viable target was found
*
* @return Block
*/
public BlockWorldVector getSolidTargetBlock() {
while (getNextBlock() != null && BlockType.canPassThrough(world.getBlock(getCurrentBlock()))) ;
return getCurrentBlock();
}
/**
* Get next block
*
* @return next block position
*/
public BlockWorldVector getNextBlock() {
prevPos = targetPos;
do {
curDistance += checkDistance;
targetPosDouble = offset.add(targetPosDouble.getX(),
targetPosDouble.getY(),
targetPosDouble.getZ());
targetPos = targetPosDouble.toBlockPoint();
} while (curDistance <= maxDistance
&& targetPos.getBlockX() == prevPos.getBlockX()
&& targetPos.getBlockY() == prevPos.getBlockY()
&& targetPos.getBlockZ() == prevPos.getBlockZ());
if (curDistance > maxDistance) {
return null;
}
return new BlockWorldVector(world, targetPos);
}
/**
* Returns the current block along the line of vision
*
* @return block position
*/
public BlockWorldVector getCurrentBlock() {
if (curDistance > maxDistance) {
return null;
} else {
return new BlockWorldVector(world, targetPos);
}
}
/**
* Returns the previous block in the aimed path
*
* @return block position
*/
public BlockWorldVector getPreviousBlock() {
return new BlockWorldVector(world, prevPos);
}
public WorldVectorFace getAnyTargetBlockFace() {
getAnyTargetBlock();
return WorldVectorFace.getWorldVectorFace(world, getCurrentBlock(), getPreviousBlock());
}
public WorldVectorFace getTargetBlockFace() {
getAnyTargetBlock();
return WorldVectorFace.getWorldVectorFace(world, getCurrentBlock(), getPreviousBlock());
}
}

View File

@ -0,0 +1,186 @@
package com.sk89q.worldedit.world;
import com.boydti.fawe.util.SetQueue;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.TreeGenerator;
import javax.annotation.Nullable;
public interface SimpleWorld extends World {
@Override
default boolean useItem(Vector position, BaseItem item, Direction face) {
return false;
}
@Override
default boolean setBlockType(Vector position, int type) {
try {
return setBlock(position, new BaseBlock(type));
} catch (WorldEditException ignored) {
return false;
}
}
@Override
default void setBlockData(Vector position, int data) {
try {
setBlock(position, new BaseBlock(getLazyBlock(position).getType(), data));
} catch (WorldEditException ignored) {
}
}
@Override
default boolean setTypeIdAndData(Vector position, int type, int data) {
try {
return setBlock(position, new BaseBlock(type, data));
} catch (WorldEditException ignored) {
return false;
}
}
@Override
default boolean setBlock(Vector pt, BaseBlock block) throws WorldEditException {
return setBlock(pt, block, true);
}
@Override
default int getMaxY() {
return getMaximumPoint().getBlockY();
}
@Override
default boolean isValidBlockType(int type) {
return BlockType.fromID(type) != null;
}
@Override
default boolean usesBlockData(int type) {
// We future proof here by assuming all unknown blocks use data
return BlockType.usesData(type) || BlockType.fromID(type) == null;
}
@Override
default Mask createLiquidMask() {
return new BlockMask(this,
new BaseBlock(BlockID.STATIONARY_LAVA, -1),
new BaseBlock(BlockID.LAVA, -1),
new BaseBlock(BlockID.STATIONARY_WATER, -1),
new BaseBlock(BlockID.WATER, -1));
}
@Override
default int getBlockType(Vector pt) {
return getLazyBlock(pt).getType();
}
@Override
default int getBlockData(Vector pt) {
return getLazyBlock(pt).getData();
}
@Override
default void dropItem(Vector pt, BaseItemStack item, int times) {
for (int i = 0; i < times; ++i) {
dropItem(pt, item);
}
}
@Override
default void simulateBlockMine(Vector pt) {
BaseBlock block = getLazyBlock(pt);
BaseItemStack stack = BlockType.getBlockDrop(block.getId(), (short) block.getData());
if (stack != null) {
final int amount = stack.getAmount();
if (amount > 1) {
dropItem(pt, new BaseItemStack(stack.getType(), 1, stack.getData()), amount);
} else {
dropItem(pt, stack, amount);
}
}
try {
setBlock(pt, new BaseBlock(BlockID.AIR));
} catch (WorldEditException e) {
throw new RuntimeException(e);
}
}
@Override
default boolean generateTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return generateTree(TreeGenerator.TreeType.TREE, editSession, pt);
}
@Override
default boolean generateBigTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return generateTree(TreeGenerator.TreeType.BIG_TREE, editSession, pt);
}
@Override
default boolean generateBirchTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return generateTree(TreeGenerator.TreeType.BIRCH, editSession, pt);
}
@Override
default boolean generateRedwoodTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return generateTree(TreeGenerator.TreeType.REDWOOD, editSession, pt);
}
@Override
default boolean generateTallRedwoodTree(EditSession editSession, Vector pt) throws MaxChangedBlocksException {
return generateTree(TreeGenerator.TreeType.TALL_REDWOOD, editSession, pt);
}
@Override
default void checkLoadedChunk(Vector pt) {
}
@Override
default void fixAfterFastMode(Iterable<BlockVector2D> chunks) {
}
@Override
default void fixLighting(Iterable<BlockVector2D> chunks) {
}
@Override
default boolean playEffect(Vector position, int type, int data) {
return false;
}
@SuppressWarnings("deprecation")
@Override
default boolean queueBlockBreakEffect(Platform server, Vector position, int blockId, double priority) {
SetQueue.IMP.addTask(() -> playEffect(position, 2001, blockId));
return true;
}
@Override
default Vector getMinimumPoint() {
return new Vector(-30000000, 0, -30000000);
}
@Override
default Vector getMaximumPoint() {
return new Vector(30000000, 255, 30000000);
}
@Override
default @Nullable
Operation commit() {
return null;
}
}

View File

@ -1,7 +1,6 @@
package com.thevoxelbox.voxelsniper;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.bukkit.wrapper.AsyncWorld;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
@ -167,7 +166,7 @@ public class Sniper {
Player bukkitPlayer = getPlayer();
World bukkitWorld = bukkitPlayer.getWorld();
FaweQueue baseQueue = FaweAPI.createQueue(fp.getLocation().world, false);
FaweQueue baseQueue = fp.getFaweQueue(false);
RegionWrapper[] mask = WEManager.IMP.getMask(fp);
if (mask.length == 0) {
BBC.NO_REGION.send(fp);