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:
parent
0dbb6171ef
commit
395b46c842
@ -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();
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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: {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -159,7 +159,6 @@ public abstract class FaweChangeSet implements ChangeSet {
|
||||
builder.allowedRegionsEverywhere();
|
||||
}
|
||||
EditSession editSession = builder.build();
|
||||
editSession.setSize(1);
|
||||
return editSession;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -0,0 +1,7 @@
|
||||
package com.boydti.fawe.util.image;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public interface Drawable {
|
||||
public BufferedImage draw();
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
214
core/src/main/java/com/sk89q/worldedit/util/TargetBlock.java
Normal file
214
core/src/main/java/com/sk89q/worldedit/util/TargetBlock.java
Normal 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());
|
||||
}
|
||||
|
||||
}
|
186
core/src/main/java/com/sk89q/worldedit/world/SimpleWorld.java
Normal file
186
core/src/main/java/com/sk89q/worldedit/world/SimpleWorld.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user