Various
update to 1.9.4 progress notifications lighting fixes optimizations Only stable for bukkit 1.8/1.9
This commit is contained in:
parent
947ff54a4c
commit
b5a8eb2176
@ -3,14 +3,18 @@ package com.boydti.fawe.bukkit;
|
|||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.object.FaweLocation;
|
import com.boydti.fawe.object.FaweLocation;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.command.ConsoleCommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
public class BukkitPlayer extends FawePlayer<Player> {
|
public class BukkitPlayer extends FawePlayer<Player> {
|
||||||
|
|
||||||
|
private static ConsoleCommandSender console;
|
||||||
|
|
||||||
public BukkitPlayer(final Player parent) {
|
public BukkitPlayer(final Player parent) {
|
||||||
super(parent);
|
super(parent);
|
||||||
}
|
}
|
||||||
@ -49,6 +53,27 @@ public class BukkitPlayer extends FawePlayer<Player> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetTitle() {
|
||||||
|
sendTitle("","");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendTitle(String title, String sub) {
|
||||||
|
try {
|
||||||
|
Method methodSendTitle = Player.class.getDeclaredMethod("sendTitle", String.class, String.class);
|
||||||
|
methodSendTitle.invoke(parent, ChatColor.GOLD + title, ChatColor.GOLD + sub);
|
||||||
|
return;
|
||||||
|
} catch (Throwable ignore) {}
|
||||||
|
if (console == null) {
|
||||||
|
console = Bukkit.getConsoleSender();
|
||||||
|
Bukkit.getServer().dispatchCommand(console, "gamerule sendCommandFeedback false");
|
||||||
|
Bukkit.getServer().dispatchCommand(console, "title " + getName() + " times 0 60 20");
|
||||||
|
}
|
||||||
|
Bukkit.getServer().dispatchCommand(console, "title " + getName() + " subtitle [{\"text\":\"" + sub + "\",\"color\":\"gold\"}]");
|
||||||
|
Bukkit.getServer().dispatchCommand(console, "title " + getName() + " title [{\"text\":\"" + title + "\",\"color\":\"gold\"}]");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(final String message) {
|
public void sendMessage(final String message) {
|
||||||
this.parent.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
|
this.parent.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
|
||||||
|
@ -195,7 +195,7 @@ public class FaweBukkit implements IFawe, Listener {
|
|||||||
debug("====== NO NMS BLOCK PLACER FOUND ======");
|
debug("====== NO NMS BLOCK PLACER FOUND ======");
|
||||||
debug("FAWE couldn't find a fast block placer");
|
debug("FAWE couldn't find a fast block placer");
|
||||||
debug("Bukkit version: " + Bukkit.getVersion());
|
debug("Bukkit version: " + Bukkit.getVersion());
|
||||||
debug("Supported NMS versions: 1.8, 1.9");
|
debug("Supported NMS versions: 1.8.8, 1.9.4");
|
||||||
debug("Fallback placer: " + BukkitQueue_All.class);
|
debug("Fallback placer: " + BukkitQueue_All.class);
|
||||||
debug("=======================================");
|
debug("=======================================");
|
||||||
hasNMS = false;
|
hasNMS = false;
|
||||||
|
@ -19,6 +19,7 @@ public class LoggingChangeSet extends FaweChangeSet {
|
|||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
public LoggingChangeSet(FawePlayer<Player> player, FaweChangeSet parent, IBlocksHubApi api) {
|
public LoggingChangeSet(FawePlayer<Player> player, FaweChangeSet parent, IBlocksHubApi api) {
|
||||||
|
super(parent.getWorld());
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.name = player.getName();
|
this.name = player.getName();
|
||||||
this.api = api;
|
this.api = api;
|
||||||
|
@ -22,12 +22,11 @@ public class BukkitEditSessionWrapper_0 extends EditSessionWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Extent getHistoryExtent(EditSession session, FaweLimit limit, Extent parent, FaweChangeSet set, FaweQueue queue, FawePlayer<?> player) {
|
public FaweChangeSet wrapChangeSet(EditSession session, FaweLimit limit, Extent parent, FaweChangeSet set, FaweQueue queue, FawePlayer<?> player) {
|
||||||
if (this.hook != null) {
|
if (this.hook != null) {
|
||||||
// If we are doing logging, use a custom logging ChangeSet
|
// If we are doing logging, use a custom logging ChangeSet
|
||||||
set = hook.getLoggingChangeSet(session, limit, parent, set, queue, player);
|
return hook.getLoggingChangeSet(session, limit, parent, set, queue, player);
|
||||||
}
|
}
|
||||||
// Now return the normal history extent
|
return set;
|
||||||
return super.getHistoryExtent(session, limit, parent, set, queue, player);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.boydti.fawe.bukkit.v0;
|
package com.boydti.fawe.bukkit.v0;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.example.CharFaweChunk;
|
import com.boydti.fawe.example.CharFaweChunk;
|
||||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||||
@ -14,6 +15,10 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@ -21,18 +26,26 @@ import org.bukkit.block.Block;
|
|||||||
|
|
||||||
public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMappedFaweQueue<World, CHUNK, CHUNKSECTIONS, SECTION> {
|
public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMappedFaweQueue<World, CHUNK, CHUNKSECTIONS, SECTION> {
|
||||||
|
|
||||||
public final BukkitImplAdapter adapter;
|
public Object adapter;
|
||||||
public Method methodToNative;
|
public Method methodToNative;
|
||||||
public Method methodFromNative;
|
public Method methodFromNative;
|
||||||
|
|
||||||
public BukkitQueue_0(final String world) {
|
public BukkitQueue_0(final String world) {
|
||||||
super(world);
|
super(world);
|
||||||
|
setupAdapter(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupAdapter(BukkitImplAdapter adapter) {
|
||||||
try {
|
try {
|
||||||
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
|
WorldEditPlugin instance = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
|
||||||
Field fieldAdapter = WorldEditPlugin.class.getDeclaredField("bukkitAdapter");
|
Field fieldAdapter = WorldEditPlugin.class.getDeclaredField("bukkitAdapter");
|
||||||
fieldAdapter.setAccessible(true);
|
fieldAdapter.setAccessible(true);
|
||||||
this.adapter = (BukkitImplAdapter) fieldAdapter.get(instance);
|
if ((this.adapter = adapter) != null) {
|
||||||
for (Method method : adapter.getClass().getDeclaredMethods()) {
|
fieldAdapter.set(instance, adapter);
|
||||||
|
} else {
|
||||||
|
this.adapter = fieldAdapter.get(instance);
|
||||||
|
}
|
||||||
|
for (Method method : this.adapter.getClass().getDeclaredMethods()) {
|
||||||
switch (method.getName()) {
|
switch (method.getName()) {
|
||||||
case "toNative":
|
case "toNative":
|
||||||
methodToNative = method;
|
methodToNative = method;
|
||||||
@ -45,7 +58,12 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException(e);
|
e.printStackTrace();
|
||||||
|
Fawe.debug("====== NO NATIVE WORLDEDIT ADAPTER ======");
|
||||||
|
Fawe.debug("Try updating WorldEdit: ");
|
||||||
|
Fawe.debug(" - http://builds.enginehub.org/job/worldedit?branch=master");
|
||||||
|
Fawe.debug("See also: http://wiki.sk89q.com/wiki/WorldEdit/Bukkit_adapters");
|
||||||
|
Fawe.debug("=========================================");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,8 +87,14 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
|
|||||||
return world.regenerateChunk(x, z);
|
return world.regenerateChunk(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean fixLighting(FaweChunk fc, boolean fixAll) {
|
public CharFaweChunk getPrevious(CharFaweChunk fs, CHUNKSECTIONS sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean fixLighting(FaweChunk fc, RelightMode mode) {
|
||||||
// Not implemented
|
// Not implemented
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -121,7 +145,7 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
|
|||||||
final Chunk chunk = fs.getChunk();
|
final Chunk chunk = fs.getChunk();
|
||||||
chunk.load(true);
|
chunk.load(true);
|
||||||
final World world = chunk.getWorld();
|
final World world = chunk.getWorld();
|
||||||
char[][] sections = fs.getIdArrays();
|
char[][] sections = fs.getCombinedIdArrays();
|
||||||
boolean done = false;
|
boolean done = false;
|
||||||
boolean more = false;
|
boolean more = false;
|
||||||
// Efficiently merge sections
|
// Efficiently merge sections
|
||||||
|
@ -2,11 +2,11 @@ package com.boydti.fawe.bukkit.v1_8;
|
|||||||
|
|
||||||
import com.boydti.fawe.bukkit.ABukkitMain;
|
import com.boydti.fawe.bukkit.ABukkitMain;
|
||||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||||
import com.boydti.fawe.bukkit.v1_8.BukkitQueue18R3;
|
|
||||||
import com.boydti.fawe.object.EditSessionWrapper;
|
import com.boydti.fawe.object.EditSessionWrapper;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
|
|
||||||
public class BukkitMain_18 extends ABukkitMain {
|
public class BukkitMain_18 extends ABukkitMain {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BukkitQueue_0 getQueue(String world) {
|
public BukkitQueue_0 getQueue(String world) {
|
||||||
return new BukkitQueue18R3(world);
|
return new BukkitQueue18R3(world);
|
||||||
|
@ -21,16 +21,19 @@ import com.sk89q.worldedit.internal.Constants;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import net.minecraft.server.v1_8_R3.BlockPosition;
|
import net.minecraft.server.v1_8_R3.BlockPosition;
|
||||||
import net.minecraft.server.v1_8_R3.ChunkCoordIntPair;
|
import net.minecraft.server.v1_8_R3.ChunkCoordIntPair;
|
||||||
import net.minecraft.server.v1_8_R3.ChunkSection;
|
import net.minecraft.server.v1_8_R3.ChunkSection;
|
||||||
import net.minecraft.server.v1_8_R3.Entity;
|
import net.minecraft.server.v1_8_R3.Entity;
|
||||||
|
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
||||||
import net.minecraft.server.v1_8_R3.EntityTypes;
|
import net.minecraft.server.v1_8_R3.EntityTypes;
|
||||||
import net.minecraft.server.v1_8_R3.NBTTagCompound;
|
import net.minecraft.server.v1_8_R3.NBTTagCompound;
|
||||||
import net.minecraft.server.v1_8_R3.NBTTagInt;
|
import net.minecraft.server.v1_8_R3.NibbleArray;
|
||||||
import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk;
|
import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk;
|
||||||
import net.minecraft.server.v1_8_R3.PlayerConnection;
|
import net.minecraft.server.v1_8_R3.PlayerConnection;
|
||||||
import net.minecraft.server.v1_8_R3.TileEntity;
|
import net.minecraft.server.v1_8_R3.TileEntity;
|
||||||
@ -96,41 +99,44 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
public CharFaweChunk getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||||
CharFaweChunk<Chunk> fs = (CharFaweChunk<Chunk>) fc;
|
Map<BlockPosition, TileEntity> tiles = (Map<BlockPosition, TileEntity>) tilesGeneric;
|
||||||
CraftChunk chunk = (CraftChunk) fs.getChunk();
|
Collection<Entity>[] entities = (Collection<Entity>[]) entitiesGeneric;
|
||||||
net.minecraft.server.v1_8_R3.Chunk nmsChunk = chunk.getHandle();
|
CharFaweChunk previous = (CharFaweChunk) getChunk(fs.getX(), fs.getZ());
|
||||||
net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld();
|
|
||||||
try {
|
|
||||||
final boolean flag = getWorld().getEnvironment() == World.Environment.NORMAL;
|
|
||||||
// Sections
|
|
||||||
ChunkSection[] sections = nmsChunk.getSections();
|
|
||||||
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
|
||||||
Collection<net.minecraft.server.v1_8_R3.Entity>[] entities = nmsChunk.getEntitySlices();
|
|
||||||
|
|
||||||
// Run change task if applicable
|
|
||||||
if (changeTask != null) {
|
|
||||||
CharFaweChunk previous = (CharFaweChunk) getChunk(fc.getX(), fc.getZ());
|
|
||||||
char[][] idPrevious = new char[16][];
|
char[][] idPrevious = new char[16][];
|
||||||
for (int layer = 0; layer < sections.length; layer++) {
|
for (int layer = 0; layer < sections.length; layer++) {
|
||||||
if (fs.getCount(layer) != 0) {
|
if (fs.getCount(layer) != 0 || all) {
|
||||||
ChunkSection section = sections[layer];
|
ChunkSection section = sections[layer];
|
||||||
if (section != null) {
|
if (section != null) {
|
||||||
idPrevious[layer] = section.getIdArray().clone();
|
idPrevious[layer] = section.getIdArray().clone();
|
||||||
|
short solid = 0;
|
||||||
|
for (int combined : idPrevious[layer]) {
|
||||||
|
if (combined > 1) {
|
||||||
|
solid++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previous.count[layer] = solid;
|
||||||
|
previous.air[layer] = (short) (4096 - solid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
previous.ids = idPrevious;
|
previous.ids = idPrevious;
|
||||||
|
if (tiles != null) {
|
||||||
for (Map.Entry<BlockPosition, TileEntity> entry : tiles.entrySet()) {
|
for (Map.Entry<BlockPosition, TileEntity> entry : tiles.entrySet()) {
|
||||||
TileEntity tile = entry.getValue();
|
TileEntity tile = entry.getValue();
|
||||||
NBTTagCompound tag = new NBTTagCompound();
|
NBTTagCompound tag = new NBTTagCompound();
|
||||||
tile.b(tag); // ReadTileIntoTag
|
tile.b(tag); // readTileEntityIntoTag
|
||||||
BlockPosition pos = entry.getKey();
|
BlockPosition pos = entry.getKey();
|
||||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
|
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
|
||||||
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
|
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (entities != null) {
|
||||||
for (Collection<Entity> entityList : entities) {
|
for (Collection<Entity> entityList : entities) {
|
||||||
for (Entity ent : entityList) {
|
for (Entity ent : entityList) {
|
||||||
|
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && !createdEntities.contains(ent.getUniqueID()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
int x = ((int) Math.round(ent.locX) & 15);
|
int x = ((int) Math.round(ent.locX) & 15);
|
||||||
int z = ((int) Math.round(ent.locZ) & 15);
|
int z = ((int) Math.round(ent.locZ) & 15);
|
||||||
int y = (int) Math.round(ent.locY);
|
int y = (int) Math.round(ent.locY);
|
||||||
@ -144,7 +150,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
|||||||
String id = EntityTypes.b(ent);
|
String id = EntityTypes.b(ent);
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
NBTTagCompound tag = new NBTTagCompound();
|
NBTTagCompound tag = new NBTTagCompound();
|
||||||
ent.e(tag);
|
ent.e(tag); // readEntityIntoTag
|
||||||
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
|
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
|
||||||
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
|
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
|
||||||
map.put("Id", new StringTag(id));
|
map.put("Id", new StringTag(id));
|
||||||
@ -153,9 +159,87 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changeTask.run(previous);
|
}
|
||||||
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
||||||
|
CharFaweChunk<Chunk> fs = (CharFaweChunk<Chunk>) fc;
|
||||||
|
CraftChunk chunk = (CraftChunk) fs.getChunk();
|
||||||
|
net.minecraft.server.v1_8_R3.Chunk nmsChunk = chunk.getHandle();
|
||||||
|
net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld();
|
||||||
|
try {
|
||||||
|
final boolean flag = getWorld().getEnvironment() == World.Environment.NORMAL;
|
||||||
|
// Sections
|
||||||
|
ChunkSection[] sections = nmsChunk.getSections();
|
||||||
|
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
||||||
|
Collection<net.minecraft.server.v1_8_R3.Entity>[] entities = nmsChunk.getEntitySlices();
|
||||||
|
|
||||||
|
// Remove entities
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
int count = fs.getCount(i);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
entities[i].clear();
|
||||||
|
} else {
|
||||||
|
char[] array = fs.getIdArray(i);
|
||||||
|
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||||
|
for (Entity entity : ents) {
|
||||||
|
if (entity instanceof EntityPlayer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int x = ((int) Math.round(entity.locX) & 15);
|
||||||
|
int z = ((int) Math.round(entity.locZ) & 15);
|
||||||
|
int y = (int) Math.round(entity.locY);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int j = FaweCache.CACHE_J[y][x][z];
|
||||||
|
if (array[j] != 0) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set entities
|
||||||
|
Set<UUID> createdEntities = new HashSet<>();
|
||||||
|
Set<CompoundTag> entitiesToSpawn = fs.getEntities();
|
||||||
|
for (CompoundTag nativeTag : entitiesToSpawn) {
|
||||||
|
Map<String, Tag> entityTagMap = nativeTag.getValue();
|
||||||
|
StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||||
|
ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||||
|
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||||
|
if (idTag == null || posTag == null || rotTag == null) {
|
||||||
|
Fawe.debug("Unknown entity tag: " + nativeTag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double x = posTag.getDouble(0);
|
||||||
|
double y = posTag.getDouble(1);
|
||||||
|
double z = posTag.getDouble(2);
|
||||||
|
float yaw = rotTag.getFloat(0);
|
||||||
|
float pitch = rotTag.getFloat(1);
|
||||||
|
String id = idTag.getValue();
|
||||||
|
Entity entity = EntityTypes.createEntityByName(id, nmsWorld);
|
||||||
|
if (entity != null) {
|
||||||
|
if (nativeTag != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(adapter, nativeTag);
|
||||||
|
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
||||||
|
tag.remove(name);
|
||||||
|
}
|
||||||
|
entity.f(tag);
|
||||||
|
}
|
||||||
|
entity.setLocation(x, y, z, yaw, pitch);
|
||||||
|
nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
||||||
|
createdEntities.add(entity.getUniqueID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Run change task if applicable
|
||||||
|
if (changeTask != null) {
|
||||||
|
CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false);
|
||||||
|
changeTask.run(previous);
|
||||||
|
}
|
||||||
// Trim tiles
|
// Trim tiles
|
||||||
Set<Map.Entry<BlockPosition, TileEntity>> entryset = tiles.entrySet();
|
Set<Map.Entry<BlockPosition, TileEntity>> entryset = tiles.entrySet();
|
||||||
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = entryset.iterator();
|
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = entryset.iterator();
|
||||||
@ -175,31 +259,17 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
|||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove entities
|
HashSet<UUID> entsToRemove = fs.getEntityRemoves();
|
||||||
for (int i = 0; i < 16; i++) {
|
if (entsToRemove.size() > 0) {
|
||||||
int count = fs.getCount(i);
|
for (int i = 0; i < entities.length; i++) {
|
||||||
if (count == 0) {
|
|
||||||
continue;
|
|
||||||
} else if (count >= 4096) {
|
|
||||||
entities[i].clear();
|
|
||||||
} else {
|
|
||||||
char[] array = fs.getIdArray(i);
|
|
||||||
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||||
for (Entity entity : ents) {
|
for (Entity entity : ents) {
|
||||||
int x = ((int) Math.round(entity.locX) & 15);
|
if (entsToRemove.contains(entity.getUniqueID())) {
|
||||||
int z = ((int) Math.round(entity.locZ) & 15);
|
|
||||||
int y = (int) Math.round(entity.locY);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int j = FaweCache.CACHE_J[y][x][z];
|
|
||||||
if (array[j] != 0) {
|
|
||||||
nmsWorld.removeEntity(entity);
|
nmsWorld.removeEntity(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set blocks
|
// Set blocks
|
||||||
for (int j = 0; j < sections.length; j++) {
|
for (int j = 0; j < sections.length; j++) {
|
||||||
if (fs.getCount(j) == 0) {
|
if (fs.getCount(j) == 0) {
|
||||||
@ -256,53 +326,19 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
|||||||
}
|
}
|
||||||
// Set tiles
|
// Set tiles
|
||||||
Map<BytePair, CompoundTag> tilesToSpawn = fs.getTiles();
|
Map<BytePair, CompoundTag> tilesToSpawn = fs.getTiles();
|
||||||
BlockPosition.MutableBlockPosition mutablePos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
|
||||||
int bx = fs.getX() << 4;
|
int bx = fs.getX() << 4;
|
||||||
int bz = fs.getZ() << 4;
|
int bz = fs.getZ() << 4;
|
||||||
|
|
||||||
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||||
CompoundTag nativeTag = entry.getValue();
|
CompoundTag nativeTag = entry.getValue();
|
||||||
BytePair pair = entry.getKey();
|
BytePair pair = entry.getKey();
|
||||||
mutablePos.c(MathMan.unpair16x(pair.pair[0]) + bx, pair.pair[1] & 0xFF, MathMan.unpair16y(pair.pair[0]) + bz); // Set pos
|
BlockPosition pos = new BlockPosition(MathMan.unpair16x(pair.pair[0]) + bx, pair.pair[1] & 0xFF, MathMan.unpair16y(pair.pair[0]) + bz); // Set pos
|
||||||
TileEntity tileEntity = nmsWorld.getTileEntity(mutablePos);
|
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||||
if (tileEntity != null) {
|
if (tileEntity != null) {
|
||||||
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(adapter, nativeTag);
|
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(adapter, nativeTag);
|
||||||
tag.set("x", new NBTTagInt(mutablePos.getX()));
|
|
||||||
tag.set("y", new NBTTagInt(mutablePos.getY()));
|
|
||||||
tag.set("z", new NBTTagInt(mutablePos.getZ()));
|
|
||||||
tileEntity.a(tag); // ReadTagIntoTile
|
tileEntity.a(tag); // ReadTagIntoTile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set entities
|
|
||||||
Set<CompoundTag> entitiesToSpawn = fs.getEntities();
|
|
||||||
for (CompoundTag nativeTag : entitiesToSpawn) {
|
|
||||||
Map<String, Tag> entityTagMap = nativeTag.getValue();
|
|
||||||
StringTag idTag = (StringTag) entityTagMap.get("Id");
|
|
||||||
ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
|
||||||
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
|
||||||
if (idTag == null || posTag == null || rotTag == null) {
|
|
||||||
Fawe.debug("Unknown entity tag: " + nativeTag);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
double x = posTag.getDouble(0);
|
|
||||||
double y = posTag.getDouble(1);
|
|
||||||
double z = posTag.getDouble(2);
|
|
||||||
float yaw = rotTag.getFloat(0);
|
|
||||||
float pitch = rotTag.getFloat(1);
|
|
||||||
String id = idTag.getValue();
|
|
||||||
Entity entity = EntityTypes.createEntityByName(id, nmsWorld);
|
|
||||||
if (entity != null) {
|
|
||||||
if (nativeTag != null) {
|
|
||||||
NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(adapter, nativeTag);
|
|
||||||
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
|
||||||
tag.remove(name);
|
|
||||||
}
|
|
||||||
entity.f(tag);
|
|
||||||
}
|
|
||||||
entity.setLocation(x, y, z, yaw, pitch);
|
|
||||||
nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -339,8 +375,8 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
|||||||
FaweLocation loc = fp.getLocation();
|
FaweLocation loc = fp.getLocation();
|
||||||
int px = loc.x >> 4;
|
int px = loc.x >> 4;
|
||||||
int pz = loc.z >> 4;
|
int pz = loc.z >> 4;
|
||||||
int dx = Math.abs(cx - (loc.x >> 4));
|
int dx = Math.abs(cx - (px));
|
||||||
int dz = Math.abs(cz - (loc.z >> 4));
|
int dz = Math.abs(cz - (pz));
|
||||||
if ((dx > view) || (dz > view)) {
|
if ((dx > view) || (dz > view)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -350,7 +386,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean fixLighting(FaweChunk chunk, boolean fixAll) {
|
public boolean fixLighting(FaweChunk chunk, RelightMode mode) {
|
||||||
try {
|
try {
|
||||||
CharFaweChunk<Chunk> fc = (CharFaweChunk<Chunk>) chunk;
|
CharFaweChunk<Chunk> fc = (CharFaweChunk<Chunk>) chunk;
|
||||||
CraftChunk craftChunk = (CraftChunk) fc.getChunk();
|
CraftChunk craftChunk = (CraftChunk) fc.getChunk();
|
||||||
@ -358,11 +394,22 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
|||||||
if (!craftChunk.isLoaded()) {
|
if (!craftChunk.isLoaded()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
ChunkSection[] sections = nmsChunk.getSections();
|
||||||
|
if (mode != RelightMode.MINIMAL) {
|
||||||
|
for (int i = 0; i < sections.length; i++) {
|
||||||
|
ChunkSection section = sections[i];
|
||||||
|
if (section != null) {
|
||||||
|
if (mode == RelightMode.ALL) {
|
||||||
|
section.a(new NibbleArray());
|
||||||
|
}
|
||||||
|
section.b(new NibbleArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
nmsChunk.initLighting();
|
nmsChunk.initLighting();
|
||||||
if (fc.getTotalRelight() == 0 && !fixAll) {
|
if (fc.getTotalRelight() == 0 && mode == RelightMode.MINIMAL) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ChunkSection[] sections = nmsChunk.getSections();
|
|
||||||
net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld();
|
net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld();
|
||||||
|
|
||||||
int X = fc.getX() << 4;
|
int X = fc.getX() << 4;
|
||||||
@ -374,7 +421,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
|||||||
if (section == null) {
|
if (section == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((fc.getRelight(j) == 0 && !fixAll) || fc.getCount(j) == 0 || (fc.getCount(j) >= 4096 && fc.getAir(j) == 0)) {
|
if ((fc.getRelight(j) == 0 && mode == RelightMode.MINIMAL) || (fc.getCount(j) == 0 && mode != RelightMode.ALL) || (fc.getCount(j) >= 4096 && fc.getAir(j) == 0)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
char[] array = section.getIdArray();
|
char[] array = section.getIdArray();
|
||||||
@ -387,7 +434,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]
|
|||||||
short id = (short) (i >> 4);
|
short id = (short) (i >> 4);
|
||||||
switch (id) { // Lighting
|
switch (id) { // Lighting
|
||||||
default:
|
default:
|
||||||
if (!fixAll) {
|
if (mode == RelightMode.MINIMAL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((k & 1) == l) {
|
if ((k & 1) == l) {
|
||||||
|
@ -21,9 +21,9 @@ commands:
|
|||||||
fawe:
|
fawe:
|
||||||
description: (FAWE) Reload the plugin
|
description: (FAWE) Reload the plugin
|
||||||
aliases: [/fawe,/fawereload]
|
aliases: [/fawe,/fawereload]
|
||||||
wrg:
|
select:
|
||||||
description: (FAWE) Select your current WorldEdit Region.
|
description: (FAWE) Select your current WorldEdit Region.
|
||||||
aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region]
|
aliases: [/select,wer,/wer,worldeditregion,/worldeditregion,/region]
|
||||||
frb:
|
frb:
|
||||||
description: (FAWE) Rollback an edit
|
description: (FAWE) Rollback an edit
|
||||||
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile project(':bukkit0')
|
compile project(':bukkit0')
|
||||||
compile 'org.bukkit.craftbukkit:CraftBukkit:1.9.2'
|
compile 'org.bukkit.craftbukkit.v1_9R2:craftbukkitv1_9R2:1.9.4'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.github.johnrengelman.shadow'
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
|
@ -5,12 +5,12 @@ import com.boydti.fawe.example.CharFaweChunk;
|
|||||||
import com.boydti.fawe.util.FaweQueue;
|
import com.boydti.fawe.util.FaweQueue;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import net.minecraft.server.v1_9_R1.Block;
|
import net.minecraft.server.v1_9_R2.Block;
|
||||||
import net.minecraft.server.v1_9_R1.DataBits;
|
import net.minecraft.server.v1_9_R2.DataBits;
|
||||||
import net.minecraft.server.v1_9_R1.DataPalette;
|
import net.minecraft.server.v1_9_R2.DataPalette;
|
||||||
import net.minecraft.server.v1_9_R1.DataPaletteBlock;
|
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
|
||||||
import net.minecraft.server.v1_9_R1.DataPaletteGlobal;
|
import net.minecraft.server.v1_9_R2.DataPaletteGlobal;
|
||||||
import net.minecraft.server.v1_9_R1.IBlockData;
|
import net.minecraft.server.v1_9_R2.IBlockData;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
|
|
||||||
public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
|
public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
|
||||||
@ -101,7 +101,7 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
|
|||||||
if (sectionPalettes != null) {
|
if (sectionPalettes != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char[][] arrays = getIdArrays();
|
char[][] arrays = getCombinedIdArrays();
|
||||||
IBlockData lastBlock = null;
|
IBlockData lastBlock = null;
|
||||||
char lastChar = Character.MAX_VALUE;
|
char lastChar = Character.MAX_VALUE;
|
||||||
for (int layer = 0; layer < 16; layer++) {
|
for (int layer = 0; layer < 16; layer++) {
|
||||||
|
@ -2,7 +2,6 @@ package com.boydti.fawe.bukkit.v1_9;
|
|||||||
|
|
||||||
import com.boydti.fawe.bukkit.ABukkitMain;
|
import com.boydti.fawe.bukkit.ABukkitMain;
|
||||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||||
import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9_R1;
|
|
||||||
import com.boydti.fawe.object.EditSessionWrapper;
|
import com.boydti.fawe.object.EditSessionWrapper;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
|
|
||||||
|
@ -4,44 +4,50 @@ import com.boydti.fawe.Fawe;
|
|||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||||
import com.boydti.fawe.example.CharFaweChunk;
|
import com.boydti.fawe.example.CharFaweChunk;
|
||||||
|
import com.boydti.fawe.object.BytePair;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
|
||||||
import com.boydti.fawe.object.IntegerPair;
|
|
||||||
import com.boydti.fawe.object.PseudoRandom;
|
import com.boydti.fawe.object.PseudoRandom;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
import com.boydti.fawe.util.MemUtil;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.ListTag;
|
||||||
|
import com.sk89q.jnbt.LongTag;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
import com.sk89q.worldedit.internal.Constants;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.util.ArrayList;
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import net.minecraft.server.v1_9_R1.Block;
|
import java.util.Set;
|
||||||
import net.minecraft.server.v1_9_R1.BlockPosition;
|
import java.util.UUID;
|
||||||
import net.minecraft.server.v1_9_R1.Blocks;
|
import net.minecraft.server.v1_9_R2.Block;
|
||||||
import net.minecraft.server.v1_9_R1.ChunkSection;
|
import net.minecraft.server.v1_9_R2.BlockPosition;
|
||||||
import net.minecraft.server.v1_9_R1.DataBits;
|
import net.minecraft.server.v1_9_R2.Blocks;
|
||||||
import net.minecraft.server.v1_9_R1.DataPalette;
|
import net.minecraft.server.v1_9_R2.ChunkSection;
|
||||||
import net.minecraft.server.v1_9_R1.DataPaletteBlock;
|
import net.minecraft.server.v1_9_R2.DataBits;
|
||||||
import net.minecraft.server.v1_9_R1.IBlockData;
|
import net.minecraft.server.v1_9_R2.DataPalette;
|
||||||
import net.minecraft.server.v1_9_R1.TileEntity;
|
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
|
||||||
import org.bukkit.Bukkit;
|
import net.minecraft.server.v1_9_R2.Entity;
|
||||||
|
import net.minecraft.server.v1_9_R2.EntityPlayer;
|
||||||
|
import net.minecraft.server.v1_9_R2.EntityTypes;
|
||||||
|
import net.minecraft.server.v1_9_R2.IBlockData;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagCompound;
|
||||||
|
import net.minecraft.server.v1_9_R2.NibbleArray;
|
||||||
|
import net.minecraft.server.v1_9_R2.TileEntity;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.World.Environment;
|
import org.bukkit.World.Environment;
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.craftbukkit.v1_9_R1.CraftChunk;
|
import org.bukkit.craftbukkit.v1_9_R2.CraftChunk;
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.generator.BlockPopulator;
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
|
||||||
|
|
||||||
public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], DataPaletteBlock> {
|
public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], DataPaletteBlock> {
|
||||||
|
|
||||||
@ -53,9 +59,16 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
|
|||||||
Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
|
Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
|
||||||
fieldAir.setAccessible(true);
|
fieldAir.setAccessible(true);
|
||||||
air = (IBlockData) fieldAir.get(null);
|
air = (IBlockData) fieldAir.get(null);
|
||||||
|
if (adapter == null) {
|
||||||
|
setupAdapter(new FaweAdapter_1_9());
|
||||||
|
Fawe.debug("=========================================");
|
||||||
|
Fawe.debug("Using adapter: " + adapter);
|
||||||
|
Fawe.debug("=========================================");
|
||||||
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
Player player = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -88,37 +101,47 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean fixLighting(final FaweChunk pc, final boolean fixAll) {
|
public boolean fixLighting(final FaweChunk pc, RelightMode mode) {
|
||||||
try {
|
try {
|
||||||
final CharFaweChunk bc = (CharFaweChunk) pc;
|
CharFaweChunk bc = (CharFaweChunk) pc;
|
||||||
final Chunk chunk = (Chunk) bc.getChunk();
|
Chunk chunk = (Chunk) bc.getChunk();
|
||||||
if (!chunk.isLoaded()) {
|
if (!chunk.isLoaded()) {
|
||||||
if (Fawe.get().getMainThread() != Thread.currentThread()) {
|
if (Fawe.get().getMainThread() != Thread.currentThread()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
chunk.load(false);
|
chunk.load(false);
|
||||||
}
|
}
|
||||||
// Initialize lighting
|
net.minecraft.server.v1_9_R2.Chunk c = ((CraftChunk) chunk).getHandle();
|
||||||
net.minecraft.server.v1_9_R1.Chunk c = ((CraftChunk) chunk).getHandle();
|
ChunkSection[] sections = c.getSections();
|
||||||
|
if (mode != RelightMode.MINIMAL) {
|
||||||
|
for (int i = 0; i < sections.length; i++) {
|
||||||
|
ChunkSection section = sections[i];
|
||||||
|
if (section != null) {
|
||||||
|
if (mode == RelightMode.ALL) {
|
||||||
|
section.a(new NibbleArray());
|
||||||
|
}
|
||||||
|
section.b(new NibbleArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
c.initLighting();
|
c.initLighting();
|
||||||
|
if (((bc.getTotalRelight() == 0) && mode == RelightMode.MINIMAL)) {
|
||||||
if (((bc.getTotalRelight() == 0) && !fixAll)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (mode == RelightMode.ALL) {
|
||||||
ChunkSection[] sections = c.getSections();
|
bc = getPrevious(bc, c.getSections(), null, null, null, true);
|
||||||
net.minecraft.server.v1_9_R1.World w = c.world;
|
}
|
||||||
|
int total = bc.getTotalCount();
|
||||||
|
net.minecraft.server.v1_9_R2.World w = c.world;
|
||||||
final int X = chunk.getX() << 4;
|
final int X = chunk.getX() << 4;
|
||||||
final int Z = chunk.getZ() << 4;
|
final int Z = chunk.getZ() << 4;
|
||||||
|
|
||||||
BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
||||||
for (int j = 0; j < sections.length; j++) {
|
for (int j = 0; j < sections.length; j++) {
|
||||||
final Object section = sections[j];
|
final Object section = sections[j];
|
||||||
if (section == null) {
|
if (section == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (((bc.getRelight(j) == 0) && !fixAll) || (bc.getCount(j) == 0) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0))) {
|
if (((bc.getRelight(j) == 0) && mode == RelightMode.MINIMAL) || (bc.getCount(j) == 0 && mode != RelightMode.ALL) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final char[] array = bc.getIdArray(j);
|
final char[] array = bc.getIdArray(j);
|
||||||
@ -136,7 +159,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
|
|||||||
case 0:
|
case 0:
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
if (!fixAll) {
|
if (mode == RelightMode.MINIMAL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((k & 1) == l) {
|
if ((k & 1) == l) {
|
||||||
@ -161,7 +184,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
|
|||||||
final int x = FaweCache.CACHE_X[j][k];
|
final int x = FaweCache.CACHE_X[j][k];
|
||||||
final int y = FaweCache.CACHE_Y[j][k];
|
final int y = FaweCache.CACHE_Y[j][k];
|
||||||
final int z = FaweCache.CACHE_Z[j][k];
|
final int z = FaweCache.CACHE_Z[j][k];
|
||||||
if (this.isSurrounded(bc.getIdArrays(), x, y, z)) {
|
if (this.isSurrounded(bc.getCombinedIdArrays(), x, y, z)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
pos.c(X + x, y, Z + z);
|
pos.c(X + x, y, Z + z);
|
||||||
@ -249,62 +272,199 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setComponents(final FaweChunk pc, RunnableVal<FaweChunk> changeTask) {
|
public CharFaweChunk getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||||
// TODO change task
|
Map<BlockPosition, TileEntity> tiles = (Map<BlockPosition, TileEntity>) tilesGeneric;
|
||||||
{
|
Collection<Entity>[] entities = (Collection<Entity>[]) entitiesGeneric;
|
||||||
// blah, stuff
|
CharFaweChunk previous = (CharFaweChunk) getChunk(fs.getX(), fs.getZ());
|
||||||
|
// Copy blocks
|
||||||
|
char[][] idPrevious = new char[16][];
|
||||||
|
for (int layer = 0; layer < sections.length; layer++) {
|
||||||
|
if (fs.getCount(layer) != 0 || all) {
|
||||||
|
ChunkSection section = sections[layer];
|
||||||
|
if (section != null) {
|
||||||
|
short solid = 0;
|
||||||
|
char[] previousLayer = idPrevious[layer] = new char[4096];
|
||||||
|
DataPaletteBlock blocks = section.getBlocks();
|
||||||
|
for (int j = 0; j < 4096; j++) {
|
||||||
|
int x = FaweCache.CACHE_X[0][j];
|
||||||
|
int y = FaweCache.CACHE_Y[0][j];
|
||||||
|
int z = FaweCache.CACHE_Z[0][j];
|
||||||
|
IBlockData ibd = blocks.a(x, y, z);
|
||||||
|
Block block = ibd.getBlock();
|
||||||
|
int combined = Block.getId(block);
|
||||||
|
if (FaweCache.hasData(combined)) {
|
||||||
|
combined = (combined << 4) + block.toLegacyData(ibd);
|
||||||
|
} else {
|
||||||
|
combined = combined << 4;
|
||||||
|
}
|
||||||
|
if (combined > 1) {
|
||||||
|
solid++;
|
||||||
|
}
|
||||||
|
previousLayer[j] = (char) combined;
|
||||||
|
}
|
||||||
|
previous.count[layer] = solid;
|
||||||
|
previous.air[layer] = (short) (4096 - solid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previous.ids = idPrevious;
|
||||||
|
// Copy tiles
|
||||||
|
if (tiles != null) {
|
||||||
|
for (Map.Entry<BlockPosition, TileEntity> entry : tiles.entrySet()) {
|
||||||
|
TileEntity tile = entry.getValue();
|
||||||
|
NBTTagCompound tag = new NBTTagCompound();
|
||||||
|
tile.save(tag); // readTagIntoEntity
|
||||||
|
BlockPosition pos = entry.getKey();
|
||||||
|
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
|
||||||
|
previous.setTile(pos.getX(), pos.getY(), pos.getZ(), nativeTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Copy entities
|
||||||
|
if (entities != null) {
|
||||||
|
for (Collection<Entity> entityList : entities) {
|
||||||
|
for (Entity ent : entityList) {
|
||||||
|
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && !createdEntities.contains(ent.getUniqueID()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int x = ((int) Math.round(ent.locX) & 15);
|
||||||
|
int z = ((int) Math.round(ent.locZ) & 15);
|
||||||
|
int y = (int) Math.round(ent.locY);
|
||||||
|
int i = FaweCache.CACHE_I[y][x][z];
|
||||||
|
char[] array = fs.getIdArray(i);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int j = FaweCache.CACHE_J[y][x][z];
|
||||||
|
if (array[j] != 0) {
|
||||||
|
String id = EntityTypes.b(ent);
|
||||||
|
if (id != null) {
|
||||||
|
NBTTagCompound tag = new NBTTagCompound();
|
||||||
|
ent.e(tag); // readEntityIntoTag
|
||||||
|
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
|
||||||
|
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
|
||||||
|
map.put("Id", new StringTag(id));
|
||||||
|
previous.setEntity(nativeTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc;
|
@Override
|
||||||
|
public boolean setComponents(final FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
||||||
|
final BukkitChunk_1_9 fs = (BukkitChunk_1_9) fc;
|
||||||
final Chunk chunk = (Chunk) fs.getChunk();
|
final Chunk chunk = (Chunk) fs.getChunk();
|
||||||
final World world = chunk.getWorld();
|
final World world = chunk.getWorld();
|
||||||
chunk.load(true);
|
chunk.load(true);
|
||||||
try {
|
try {
|
||||||
final boolean flag = world.getEnvironment() == Environment.NORMAL;
|
final boolean flag = world.getEnvironment() == Environment.NORMAL;
|
||||||
|
net.minecraft.server.v1_9_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
||||||
// Sections
|
net.minecraft.server.v1_9_R2.World nmsWorld = nmsChunk.world;
|
||||||
net.minecraft.server.v1_9_R1.Chunk c = ((CraftChunk) chunk).getHandle();
|
ChunkSection[] sections = nmsChunk.getSections();
|
||||||
net.minecraft.server.v1_9_R1.World w = c.world;
|
Class<? extends net.minecraft.server.v1_9_R2.Chunk> clazzChunk = nmsChunk.getClass();
|
||||||
ChunkSection[] sections = c.getSections();
|
|
||||||
|
|
||||||
Class<? extends net.minecraft.server.v1_9_R1.Chunk> clazzChunk = c.getClass();
|
|
||||||
final Field ef = clazzChunk.getDeclaredField("entitySlices");
|
final Field ef = clazzChunk.getDeclaredField("entitySlices");
|
||||||
final Collection<?>[] entities = (Collection<?>[]) ef.get(c);
|
final Collection<Entity>[] entities = (Collection<Entity>[]) ef.get(nmsChunk);
|
||||||
|
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
||||||
// Trim tiles
|
// Remove entities
|
||||||
boolean removed = false;
|
for (int i = 0; i < entities.length; i++) {
|
||||||
Map<BlockPosition, TileEntity> tiles = c.getTileEntities();
|
int count = fs.getCount(i);
|
||||||
if (fs.getTotalCount() >= 65536) {
|
if (count == 0) {
|
||||||
tiles.clear();
|
continue;
|
||||||
removed = true;
|
} else if (count >= 4096) {
|
||||||
|
entities[i].clear();
|
||||||
} else {
|
} else {
|
||||||
Iterator<Entry<BlockPosition, TileEntity>> iter = tiles.entrySet().iterator();
|
char[] array = fs.getIdArray(i);
|
||||||
while (iter.hasNext()) {
|
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||||
Entry<BlockPosition, TileEntity> tile = iter.next();
|
for (Entity entity : ents) {
|
||||||
|
if (entity instanceof EntityPlayer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int x = ((int) Math.round(entity.locX) & 15);
|
||||||
|
int z = ((int) Math.round(entity.locZ) & 15);
|
||||||
|
int y = (int) Math.round(entity.locY);
|
||||||
|
if (array == null || y < 0 || y > 255) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int j = FaweCache.CACHE_J[y][x][z];
|
||||||
|
if (array[j] != 0) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HashSet<UUID> entsToRemove = fs.getEntityRemoves();
|
||||||
|
if (entsToRemove.size() > 0) {
|
||||||
|
for (int i = 0; i < entities.length; i++) {
|
||||||
|
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||||
|
for (Entity entity : ents) {
|
||||||
|
if (entsToRemove.contains(entity.getUniqueID())) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set entities
|
||||||
|
Set<UUID> createdEntities = new HashSet<>();
|
||||||
|
Set<CompoundTag> entitiesToSpawn = fs.getEntities();
|
||||||
|
for (CompoundTag nativeTag : entitiesToSpawn) {
|
||||||
|
Map<String, Tag> entityTagMap = ReflectionUtils.getMap(nativeTag.getValue());
|
||||||
|
StringTag idTag = (StringTag) entityTagMap.get("Id");
|
||||||
|
ListTag posTag = (ListTag) entityTagMap.get("Pos");
|
||||||
|
ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
|
||||||
|
if (idTag == null || posTag == null || rotTag == null) {
|
||||||
|
Fawe.debug("Unknown entity tag: " + nativeTag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double x = posTag.getDouble(0);
|
||||||
|
double y = posTag.getDouble(1);
|
||||||
|
double z = posTag.getDouble(2);
|
||||||
|
float yaw = rotTag.getFloat(0);
|
||||||
|
float pitch = rotTag.getFloat(1);
|
||||||
|
String id = idTag.getValue();
|
||||||
|
Entity entity = EntityTypes.createEntityByName(id, nmsWorld);
|
||||||
|
if (entity != null) {
|
||||||
|
UUID uuid = entity.getUniqueID();
|
||||||
|
entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits()));
|
||||||
|
entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits()));
|
||||||
|
if (nativeTag != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(adapter, nativeTag);
|
||||||
|
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
||||||
|
tag.remove(name);
|
||||||
|
}
|
||||||
|
entity.f(tag);
|
||||||
|
}
|
||||||
|
entity.setLocation(x, y, z, yaw, pitch);
|
||||||
|
nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
||||||
|
createdEntities.add(entity.getUniqueID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Change task?
|
||||||
|
if (changeTask != null) {
|
||||||
|
CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false);
|
||||||
|
changeTask.run(previous);
|
||||||
|
}
|
||||||
|
// Trim tiles
|
||||||
|
Set<Entry<BlockPosition, TileEntity>> entryset = tiles.entrySet();
|
||||||
|
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = entryset.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<BlockPosition, TileEntity> tile = iterator.next();
|
||||||
BlockPosition pos = tile.getKey();
|
BlockPosition pos = tile.getKey();
|
||||||
final int lx = pos.getX() & 15;
|
int lx = pos.getX() & 15;
|
||||||
final int ly = pos.getY();
|
int ly = pos.getY();
|
||||||
final int lz = pos.getZ() & 15;
|
int lz = pos.getZ() & 15;
|
||||||
final int j = FaweCache.CACHE_I[ly][lx][lz];
|
int j = FaweCache.CACHE_I[ly][lx][lz];
|
||||||
final int k = FaweCache.CACHE_J[ly][lx][lz];
|
char[] array = fs.getIdArray(j);
|
||||||
final char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
if (array == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
int k = FaweCache.CACHE_J[ly][lx][lz];
|
||||||
if (array[k] != 0) {
|
if (array[k] != 0) {
|
||||||
removed = true;
|
iterator.remove();
|
||||||
iter.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// Set blocks
|
||||||
|
|
||||||
// Trim entities
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) {
|
|
||||||
entities[i].clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Efficiently merge sections
|
|
||||||
for (int j = 0; j < sections.length; j++) {
|
for (int j = 0; j < sections.length; j++) {
|
||||||
int count = fs.getCount(j);
|
int count = fs.getCount(j);
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
@ -367,7 +527,38 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
|
|||||||
}
|
}
|
||||||
setCount(0, nonEmptyBlockCount, section);
|
setCount(0, nonEmptyBlockCount, section);
|
||||||
}
|
}
|
||||||
// Clear
|
// Set biomes
|
||||||
|
int[][] biomes = fs.biomes;
|
||||||
|
if (biomes != null) {
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
int[] array = biomes[x];
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
int biome = array[z];
|
||||||
|
if (biome == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set tiles
|
||||||
|
Map<BytePair, CompoundTag> tilesToSpawn = fs.getTiles();
|
||||||
|
int bx = fs.getX() << 4;
|
||||||
|
int bz = fs.getZ() << 4;
|
||||||
|
|
||||||
|
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||||
|
CompoundTag nativeTag = entry.getValue();
|
||||||
|
BytePair pair = entry.getKey();
|
||||||
|
BlockPosition pos = new BlockPosition(MathMan.unpair16x(pair.pair[0]) + bx, pair.pair[1] & 0xFF, MathMan.unpair16y(pair.pair[0]) + bz); // Set pos
|
||||||
|
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||||
|
if (tileEntity != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(adapter, nativeTag);
|
||||||
|
tileEntity.a(tag); // ReadTagIntoTile
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -392,117 +583,9 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Deprecated
|
||||||
* This method is called when the server is < 1% available memory (i.e. likely to crash)<br>
|
|
||||||
* - You can disable this in the conifg<br>
|
|
||||||
* - Will try to free up some memory<br>
|
|
||||||
* - Clears the queue<br>
|
|
||||||
* - Clears worldedit history<br>
|
|
||||||
* - Clears entities<br>
|
|
||||||
* - Unloads chunks in vacant worlds<br>
|
|
||||||
* - Unloads non visible chunks<br>
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void saveMemory() {
|
|
||||||
super.saveMemory();
|
|
||||||
// Clear the queue
|
|
||||||
super.clear();
|
|
||||||
ArrayDeque<Chunk> toUnload = new ArrayDeque<>();
|
|
||||||
final int distance = Bukkit.getViewDistance() + 2;
|
|
||||||
HashMap<String, HashMap<IntegerPair, Integer>> players = new HashMap<>();
|
|
||||||
for (final Player player : Bukkit.getOnlinePlayers()) {
|
|
||||||
// Clear history
|
|
||||||
final FawePlayer<Object> fp = FawePlayer.wrap(player);
|
|
||||||
final LocalSession s = fp.getSession();
|
|
||||||
if (s != null) {
|
|
||||||
s.clearHistory();
|
|
||||||
s.setClipboard(null);
|
|
||||||
}
|
|
||||||
final Location loc = player.getLocation();
|
|
||||||
final World worldObj = loc.getWorld();
|
|
||||||
final String world = worldObj.getName();
|
|
||||||
HashMap<IntegerPair, Integer> map = players.get(world);
|
|
||||||
if (map == null) {
|
|
||||||
map = new HashMap<>();
|
|
||||||
players.put(world, map);
|
|
||||||
}
|
|
||||||
final IntegerPair origin = new IntegerPair(loc.getBlockX() >> 4, loc.getBlockZ() >> 4);
|
|
||||||
Integer val = map.get(origin);
|
|
||||||
int check;
|
|
||||||
if (val != null) {
|
|
||||||
if (val == distance) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
check = distance - val;
|
|
||||||
} else {
|
|
||||||
check = distance;
|
|
||||||
map.put(origin, distance);
|
|
||||||
}
|
|
||||||
for (int x = -distance; x <= distance; x++) {
|
|
||||||
if ((x >= check) || (-x >= check)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int z = -distance; z <= distance; z++) {
|
|
||||||
if ((z >= check) || (-z >= check)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final int weight = distance - Math.max(Math.abs(x), Math.abs(z));
|
|
||||||
final IntegerPair chunk = new IntegerPair(x + origin.x, z + origin.z);
|
|
||||||
val = map.get(chunk);
|
|
||||||
if ((val == null) || (val < weight)) {
|
|
||||||
map.put(chunk, weight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Fawe.get().getWorldEdit().clearSessions();
|
|
||||||
for (final World world : Bukkit.getWorlds()) {
|
|
||||||
final String name = world.getName();
|
|
||||||
final HashMap<IntegerPair, Integer> map = players.get(name);
|
|
||||||
if ((map == null) || (map.size() == 0)) {
|
|
||||||
final boolean save = world.isAutoSave();
|
|
||||||
world.setAutoSave(false);
|
|
||||||
for (final Chunk chunk : world.getLoadedChunks()) {
|
|
||||||
this.unloadChunk(name, chunk);
|
|
||||||
}
|
|
||||||
world.setAutoSave(save);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final Chunk[] chunks = world.getLoadedChunks();
|
|
||||||
for (final Chunk chunk : chunks) {
|
|
||||||
final int x = chunk.getX();
|
|
||||||
final int z = chunk.getZ();
|
|
||||||
if (!map.containsKey(new IntegerPair(x, z))) {
|
|
||||||
toUnload.add(chunk);
|
|
||||||
} else if (chunk.getEntities().length > 4096) {
|
|
||||||
for (final Entity ent : chunk.getEntities()) {
|
|
||||||
ent.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// GC again
|
|
||||||
System.gc();
|
|
||||||
System.gc();
|
|
||||||
// If still critical memory
|
|
||||||
int free = MemUtil.calculateMemory();
|
|
||||||
if (free <= 1) {
|
|
||||||
for (final Chunk chunk : toUnload) {
|
|
||||||
this.unloadChunk(chunk.getWorld().getName(), chunk);
|
|
||||||
}
|
|
||||||
} else if (free == Integer.MAX_VALUE) {
|
|
||||||
for (final Chunk chunk : toUnload) {
|
|
||||||
chunk.unload(true, false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
toUnload = null;
|
|
||||||
players = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean unloadChunk(final String world, final Chunk chunk) {
|
public boolean unloadChunk(final String world, final Chunk chunk) {
|
||||||
net.minecraft.server.v1_9_R1.Chunk c = ((CraftChunk) chunk).getHandle();
|
net.minecraft.server.v1_9_R2.Chunk c = ((CraftChunk) chunk).getHandle();
|
||||||
c.mustSave = false;
|
c.mustSave = false;
|
||||||
if (chunk.isLoaded()) {
|
if (chunk.isLoaded()) {
|
||||||
chunk.unload(false, false);
|
chunk.unload(false, false);
|
||||||
@ -510,133 +593,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkGenerator setGenerator(final World world, final ChunkGenerator newGen) {
|
|
||||||
try {
|
|
||||||
final ChunkGenerator gen = world.getGenerator();
|
|
||||||
final Class<? extends World> clazz = world.getClass();
|
|
||||||
final Field generator = clazz.getDeclaredField("generator");
|
|
||||||
generator.setAccessible(true);
|
|
||||||
generator.set(world, newGen);
|
|
||||||
|
|
||||||
final Field wf = clazz.getDeclaredField("world");
|
|
||||||
wf.setAccessible(true);
|
|
||||||
final Object w = wf.get(world);
|
|
||||||
final Class<?> clazz2 = w.getClass().getSuperclass();
|
|
||||||
final Field generator2 = clazz2.getDeclaredField("generator");
|
|
||||||
generator2.set(w, newGen);
|
|
||||||
|
|
||||||
return gen;
|
|
||||||
} catch (final Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<BlockPopulator> setPopulator(final World world, final List<BlockPopulator> newPop) {
|
|
||||||
try {
|
|
||||||
final List<BlockPopulator> pop = world.getPopulators();
|
|
||||||
final Field populators = world.getClass().getDeclaredField("populators");
|
|
||||||
populators.setAccessible(true);
|
|
||||||
populators.set(world, newPop);
|
|
||||||
return pop;
|
|
||||||
} catch (final Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEntitiesAndTiles(final Chunk chunk, final List<?>[] entities, final Map<?, ?> tiles) {
|
|
||||||
try {
|
|
||||||
final Class<? extends Chunk> clazz = chunk.getClass();
|
|
||||||
final Method handle = clazz.getMethod("getHandle");
|
|
||||||
final Object c = handle.invoke(chunk);
|
|
||||||
final Class<? extends Object> clazz2 = c.getClass();
|
|
||||||
|
|
||||||
if (tiles.size() > 0) {
|
|
||||||
final Field tef = clazz2.getDeclaredField("tileEntities");
|
|
||||||
final Map<?, ?> te = (Map<?, ?>) tef.get(c);
|
|
||||||
final Method put = te.getClass().getMethod("putAll", Map.class);
|
|
||||||
put.invoke(te, tiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Field esf = clazz2.getDeclaredField("entitySlices");
|
|
||||||
esf.setAccessible(true);
|
|
||||||
esf.set(c, entities);
|
|
||||||
} catch (final Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getProvider(final World world) {
|
|
||||||
try {
|
|
||||||
// Provider 1
|
|
||||||
final Class<? extends World> clazz = world.getClass();
|
|
||||||
final Field wf = clazz.getDeclaredField("world");
|
|
||||||
wf.setAccessible(true);
|
|
||||||
final Object w = wf.get(world);
|
|
||||||
final Field provider = w.getClass().getSuperclass().getDeclaredField("chunkProvider");
|
|
||||||
provider.setAccessible(true);
|
|
||||||
// ChunkProviderServer
|
|
||||||
final Class<? extends Object> clazz2 = w.getClass();
|
|
||||||
final Field wpsf = clazz2.getDeclaredField("chunkProviderServer");
|
|
||||||
// Store old provider server
|
|
||||||
final Object worldProviderServer = wpsf.get(w);
|
|
||||||
// Store the old provider
|
|
||||||
final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider");
|
|
||||||
return cp.get(worldProviderServer);
|
|
||||||
} catch (final Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object setProvider(final World world, Object newProvider) {
|
|
||||||
try {
|
|
||||||
// Provider 1
|
|
||||||
final Class<? extends World> clazz = world.getClass();
|
|
||||||
final Field wf = clazz.getDeclaredField("world");
|
|
||||||
wf.setAccessible(true);
|
|
||||||
final Object w = wf.get(world);
|
|
||||||
// ChunkProviderServer
|
|
||||||
final Class<? extends Object> clazz2 = w.getClass();
|
|
||||||
final Field wpsf = clazz2.getDeclaredField("chunkProviderServer");
|
|
||||||
// Store old provider server
|
|
||||||
final Object worldProviderServer = wpsf.get(w);
|
|
||||||
// Store the old provider
|
|
||||||
final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider");
|
|
||||||
final Object oldProvider = cp.get(worldProviderServer);
|
|
||||||
// Provider 2
|
|
||||||
final Class<? extends Object> clazz3 = worldProviderServer.getClass();
|
|
||||||
final Field provider2 = clazz3.getDeclaredField("chunkProvider");
|
|
||||||
// If the provider needs to be calculated
|
|
||||||
if (newProvider == null) {
|
|
||||||
Method k;
|
|
||||||
try {
|
|
||||||
k = clazz2.getDeclaredMethod("k");
|
|
||||||
} catch (final Throwable e) {
|
|
||||||
try {
|
|
||||||
k = clazz2.getDeclaredMethod("j");
|
|
||||||
} catch (final Throwable e2) {
|
|
||||||
e2.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
k.setAccessible(true);
|
|
||||||
final Object tempProviderServer = k.invoke(w);
|
|
||||||
newProvider = cp.get(tempProviderServer);
|
|
||||||
// Restore old provider
|
|
||||||
wpsf.set(w, worldProviderServer);
|
|
||||||
}
|
|
||||||
// Set provider for provider server
|
|
||||||
provider2.set(worldProviderServer, newProvider);
|
|
||||||
// Return the previous provider
|
|
||||||
return oldProvider;
|
|
||||||
} catch (final Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweChunk getChunk(int x, int z) {
|
public FaweChunk getChunk(int x, int z) {
|
||||||
return new BukkitChunk_1_9(this, x, z);
|
return new BukkitChunk_1_9(this, x, z);
|
||||||
|
@ -0,0 +1,373 @@
|
|||||||
|
package com.boydti.fawe.bukkit.v1_9;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.sk89q.jnbt.ByteArrayTag;
|
||||||
|
import com.sk89q.jnbt.ByteTag;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.DoubleTag;
|
||||||
|
import com.sk89q.jnbt.EndTag;
|
||||||
|
import com.sk89q.jnbt.FloatTag;
|
||||||
|
import com.sk89q.jnbt.IntArrayTag;
|
||||||
|
import com.sk89q.jnbt.IntTag;
|
||||||
|
import com.sk89q.jnbt.ListTag;
|
||||||
|
import com.sk89q.jnbt.LongTag;
|
||||||
|
import com.sk89q.jnbt.NBTConstants;
|
||||||
|
import com.sk89q.jnbt.ShortTag;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
|
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||||
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
|
import com.sk89q.worldedit.internal.Constants;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import net.minecraft.server.v1_9_R2.BiomeBase;
|
||||||
|
import net.minecraft.server.v1_9_R2.BlockPosition;
|
||||||
|
import net.minecraft.server.v1_9_R2.EntityTypes;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTBase;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagByte;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagByteArray;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagCompound;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagDouble;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagEnd;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagFloat;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagInt;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagIntArray;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagList;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagLong;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagShort;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagString;
|
||||||
|
import net.minecraft.server.v1_9_R2.TileEntity;
|
||||||
|
import net.minecraft.server.v1_9_R2.World;
|
||||||
|
import net.minecraft.server.v1_9_R2.WorldServer;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Biome;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.craftbukkit.v1_9_R2.CraftServer;
|
||||||
|
import org.bukkit.craftbukkit.v1_9_R2.CraftWorld;
|
||||||
|
import org.bukkit.craftbukkit.v1_9_R2.block.CraftBlock;
|
||||||
|
import org.bukkit.craftbukkit.v1_9_R2.entity.CraftEntity;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
|
||||||
|
public final class FaweAdapter_1_9 implements BukkitImplAdapter
|
||||||
|
{
|
||||||
|
private final Logger logger = Logger.getLogger(getClass().getCanonicalName());
|
||||||
|
private final Field nbtListTagListField;
|
||||||
|
private final Method nbtCreateTagMethod;
|
||||||
|
|
||||||
|
public FaweAdapter_1_9()
|
||||||
|
throws NoSuchFieldException, NoSuchMethodException
|
||||||
|
{
|
||||||
|
CraftServer.class.cast(Bukkit.getServer());
|
||||||
|
|
||||||
|
this.nbtListTagListField = NBTTagList.class.getDeclaredField("list");
|
||||||
|
this.nbtListTagListField.setAccessible(true);
|
||||||
|
|
||||||
|
this.nbtCreateTagMethod = NBTBase.class.getDeclaredMethod("createTag", new Class[] { Byte.TYPE });
|
||||||
|
this.nbtCreateTagMethod.setAccessible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void readTagIntoTileEntity(NBTTagCompound tag, TileEntity tileEntity)
|
||||||
|
{
|
||||||
|
tileEntity.a(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void readTileEntityIntoTag(TileEntity tileEntity, NBTTagCompound tag)
|
||||||
|
{
|
||||||
|
tileEntity.save(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static String getEntityId(net.minecraft.server.v1_9_R2.Entity entity)
|
||||||
|
{
|
||||||
|
return EntityTypes.b(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static net.minecraft.server.v1_9_R2.Entity createEntityFromId(String id, World world)
|
||||||
|
{
|
||||||
|
return EntityTypes.createEntityByName(id, world);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void readTagIntoEntity(NBTTagCompound tag, net.minecraft.server.v1_9_R2.Entity entity)
|
||||||
|
{
|
||||||
|
entity.f(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void readEntityIntoTag(net.minecraft.server.v1_9_R2.Entity entity, NBTTagCompound tag)
|
||||||
|
{
|
||||||
|
entity.e(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlockId(Material material)
|
||||||
|
{
|
||||||
|
return material.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Material getMaterial(int id)
|
||||||
|
{
|
||||||
|
return Material.getMaterial(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBiomeId(Biome biome)
|
||||||
|
{
|
||||||
|
BiomeBase mcBiome = CraftBlock.biomeToBiomeBase(biome);
|
||||||
|
return mcBiome != null ? BiomeBase.a(mcBiome) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Biome getBiome(int id)
|
||||||
|
{
|
||||||
|
BiomeBase mcBiome = BiomeBase.getBiome(id);
|
||||||
|
return CraftBlock.biomeBaseToBiome(mcBiome);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseBlock getBlock(Location location)
|
||||||
|
{
|
||||||
|
Preconditions.checkNotNull(location);
|
||||||
|
|
||||||
|
CraftWorld craftWorld = (CraftWorld)location.getWorld();
|
||||||
|
int x = location.getBlockX();
|
||||||
|
int y = location.getBlockY();
|
||||||
|
int z = location.getBlockZ();
|
||||||
|
|
||||||
|
Block bukkitBlock = location.getBlock();
|
||||||
|
BaseBlock block = new BaseBlock(bukkitBlock.getTypeId(), bukkitBlock.getData());
|
||||||
|
|
||||||
|
TileEntity te = craftWorld.getHandle().getTileEntity(new BlockPosition(x, y, z));
|
||||||
|
if (te != null)
|
||||||
|
{
|
||||||
|
NBTTagCompound tag = new NBTTagCompound();
|
||||||
|
readTileEntityIntoTag(te, tag);
|
||||||
|
block.setNbtData((CompoundTag)toNative(tag));
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setBlock(Location location, BaseBlock block, boolean notifyAndLight)
|
||||||
|
{
|
||||||
|
Preconditions.checkNotNull(location);
|
||||||
|
Preconditions.checkNotNull(block);
|
||||||
|
|
||||||
|
CraftWorld craftWorld = (CraftWorld)location.getWorld();
|
||||||
|
int x = location.getBlockX();
|
||||||
|
int y = location.getBlockY();
|
||||||
|
int z = location.getBlockZ();
|
||||||
|
|
||||||
|
boolean changed = location.getBlock().setTypeIdAndData(block.getId(), (byte)block.getData(), notifyAndLight);
|
||||||
|
|
||||||
|
CompoundTag nativeTag = block.getNbtData();
|
||||||
|
if (nativeTag != null)
|
||||||
|
{
|
||||||
|
TileEntity tileEntity = craftWorld.getHandle().getTileEntity(new BlockPosition(x, y, z));
|
||||||
|
if (tileEntity != null)
|
||||||
|
{
|
||||||
|
NBTTagCompound tag = (NBTTagCompound)fromNative(nativeTag);
|
||||||
|
tag.set("x", new NBTTagInt(x));
|
||||||
|
tag.set("y", new NBTTagInt(y));
|
||||||
|
tag.set("z", new NBTTagInt(z));
|
||||||
|
readTagIntoTileEntity(tag, tileEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseEntity getEntity(org.bukkit.entity.Entity entity)
|
||||||
|
{
|
||||||
|
Preconditions.checkNotNull(entity);
|
||||||
|
|
||||||
|
CraftEntity craftEntity = (CraftEntity)entity;
|
||||||
|
net.minecraft.server.v1_9_R2.Entity mcEntity = craftEntity.getHandle();
|
||||||
|
|
||||||
|
String id = getEntityId(mcEntity);
|
||||||
|
if (id != null)
|
||||||
|
{
|
||||||
|
NBTTagCompound tag = new NBTTagCompound();
|
||||||
|
readEntityIntoTag(mcEntity, tag);
|
||||||
|
return new BaseEntity(id, (CompoundTag)toNative(tag));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public org.bukkit.entity.Entity createEntity(Location location, BaseEntity state)
|
||||||
|
{
|
||||||
|
Preconditions.checkNotNull(location);
|
||||||
|
Preconditions.checkNotNull(state);
|
||||||
|
|
||||||
|
CraftWorld craftWorld = (CraftWorld)location.getWorld();
|
||||||
|
WorldServer worldServer = craftWorld.getHandle();
|
||||||
|
|
||||||
|
net.minecraft.server.v1_9_R2.Entity createdEntity = createEntityFromId(state.getTypeId(), craftWorld.getHandle());
|
||||||
|
if (createdEntity != null)
|
||||||
|
{
|
||||||
|
CompoundTag nativeTag = state.getNbtData();
|
||||||
|
if (nativeTag != null)
|
||||||
|
{
|
||||||
|
NBTTagCompound tag = (NBTTagCompound)fromNative(nativeTag);
|
||||||
|
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
||||||
|
tag.remove(name);
|
||||||
|
}
|
||||||
|
readTagIntoEntity(tag, createdEntity);
|
||||||
|
}
|
||||||
|
createdEntity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||||
|
|
||||||
|
worldServer.addEntity(createdEntity, CreatureSpawnEvent.SpawnReason.CUSTOM);
|
||||||
|
return createdEntity.getBukkitEntity();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tag toNative(NBTBase foreign)
|
||||||
|
{
|
||||||
|
if (foreign == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagCompound))
|
||||||
|
{
|
||||||
|
Map<String, Tag> values = new HashMap();
|
||||||
|
Set<String> foreignKeys = ((NBTTagCompound)foreign).c();
|
||||||
|
for (String str : foreignKeys)
|
||||||
|
{
|
||||||
|
NBTBase base = ((NBTTagCompound)foreign).get(str);
|
||||||
|
values.put(str, toNative(base));
|
||||||
|
}
|
||||||
|
return new CompoundTag(values);
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagByte)) {
|
||||||
|
return new ByteTag(((NBTTagByte)foreign).f());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagByteArray)) {
|
||||||
|
return new ByteArrayTag(((NBTTagByteArray)foreign).c());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagDouble)) {
|
||||||
|
return new DoubleTag(((NBTTagDouble)foreign).g());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagFloat)) {
|
||||||
|
return new FloatTag(((NBTTagFloat)foreign).h());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagInt)) {
|
||||||
|
return new IntTag(((NBTTagInt)foreign).d());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagIntArray)) {
|
||||||
|
return new IntArrayTag(((NBTTagIntArray)foreign).c());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagList)) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return toNativeList((NBTTagList)foreign);
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
this.logger.log(Level.WARNING, "Failed to convert NBTTagList", e);
|
||||||
|
return new ListTag(ByteTag.class, new ArrayList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagLong)) {
|
||||||
|
return new LongTag(((NBTTagLong)foreign).c());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagShort)) {
|
||||||
|
return new ShortTag(((NBTTagShort)foreign).e());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagString)) {
|
||||||
|
return new StringTag(((NBTTagString)foreign).a_());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof NBTTagEnd)) {
|
||||||
|
return new EndTag();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ListTag toNativeList(NBTTagList foreign)
|
||||||
|
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException
|
||||||
|
{
|
||||||
|
List<Tag> values = new ArrayList();
|
||||||
|
int type = foreign.d();
|
||||||
|
|
||||||
|
List foreignList = (List)this.nbtListTagListField.get(foreign);
|
||||||
|
for (int i = 0; i < foreign.size(); i++)
|
||||||
|
{
|
||||||
|
NBTBase element = (NBTBase)foreignList.get(i);
|
||||||
|
values.add(toNative(element));
|
||||||
|
}
|
||||||
|
Class<? extends Tag> cls = NBTConstants.getClassFromType(type);
|
||||||
|
return new ListTag(cls, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NBTBase fromNative(Tag foreign)
|
||||||
|
{
|
||||||
|
if (foreign == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Map.Entry<String, Tag> entry;
|
||||||
|
if ((foreign instanceof CompoundTag))
|
||||||
|
{
|
||||||
|
NBTTagCompound tag = new NBTTagCompound();
|
||||||
|
for (Iterator localIterator = ((CompoundTag)foreign)
|
||||||
|
.getValue().entrySet().iterator(); localIterator.hasNext();)
|
||||||
|
{
|
||||||
|
entry = (Map.Entry)localIterator.next();
|
||||||
|
|
||||||
|
tag.set((String)entry.getKey(), fromNative((Tag)entry.getValue()));
|
||||||
|
}
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
if ((foreign instanceof ByteTag)) {
|
||||||
|
return new NBTTagByte(((ByteTag)foreign).getValue().byteValue());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof ByteArrayTag)) {
|
||||||
|
return new NBTTagByteArray(((ByteArrayTag)foreign).getValue());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof DoubleTag)) {
|
||||||
|
return new NBTTagDouble(((DoubleTag)foreign).getValue().doubleValue());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof FloatTag)) {
|
||||||
|
return new NBTTagFloat(((FloatTag)foreign).getValue().floatValue());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof IntTag)) {
|
||||||
|
return new NBTTagInt(((IntTag)foreign).getValue().intValue());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof IntArrayTag)) {
|
||||||
|
return new NBTTagIntArray(((IntArrayTag)foreign).getValue());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof ListTag))
|
||||||
|
{
|
||||||
|
NBTTagList tag = new NBTTagList();
|
||||||
|
ListTag foreignList = (ListTag)foreign;
|
||||||
|
for (Tag t : foreignList.getValue()) {
|
||||||
|
tag.add(fromNative(t));
|
||||||
|
}
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
if ((foreign instanceof LongTag)) {
|
||||||
|
return new NBTTagLong(((LongTag)foreign).getValue().longValue());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof ShortTag)) {
|
||||||
|
return new NBTTagShort(((ShortTag)foreign).getValue().shortValue());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof StringTag)) {
|
||||||
|
return new NBTTagString(((StringTag)foreign).getValue());
|
||||||
|
}
|
||||||
|
if ((foreign instanceof EndTag)) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (NBTBase)this.nbtCreateTagMethod.invoke(null, new Object[] { Byte.valueOf((byte) 0) });
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
|
||||||
|
}
|
||||||
|
}
|
@ -21,9 +21,9 @@ commands:
|
|||||||
fawe:
|
fawe:
|
||||||
description: (FAWE) Reload the plugin
|
description: (FAWE) Reload the plugin
|
||||||
aliases: [/fawe,/fawereload]
|
aliases: [/fawe,/fawereload]
|
||||||
wrg:
|
select:
|
||||||
description: (FAWE) Select your current WorldEdit Region.
|
description: (FAWE) Select your current WorldEdit Region.
|
||||||
aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region]
|
aliases: [/select,wer,/wer,worldeditregion,/worldeditregion,/region]
|
||||||
frb:
|
frb:
|
||||||
description: (FAWE) Rollback an edit
|
description: (FAWE) Rollback an edit
|
||||||
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
||||||
|
@ -200,7 +200,7 @@ public class Fawe {
|
|||||||
this.IMP.setupCommand("wea", new Wea());
|
this.IMP.setupCommand("wea", new Wea());
|
||||||
this.IMP.setupCommand("fixlighting", new FixLighting());
|
this.IMP.setupCommand("fixlighting", new FixLighting());
|
||||||
this.IMP.setupCommand("stream", new Stream());
|
this.IMP.setupCommand("stream", new Stream());
|
||||||
this.IMP.setupCommand("wrg", new WorldEditRegion());
|
this.IMP.setupCommand("select", new WorldEditRegion());
|
||||||
this.IMP.setupCommand("fawe", new Reload());
|
this.IMP.setupCommand("fawe", new Reload());
|
||||||
this.IMP.setupCommand("frb", new Rollback());
|
this.IMP.setupCommand("frb", new Rollback());
|
||||||
this.IMP.setupCommand("fcancel", new Cancel());
|
this.IMP.setupCommand("fcancel", new Cancel());
|
||||||
|
@ -18,6 +18,7 @@ import com.sk89q.jnbt.IntTag;
|
|||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
import com.sk89q.jnbt.ShortTag;
|
import com.sk89q.jnbt.ShortTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
@ -39,6 +40,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
|
||||||
@ -51,6 +53,31 @@ import org.bukkit.Location;
|
|||||||
*/
|
*/
|
||||||
public class FaweAPI {
|
public class FaweAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new EditSessionfor a player<br>
|
||||||
|
* - The EditSession can be used from another thread<br>
|
||||||
|
* - FAWE will handle
|
||||||
|
* @see com.boydti.fawe.object.FawePlayer#wrap(Object)
|
||||||
|
* @param player
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public EditSession getNewEditSession(@Nonnull FawePlayer player) {
|
||||||
|
if (player == null) {
|
||||||
|
throw new IllegalArgumentException("Player may not be null");
|
||||||
|
}
|
||||||
|
return player.getNewEditSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new non-player EditSession
|
||||||
|
* @see #getWorld(String)
|
||||||
|
* @param world
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public EditSession getNewEditSession(World world) {
|
||||||
|
return WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The TaskManager has some useful methods for doing things asynchronously
|
* The TaskManager has some useful methods for doing things asynchronously
|
||||||
* @return TaskManager
|
* @return TaskManager
|
||||||
@ -133,7 +160,7 @@ public class FaweAPI {
|
|||||||
* Cancel the edit with the following extent<br>
|
* Cancel the edit with the following extent<br>
|
||||||
* - The extent must be the one being used by an EditSession, otherwise an error may be thrown <br>
|
* - The extent must be the one being used by an EditSession, otherwise an error may be thrown <br>
|
||||||
* - Insert an extent into the EditSession using the EditSessionEvent: http://wiki.sk89q.com/wiki/WorldEdit/API/Hooking_EditSession <br>
|
* - Insert an extent into the EditSession using the EditSessionEvent: http://wiki.sk89q.com/wiki/WorldEdit/API/Hooking_EditSession <br>
|
||||||
* @see com.sk89q.worldedit.EditSession#getFaweExtent() To get the FaweExtent for an EditSession
|
* @see com.sk89q.worldedit.EditSession#getRegionExtent() To get the FaweExtent for an EditSession
|
||||||
* @param extent
|
* @param extent
|
||||||
* @param reason
|
* @param reason
|
||||||
*/
|
*/
|
||||||
@ -229,7 +256,11 @@ public class FaweAPI {
|
|||||||
Collections.sort(files, new Comparator<File>() {
|
Collections.sort(files, new Comparator<File>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(File a, File b) {
|
public int compare(File a, File b) {
|
||||||
long value = a.lastModified() - b.lastModified();
|
String aName = a.getName();
|
||||||
|
String bName = b.getName();
|
||||||
|
int aI = Integer.parseInt(aName.substring(0, aName.length() - 3));
|
||||||
|
int bI = Integer.parseInt(bName.substring(0, bName.length() - 3));
|
||||||
|
long value = aI - bI;
|
||||||
return value == 0 ? 0 : value < 0 ? -1 : 1;
|
return value == 0 ? 0 : value < 0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -292,21 +323,21 @@ public class FaweAPI {
|
|||||||
* @param world
|
* @param world
|
||||||
* @param x
|
* @param x
|
||||||
* @param z
|
* @param z
|
||||||
* @param fixAll
|
* @param mode
|
||||||
*/
|
*/
|
||||||
public static void fixLighting(String world, int x, int z, final boolean fixAll) {
|
public static void fixLighting(String world, int x, int z, FaweQueue.RelightMode mode) {
|
||||||
FaweQueue queue = SetQueue.IMP.getNewQueue(world, true, false);
|
FaweQueue queue = SetQueue.IMP.getNewQueue(world, true, false);
|
||||||
queue.fixLighting(queue.getChunk(x, z), fixAll);
|
queue.fixLighting(queue.getChunk(x, z), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fix the lighting in a chunk
|
* Fix the lighting in a chunk
|
||||||
* @param chunk
|
* @param chunk
|
||||||
* @param fixAll
|
* @param mode
|
||||||
*/
|
*/
|
||||||
public static void fixLighting(final Chunk chunk, final boolean fixAll) {
|
public static void fixLighting(final Chunk chunk, FaweQueue.RelightMode mode) {
|
||||||
FaweQueue queue = SetQueue.IMP.getNewQueue(chunk.getWorld().getName(), true, false);
|
FaweQueue queue = SetQueue.IMP.getNewQueue(chunk.getWorld().getName(), true, false);
|
||||||
queue.fixLighting(queue.getChunk(chunk.getX(), chunk.getZ()), fixAll);
|
queue.fixLighting(queue.getChunk(chunk.getX(), chunk.getZ()), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -318,6 +349,7 @@ public class FaweAPI {
|
|||||||
* @param loc
|
* @param loc
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static void streamSchematic(final File file, final Location loc) {
|
public static void streamSchematic(final File file, final Location loc) {
|
||||||
final FaweLocation fl = new FaweLocation(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
final FaweLocation fl = new FaweLocation(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||||
streamSchematic(file, fl);
|
streamSchematic(file, fl);
|
||||||
@ -331,6 +363,7 @@ public class FaweAPI {
|
|||||||
* @param loc
|
* @param loc
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static void streamSchematic(final File file, final FaweLocation loc) {
|
public static void streamSchematic(final File file, final FaweLocation loc) {
|
||||||
try {
|
try {
|
||||||
final FileInputStream is = new FileInputStream(file);
|
final FileInputStream is = new FileInputStream(file);
|
||||||
@ -347,6 +380,7 @@ public class FaweAPI {
|
|||||||
* @param url
|
* @param url
|
||||||
* @param loc
|
* @param loc
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static void streamSchematic(final URL url, final FaweLocation loc) {
|
public static void streamSchematic(final URL url, final FaweLocation loc) {
|
||||||
try {
|
try {
|
||||||
final ReadableByteChannel rbc = Channels.newChannel(url.openStream());
|
final ReadableByteChannel rbc = Channels.newChannel(url.openStream());
|
||||||
@ -366,6 +400,7 @@ public class FaweAPI {
|
|||||||
* @param loc
|
* @param loc
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static void streamSchematic(final InputStream is, final FaweLocation loc) throws IOException {
|
public static void streamSchematic(final InputStream is, final FaweLocation loc) throws IOException {
|
||||||
final NBTInputStream stream = new NBTInputStream(new GZIPInputStream(is));
|
final NBTInputStream stream = new NBTInputStream(new GZIPInputStream(is));
|
||||||
Tag tag = stream.readNamedTag().getTag();
|
Tag tag = stream.readNamedTag().getTag();
|
||||||
@ -403,79 +438,10 @@ public class FaweAPI {
|
|||||||
final int i = i2 + x;
|
final int i = i2 + x;
|
||||||
final int xx = x_offset + x;
|
final int xx = x_offset + x;
|
||||||
final short id = (short) (ids[i] & 0xFF);
|
final short id = (short) (ids[i] & 0xFF);
|
||||||
switch (id) {
|
if (FaweCache.hasData(id)) {
|
||||||
case 0:
|
|
||||||
case 2:
|
|
||||||
case 4:
|
|
||||||
case 13:
|
|
||||||
case 14:
|
|
||||||
case 15:
|
|
||||||
case 20:
|
|
||||||
case 21:
|
|
||||||
case 22:
|
|
||||||
case 30:
|
|
||||||
case 32:
|
|
||||||
case 37:
|
|
||||||
case 39:
|
|
||||||
case 40:
|
|
||||||
case 41:
|
|
||||||
case 42:
|
|
||||||
case 45:
|
|
||||||
case 46:
|
|
||||||
case 47:
|
|
||||||
case 48:
|
|
||||||
case 49:
|
|
||||||
case 51:
|
|
||||||
case 56:
|
|
||||||
case 57:
|
|
||||||
case 58:
|
|
||||||
case 60:
|
|
||||||
case 7:
|
|
||||||
case 8:
|
|
||||||
case 9:
|
|
||||||
case 10:
|
|
||||||
case 11:
|
|
||||||
case 73:
|
|
||||||
case 74:
|
|
||||||
case 78:
|
|
||||||
case 79:
|
|
||||||
case 80:
|
|
||||||
case 81:
|
|
||||||
case 82:
|
|
||||||
case 83:
|
|
||||||
case 85:
|
|
||||||
case 87:
|
|
||||||
case 88:
|
|
||||||
case 101:
|
|
||||||
case 102:
|
|
||||||
case 103:
|
|
||||||
case 110:
|
|
||||||
case 112:
|
|
||||||
case 113:
|
|
||||||
case 121:
|
|
||||||
case 122:
|
|
||||||
case 129:
|
|
||||||
case 133:
|
|
||||||
case 165:
|
|
||||||
case 166:
|
|
||||||
case 169:
|
|
||||||
case 170:
|
|
||||||
case 172:
|
|
||||||
case 173:
|
|
||||||
case 174:
|
|
||||||
case 181:
|
|
||||||
case 182:
|
|
||||||
case 188:
|
|
||||||
case 189:
|
|
||||||
case 190:
|
|
||||||
case 191:
|
|
||||||
case 192:
|
|
||||||
queue.setBlock(xx, yy, zz, id, (byte) 0);
|
|
||||||
break;
|
|
||||||
default: {
|
|
||||||
queue.setBlock(xx, yy, zz, id, datas[i]);
|
queue.setBlock(xx, yy, zz, id, datas[i]);
|
||||||
break;
|
} else {
|
||||||
}
|
queue.setBlock(xx, yy, zz, id, (byte) 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,26 +6,56 @@ import com.sk89q.worldedit.blocks.BaseBlock;
|
|||||||
|
|
||||||
public class FaweCache {
|
public class FaweCache {
|
||||||
/**
|
/**
|
||||||
* y | x | z
|
* [ y | x | z ] => index
|
||||||
*/
|
*/
|
||||||
public final static short[][][] CACHE_I = new short[256][16][16];
|
public final static short[][][] CACHE_I = new short[256][16][16];
|
||||||
/**
|
/**
|
||||||
* y | x | z
|
* [ y | x | z ] => index
|
||||||
*/
|
*/
|
||||||
public final static short[][][] CACHE_J = new short[256][16][16];
|
public final static short[][][] CACHE_J = new short[256][16][16];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ i | j ] => x
|
||||||
|
*/
|
||||||
public final static byte[][] CACHE_X = new byte[16][4096];
|
public final static byte[][] CACHE_X = new byte[16][4096];
|
||||||
|
/**
|
||||||
|
* [ i | j ] => y
|
||||||
|
*/
|
||||||
public final static short[][] CACHE_Y = new short[16][4096];
|
public final static short[][] CACHE_Y = new short[16][4096];
|
||||||
|
/**
|
||||||
|
* [ i | j ] => z
|
||||||
|
*/
|
||||||
public final static byte[][] CACHE_Z = new byte[16][4096];
|
public final static byte[][] CACHE_Z = new byte[16][4096];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [ combined ] => id
|
||||||
|
* (combined >> 4) = id
|
||||||
|
*/
|
||||||
public final static short[] CACHE_ID = new short[65535];
|
public final static short[] CACHE_ID = new short[65535];
|
||||||
|
/**
|
||||||
|
* [ combined ] => data
|
||||||
|
* (combined & 0xF) = data
|
||||||
|
*/
|
||||||
public final static byte[] CACHE_DATA = new byte[65535];
|
public final static byte[] CACHE_DATA = new byte[65535];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immutable BaseBlock cache
|
||||||
|
* [ combined ] => block
|
||||||
|
*/
|
||||||
public final static BaseBlock[] CACHE_BLOCK = new BaseBlock[Short.MAX_VALUE];
|
public final static BaseBlock[] CACHE_BLOCK = new BaseBlock[Short.MAX_VALUE];
|
||||||
|
|
||||||
// Faster than java random (since the game just needs to look random)
|
/**
|
||||||
|
* Faster than java random (since it just needs to look random)
|
||||||
|
*/
|
||||||
public final static PseudoRandom RANDOM = new PseudoRandom();
|
public final static PseudoRandom RANDOM = new PseudoRandom();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cached BaseBlock object for an id/data<br>
|
||||||
|
* - The block is immutable
|
||||||
|
* @param id
|
||||||
|
* @param data
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public static BaseBlock getBlock(int id, int data) {
|
public static BaseBlock getBlock(int id, int data) {
|
||||||
return CACHE_BLOCK[(id << 4) + data];
|
return CACHE_BLOCK[(id << 4) + data];
|
||||||
}
|
}
|
||||||
@ -85,6 +115,11 @@ public class FaweCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an id might have data
|
||||||
|
* @param id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public static boolean hasData(int id) {
|
public static boolean hasData(int id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -168,6 +203,11 @@ public class FaweCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an id might have nbt
|
||||||
|
* @param id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public static boolean hasNBT(int id) {
|
public static boolean hasNBT(int id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 54:
|
case 54:
|
||||||
|
@ -28,7 +28,7 @@ public class Cancel extends FaweCommand {
|
|||||||
for (FaweQueue queue : queues) {
|
for (FaweQueue queue : queues) {
|
||||||
Set<EditSession> sessions = queue.getEditSessions();
|
Set<EditSession> sessions = queue.getEditSessions();
|
||||||
for (EditSession session : sessions) {
|
for (EditSession session : sessions) {
|
||||||
Actor actor = session.actor;
|
Actor actor = session.getActor();
|
||||||
if (actor == null) {
|
if (actor == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,13 @@ package com.boydti.fawe.command;
|
|||||||
|
|
||||||
import com.boydti.fawe.FaweAPI;
|
import com.boydti.fawe.FaweAPI;
|
||||||
import com.boydti.fawe.config.BBC;
|
import com.boydti.fawe.config.BBC;
|
||||||
import com.boydti.fawe.config.Settings;
|
|
||||||
import com.boydti.fawe.object.FaweCommand;
|
import com.boydti.fawe.object.FaweCommand;
|
||||||
import com.boydti.fawe.object.FaweLocation;
|
import com.boydti.fawe.object.FaweLocation;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
|
import com.boydti.fawe.util.FaweQueue;
|
||||||
|
import com.boydti.fawe.util.SetQueue;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
|
||||||
public class FixLighting extends FaweCommand {
|
public class FixLighting extends FaweCommand {
|
||||||
@ -21,27 +23,27 @@ public class FixLighting extends FaweCommand {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final FaweLocation loc = player.getLocation();
|
final FaweLocation loc = player.getLocation();
|
||||||
final Region selection = player.getSelection();
|
|
||||||
if (selection == null) {
|
|
||||||
FaweAPI.fixLighting(loc.world, loc.x >> 4, loc.z >> 4, Settings.FIX_ALL_LIGHTING);
|
|
||||||
BBC.FIX_LIGHTING_CHUNK.send(player);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
final int cx = loc.x >> 4;
|
final int cx = loc.x >> 4;
|
||||||
final int cz = loc.z >> 4;
|
final int cz = loc.z >> 4;
|
||||||
|
|
||||||
|
Region selection = player.getSelection();
|
||||||
|
if (selection == null) {
|
||||||
|
selection = new CuboidRegion(new Vector(cx - 8, 0, cz - 8).multiply(16), new Vector(cx + 8, 0, cz + 8).multiply(16));
|
||||||
|
}
|
||||||
final Vector bot = selection.getMinimumPoint();
|
final Vector bot = selection.getMinimumPoint();
|
||||||
final Vector top = selection.getMaximumPoint();
|
final Vector top = selection.getMaximumPoint();
|
||||||
|
|
||||||
final int minX = Math.max(cx - 8, bot.getBlockX() >> 4);
|
final int minX = bot.getBlockX() >> 4;
|
||||||
final int minZ = Math.max(cz - 8, bot.getBlockZ() >> 4);
|
final int minZ = bot.getBlockZ() >> 4;
|
||||||
|
|
||||||
final int maxX = Math.min(cx + 8, top.getBlockX() >> 4);
|
final int maxX = top.getBlockX() >> 4;
|
||||||
final int maxZ = Math.min(cz + 8, top.getBlockZ() >> 4);
|
final int maxZ = top.getBlockZ() >> 4;
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
FaweQueue queue = SetQueue.IMP.getNewQueue(loc.world, true, false);
|
||||||
for (int x = minX; x <= maxX; x++) {
|
for (int x = minX; x <= maxX; x++) {
|
||||||
for (int z = minZ; z <= maxZ; z++) {
|
for (int z = minZ; z <= maxZ; z++) {
|
||||||
FaweAPI.fixLighting(loc.world, x, z, Settings.FIX_ALL_LIGHTING);
|
queue.fixLighting(queue.getChunk(x, z), FaweQueue.RelightMode.ALL);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import com.boydti.fawe.object.RunnableVal;
|
|||||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.boydti.fawe.util.SetQueue;
|
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.blocks.ItemType;
|
import com.sk89q.worldedit.blocks.ItemType;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
@ -102,7 +101,7 @@ public class Rollback extends FaweCommand {
|
|||||||
EditSession session = edit.toEditSession(null);
|
EditSession session = edit.toEditSession(null);
|
||||||
session.undo(session);
|
session.undo(session);
|
||||||
edit.deleteFiles();
|
edit.deleteFiles();
|
||||||
SetQueue.IMP.addTask(this);
|
session.getQueue().addNotifyTask(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
task.run();
|
task.run();
|
||||||
|
@ -17,7 +17,7 @@ public enum BBC {
|
|||||||
* Things to note about this class:
|
* Things to note about this class:
|
||||||
* Can use multiple arguments %s, %s1, %s2, %s3 etc
|
* Can use multiple arguments %s, %s1, %s2, %s3 etc
|
||||||
*/
|
*/
|
||||||
PREFIX("&8(&5&lFAWE&8)&7", "Info"),
|
PREFIX("&8(&4&lFAWE&8)&7", "Info"),
|
||||||
SCHEMATIC_PASTING("&7The schematic is pasting. This cannot be undone.", "Info"),
|
SCHEMATIC_PASTING("&7The schematic is pasting. This cannot be undone.", "Info"),
|
||||||
FIX_LIGHTING_CHUNK("&7Lighting has been fixed in your current chunk. Relog to see the affect.", "Info"),
|
FIX_LIGHTING_CHUNK("&7Lighting has been fixed in your current chunk. Relog to see the affect.", "Info"),
|
||||||
FIX_LIGHTING_SELECTION("&7Lighting has been fixed in %s0 chunks. Relog to see the affect.", "Info"),
|
FIX_LIGHTING_SELECTION("&7Lighting has been fixed in %s0 chunks. Relog to see the affect.", "Info"),
|
||||||
@ -95,6 +95,8 @@ public enum BBC {
|
|||||||
SELECTOR_CUBOID_POS1("First position set to %s0 %s1.", "WorldEdit.Selector"),
|
SELECTOR_CUBOID_POS1("First position set to %s0 %s1.", "WorldEdit.Selector"),
|
||||||
SELECTOR_CUBOID_POS2("Second position set to %s0 %s1.", "WorldEdit.Selector"),
|
SELECTOR_CUBOID_POS2("Second position set to %s0 %s1.", "WorldEdit.Selector"),
|
||||||
|
|
||||||
|
PROGRESS_MESSAGE("[ Queue: %s0 | Dispatched: %s1 ]", "Progress"),
|
||||||
|
PROGRESS_DONE ("[ Took: %s0s ]", "Progress"),
|
||||||
|
|
||||||
|
|
||||||
COMMAND_SYNTAX("&cUsage: &7%s0", "Error"),
|
COMMAND_SYNTAX("&cUsage: &7%s0", "Error"),
|
||||||
|
@ -14,33 +14,37 @@ import java.util.Map.Entry;
|
|||||||
|
|
||||||
public class Settings {
|
public class Settings {
|
||||||
|
|
||||||
// public static boolean REQUIRE_SELECTION = false;
|
|
||||||
// public static boolean COMMAND_PROCESSOR = false;
|
|
||||||
// public static List<String> WE_BLACKLIST = Arrays.asList("cs", ".s", "restore", "snapshot", "delchunks", "listchunks");
|
|
||||||
public static long MEM_FREE = 95;
|
public static long MEM_FREE = 95;
|
||||||
public static boolean ENABLE_HARD_LIMIT = true;
|
public static boolean ENABLE_HARD_LIMIT = true;
|
||||||
public static boolean STORE_HISTORY_ON_DISK = false;
|
public static boolean STORE_HISTORY_ON_DISK = false;
|
||||||
public static boolean STORE_CLIPBOARD_ON_DISK = false;
|
public static boolean STORE_CLIPBOARD_ON_DISK = false;
|
||||||
public static int DELETE_HISTORY_AFTER_DAYS = 7;
|
public static int DELETE_HISTORY_AFTER_DAYS = 7;
|
||||||
|
public static boolean CLEAN_HISTORY_ON_LOGOUT = true;
|
||||||
public static int DELETE_CLIPBOARD_AFTER_DAYS = 1;
|
public static int DELETE_CLIPBOARD_AFTER_DAYS = 1;
|
||||||
public static int COMPRESSION_LEVEL = 0;
|
|
||||||
public static int BUFFER_SIZE = 531441;
|
|
||||||
public static boolean METRICS = true;
|
public static boolean METRICS = true;
|
||||||
public static int CHUNK_WAIT = 100;
|
public static int CHUNK_WAIT = 100;
|
||||||
public static boolean REGION_RESTRICTIONS = true;
|
public static boolean REGION_RESTRICTIONS = true;
|
||||||
public static int ALLOCATE = 0;
|
public static int ALLOCATE = 0;
|
||||||
public static int QUEUE_SIZE = 64;
|
public static int QUEUE_SIZE = 64;
|
||||||
public static int QUEUE_MAX_WAIT = 1000;
|
public static int QUEUE_MAX_WAIT = 1000;
|
||||||
public static int QUEUE_DISCARD_AFTER = 60000;
|
public static boolean DISPLAY_PROGRESS = false;
|
||||||
|
public static int DISPLAY_PROGRESS_INTERVAL = 1;
|
||||||
public static List<String> ALLOWED_3RDPARTY_EXTENTS;
|
public static List<String> ALLOWED_3RDPARTY_EXTENTS;
|
||||||
public static boolean EXTENT_DEBUG = true;
|
public static boolean EXTENT_DEBUG = true;
|
||||||
public static int UNSAFE_PARALLEL_THREADS = 1;
|
|
||||||
public static boolean FIX_ALL_LIGHTING = true;
|
public static boolean FIX_ALL_LIGHTING = true;
|
||||||
public static boolean ASYNC_LIGHTING = true;
|
public static boolean ASYNC_LIGHTING = true;
|
||||||
public static int PHYSICS_PER_TICK = 500000;
|
public static int PHYSICS_PER_TICK = 500000;
|
||||||
public static int ITEMS_PER_TICK = 50000;
|
public static int ITEMS_PER_TICK = 50000;
|
||||||
|
|
||||||
public static boolean COMBINE_HISTORY_STAGE = true;
|
// Maybe confusing?
|
||||||
|
// - `compression: false` just uses cheaper compression, but still compresses
|
||||||
|
public static int COMPRESSION_LEVEL = 0;
|
||||||
|
public static boolean COMBINE_HISTORY_STAGE = false;
|
||||||
|
public static int PARALLEL_THREADS = 1;
|
||||||
|
|
||||||
|
// Non configurable (yet / shouldn't be?)
|
||||||
|
public static int BUFFER_SIZE = 531441;
|
||||||
|
public static int QUEUE_DISCARD_AFTER = 60000;
|
||||||
|
|
||||||
public static HashMap<String, FaweLimit> limits;
|
public static HashMap<String, FaweLimit> limits;
|
||||||
|
|
||||||
@ -77,13 +81,11 @@ public class Settings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
final YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
|
final YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
|
||||||
|
config.set("DOCUMENTATION","https://github.com/boy0001/FastAsyncWorldedit/wiki/Configuration");
|
||||||
|
|
||||||
limits = new HashMap<>();
|
limits = new HashMap<>();
|
||||||
|
|
||||||
final Map<String, Object> options = new HashMap<>();
|
final Map<String, Object> options = new HashMap<>();
|
||||||
// options.put("require-selection-in-mask", REQUIRE_SELECTION);
|
|
||||||
// options.put("command-blacklist", WE_BLACKLIST);
|
|
||||||
// options.put("command-processor", COMMAND_PROCESSOR);
|
|
||||||
options.put("max-memory-percent", MEM_FREE);
|
options.put("max-memory-percent", MEM_FREE);
|
||||||
options.put("crash-mitigation", ENABLE_HARD_LIMIT);
|
options.put("crash-mitigation", ENABLE_HARD_LIMIT);
|
||||||
options.put("lighting.fix-all", FIX_ALL_LIGHTING);
|
options.put("lighting.fix-all", FIX_ALL_LIGHTING);
|
||||||
@ -93,18 +95,22 @@ public class Settings {
|
|||||||
options.put("history.use-disk", STORE_HISTORY_ON_DISK);
|
options.put("history.use-disk", STORE_HISTORY_ON_DISK);
|
||||||
options.put("history.compress", false);
|
options.put("history.compress", false);
|
||||||
options.put("history.chunk-wait-ms", CHUNK_WAIT);
|
options.put("history.chunk-wait-ms", CHUNK_WAIT);
|
||||||
// options.put("history.buffer-size", BUFFER_SIZE);
|
|
||||||
options.put("history.delete-after-days", DELETE_HISTORY_AFTER_DAYS);
|
options.put("history.delete-after-days", DELETE_HISTORY_AFTER_DAYS);
|
||||||
|
options.put("history.delete-on-logout", CLEAN_HISTORY_ON_LOGOUT);
|
||||||
options.put("region-restrictions", REGION_RESTRICTIONS);
|
options.put("region-restrictions", REGION_RESTRICTIONS);
|
||||||
options.put("queue.parallel-threads", UNSAFE_PARALLEL_THREADS);
|
|
||||||
options.put("queue.extra-time-ms", ALLOCATE);
|
options.put("queue.extra-time-ms", ALLOCATE);
|
||||||
|
options.put("queue.progress.display", DISPLAY_PROGRESS);
|
||||||
|
options.put("queue.progress.interval", DISPLAY_PROGRESS_INTERVAL);
|
||||||
options.put("queue.target-size", QUEUE_SIZE);
|
options.put("queue.target-size", QUEUE_SIZE);
|
||||||
options.put("queue.max-wait-ms", QUEUE_MAX_WAIT);
|
options.put("queue.max-wait-ms", QUEUE_MAX_WAIT);
|
||||||
// options.put("queue.discard-after-ms", QUEUE_DISCARD_AFTER);
|
|
||||||
options.put("extent.allowed-plugins", new ArrayList<String>());
|
options.put("extent.allowed-plugins", new ArrayList<String>());
|
||||||
options.put("extent.debug", EXTENT_DEBUG);
|
options.put("extent.debug", EXTENT_DEBUG);
|
||||||
options.put("metrics", METRICS);
|
options.put("metrics", METRICS);
|
||||||
|
|
||||||
|
// Possibly confusing? - leave configurable since not entirely stable yet
|
||||||
|
options.put("history.combine-stages", COMBINE_HISTORY_STAGE);
|
||||||
|
options.put("queue.parallel-threads", Math.max(1, Runtime.getRuntime().availableProcessors()));
|
||||||
|
|
||||||
if (config.getInt("tick-limiter.physics") == 1337) {
|
if (config.getInt("tick-limiter.physics") == 1337) {
|
||||||
config.set("tick-limiter.physics", PHYSICS_PER_TICK);
|
config.set("tick-limiter.physics", PHYSICS_PER_TICK);
|
||||||
}
|
}
|
||||||
@ -130,21 +136,19 @@ public class Settings {
|
|||||||
FIX_ALL_LIGHTING = config.getBoolean("lighting.fix-all");
|
FIX_ALL_LIGHTING = config.getBoolean("lighting.fix-all");
|
||||||
ASYNC_LIGHTING = config.getBoolean("lighting.async");
|
ASYNC_LIGHTING = config.getBoolean("lighting.async");
|
||||||
MEM_FREE = config.getInt("max-memory-percent");
|
MEM_FREE = config.getInt("max-memory-percent");
|
||||||
// COMMAND_PROCESSOR = config.getBoolean("command-processor");
|
|
||||||
// REQUIRE_SELECTION = config.getBoolean("require-selection-in-mask");
|
|
||||||
// WE_BLACKLIST = config.getStringList("command-blacklist");
|
|
||||||
ENABLE_HARD_LIMIT = config.getBoolean("crash-mitigation");
|
ENABLE_HARD_LIMIT = config.getBoolean("crash-mitigation");
|
||||||
REGION_RESTRICTIONS = config.getBoolean("region-restrictions");
|
REGION_RESTRICTIONS = config.getBoolean("region-restrictions");
|
||||||
METRICS = config.getBoolean("metrics");
|
METRICS = config.getBoolean("metrics");
|
||||||
COMPRESSION_LEVEL = config.getInt("history.compression-level", config.getBoolean("history.compress") ? 1 : 0);
|
COMPRESSION_LEVEL = config.getInt("history.compression-level", config.getBoolean("history.compress") ? 1 : 0);
|
||||||
DELETE_HISTORY_AFTER_DAYS = config.getInt("history.delete-after-days");
|
DELETE_HISTORY_AFTER_DAYS = config.getInt("history.delete-after-days");
|
||||||
BUFFER_SIZE = config.getInt("history.buffer-size", BUFFER_SIZE);
|
CLEAN_HISTORY_ON_LOGOUT = config.getBoolean("history.delete-on-logout");
|
||||||
CHUNK_WAIT = config.getInt("history.chunk-wait-ms");
|
CHUNK_WAIT = config.getInt("history.chunk-wait-ms");
|
||||||
ALLOCATE = config.getInt("queue.extra-time-ms");
|
ALLOCATE = config.getInt("queue.extra-time-ms");
|
||||||
QUEUE_SIZE = config.getInt("queue.target-size");
|
QUEUE_SIZE = config.getInt("queue.target-size");
|
||||||
QUEUE_MAX_WAIT = config.getInt("queue.max-wait-ms");
|
QUEUE_MAX_WAIT = config.getInt("queue.max-wait-ms");
|
||||||
UNSAFE_PARALLEL_THREADS = config.getInt("queue.parallel-threads");
|
DISPLAY_PROGRESS = config.getBoolean("queue.progress.display");
|
||||||
QUEUE_DISCARD_AFTER = config.getInt("queue.discard-after-ms", QUEUE_DISCARD_AFTER);
|
DISPLAY_PROGRESS_INTERVAL = config.getInt("queue.progress.interval");
|
||||||
|
PARALLEL_THREADS = config.getInt("queue.parallel-threads", Math.max(1, Runtime.getRuntime().availableProcessors()));
|
||||||
ALLOWED_3RDPARTY_EXTENTS = config.getStringList("extent.allowed-plugins");
|
ALLOWED_3RDPARTY_EXTENTS = config.getStringList("extent.allowed-plugins");
|
||||||
EXTENT_DEBUG = config.getBoolean("extent.debug");
|
EXTENT_DEBUG = config.getBoolean("extent.debug");
|
||||||
STORE_CLIPBOARD_ON_DISK = config.getBoolean("clipboard.use-disk");
|
STORE_CLIPBOARD_ON_DISK = config.getBoolean("clipboard.use-disk");
|
||||||
@ -152,6 +156,11 @@ public class Settings {
|
|||||||
PHYSICS_PER_TICK = config.getInt("tick-limiter.physics");
|
PHYSICS_PER_TICK = config.getInt("tick-limiter.physics");
|
||||||
ITEMS_PER_TICK = config.getInt("tick-limiter.items");
|
ITEMS_PER_TICK = config.getInt("tick-limiter.items");
|
||||||
|
|
||||||
|
// Not usually configurable
|
||||||
|
BUFFER_SIZE = config.getInt("history.buffer-size", BUFFER_SIZE);
|
||||||
|
QUEUE_DISCARD_AFTER = config.getInt("queue.discard-after-ms", QUEUE_DISCARD_AFTER);
|
||||||
|
COMBINE_HISTORY_STAGE = config.getBoolean("history.combine-stages", COMBINE_HISTORY_STAGE);
|
||||||
|
|
||||||
if (STORE_HISTORY_ON_DISK = config.getBoolean("history.use-disk")) {
|
if (STORE_HISTORY_ON_DISK = config.getBoolean("history.use-disk")) {
|
||||||
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
|
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
||||||
|
|
||||||
@ -111,7 +112,7 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
|||||||
return this.ids[i];
|
return this.ids[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
public char[][] getIdArrays() {
|
public char[][] getCombinedIdArrays() {
|
||||||
return this.ids;
|
return this.ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,8 +154,12 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
|||||||
return entities == null ? new HashSet<CompoundTag>() : entities;
|
return entities == null ? new HashSet<CompoundTag>() : entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public HashSet<CompoundTag> entities;
|
public HashSet<CompoundTag> entities;
|
||||||
|
|
||||||
|
public HashSet<UUID> entityRemoves;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEntity(CompoundTag tag) {
|
public void setEntity(CompoundTag tag) {
|
||||||
if (entities == null) {
|
if (entities == null) {
|
||||||
@ -163,6 +168,19 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
|||||||
entities.add(tag);
|
entities.add(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeEntity(UUID uuid) {
|
||||||
|
if (entityRemoves == null) {
|
||||||
|
entityRemoves = new HashSet<>();
|
||||||
|
}
|
||||||
|
entityRemoves.add(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashSet<UUID> getEntityRemoves() {
|
||||||
|
return entityRemoves == null ? new HashSet<UUID>() : entityRemoves;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBlock(final int x, final int y, final int z, final int id, byte data) {
|
public void setBlock(final int x, final int y, final int z, final int id, byte data) {
|
||||||
final int i = FaweCache.CACHE_I[y][x][z];
|
final int i = FaweCache.CACHE_I[y][x][z];
|
||||||
|
@ -14,6 +14,7 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
|
|||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
|
|
||||||
@ -25,7 +26,15 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
* Map of chunks in the queue
|
* Map of chunks in the queue
|
||||||
*/
|
*/
|
||||||
private ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<>();
|
private ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<>();
|
||||||
private LinkedBlockingDeque<FaweChunk> chunks = new LinkedBlockingDeque<>();
|
private LinkedBlockingDeque<FaweChunk> chunks = new LinkedBlockingDeque<FaweChunk>() {
|
||||||
|
@Override
|
||||||
|
public boolean add(FaweChunk o) {
|
||||||
|
if (progressTask != null) {
|
||||||
|
progressTask.run(ProgressType.QUEUE, size() + 1);
|
||||||
|
}
|
||||||
|
return super.add(o);
|
||||||
|
}
|
||||||
|
};
|
||||||
private ArrayDeque<Runnable> tasks = new ArrayDeque<>();
|
private ArrayDeque<Runnable> tasks = new ArrayDeque<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,6 +62,7 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
@Override
|
@Override
|
||||||
public void addNotifyTask(Runnable runnable) {
|
public void addNotifyTask(Runnable runnable) {
|
||||||
this.tasks.add(runnable);
|
this.tasks.add(runnable);
|
||||||
|
size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedFaweQueue(final String world) {
|
public MappedFaweQueue(final String world) {
|
||||||
@ -72,9 +82,6 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
@Override
|
@Override
|
||||||
public abstract FaweChunk getChunk(int x, int z);
|
public abstract FaweChunk getChunk(int x, int z);
|
||||||
|
|
||||||
@Override
|
|
||||||
public abstract boolean fixLighting(FaweChunk fc, boolean fixAll);
|
|
||||||
|
|
||||||
public abstract boolean loadChunk(WORLD world, int x, int z, boolean generate);
|
public abstract boolean loadChunk(WORLD world, int x, int z, boolean generate);
|
||||||
|
|
||||||
public abstract CHUNK getCachedChunk(WORLD world, int cx, int cz);
|
public abstract CHUNK getCachedChunk(WORLD world, int cx, int cz);
|
||||||
@ -202,6 +209,33 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
lastWrappedChunk.setEntity(tag);
|
lastWrappedChunk.setEntity(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeEntity(int x, int y, int z, UUID uuid) {
|
||||||
|
if ((y > 255) || (y < 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int cx = x >> 4;
|
||||||
|
int cz = z >> 4;
|
||||||
|
if (cx != lastX || cz != lastZ) {
|
||||||
|
lastX = cx;
|
||||||
|
lastZ = cz;
|
||||||
|
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||||
|
lastWrappedChunk = this.blocks.get(pair);
|
||||||
|
if (lastWrappedChunk == null) {
|
||||||
|
lastWrappedChunk = this.getChunk(x >> 4, z >> 4);
|
||||||
|
lastWrappedChunk.removeEntity(uuid);
|
||||||
|
FaweChunk previous = this.blocks.put(pair, lastWrappedChunk);
|
||||||
|
if (previous == null) {
|
||||||
|
chunks.add(lastWrappedChunk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.blocks.put(pair, previous);
|
||||||
|
lastWrappedChunk = previous;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastWrappedChunk.removeEntity(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setBiome(int x, int z, BaseBiome biome) {
|
public boolean setBiome(int x, int z, BaseBiome biome) {
|
||||||
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
|
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
|
||||||
@ -243,15 +277,23 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void runTasks() {
|
public void runTasks() {
|
||||||
for (Runnable run : tasks) {
|
if (progressTask != null) {
|
||||||
run.run();
|
progressTask.run(ProgressType.DONE, 1);
|
||||||
}
|
}
|
||||||
|
ArrayDeque<Runnable> tmp = new ArrayDeque<>(tasks);
|
||||||
tasks.clear();
|
tasks.clear();
|
||||||
|
for (Runnable run : tmp) {
|
||||||
|
try {
|
||||||
|
run.run();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
if (chunks.size() == 0 && SetQueue.IMP.isStage(this, SetQueue.QueueStage.ACTIVE)) {
|
if (chunks.size() == 0 && SetQueue.IMP.getStage(this) != SetQueue.QueueStage.INACTIVE) {
|
||||||
runTasks();
|
runTasks();
|
||||||
}
|
}
|
||||||
return chunks.size();
|
return chunks.size();
|
||||||
@ -259,11 +301,17 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
|
|
||||||
private LinkedBlockingDeque<FaweChunk> toUpdate = new LinkedBlockingDeque<>();
|
private LinkedBlockingDeque<FaweChunk> toUpdate = new LinkedBlockingDeque<>();
|
||||||
|
|
||||||
|
private int dispatched = 0;
|
||||||
|
|
||||||
public boolean execute(final FaweChunk fc) {
|
public boolean execute(final FaweChunk fc) {
|
||||||
if (fc == null) {
|
if (fc == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Set blocks / entities / biome
|
// Set blocks / entities / biome
|
||||||
|
if (progressTask != null) {
|
||||||
|
progressTask.run(ProgressType.QUEUE, chunks.size());
|
||||||
|
progressTask.run(ProgressType.DISPATCH, ++dispatched);
|
||||||
|
}
|
||||||
if (getChangeTask() != null) {
|
if (getChangeTask() != null) {
|
||||||
if (!this.setComponents(fc, new RunnableVal<FaweChunk>() {
|
if (!this.setComponents(fc, new RunnableVal<FaweChunk>() {
|
||||||
@Override
|
@Override
|
||||||
@ -284,6 +332,7 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
public void clear() {
|
public void clear() {
|
||||||
this.blocks.clear();
|
this.blocks.clear();
|
||||||
this.chunks.clear();
|
this.chunks.clear();
|
||||||
|
runTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2,7 +2,12 @@ package com.boydti.fawe.example;
|
|||||||
|
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
|
import com.boydti.fawe.util.FaweQueue;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> extends MappedFaweQueue<WORLD, CHUNKSECTION, SECTION> {
|
public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> extends MappedFaweQueue<WORLD, CHUNKSECTION, SECTION> {
|
||||||
public NMSMappedFaweQueue(String world) {
|
public NMSMappedFaweQueue(String world) {
|
||||||
@ -14,12 +19,12 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
|||||||
TaskManager.IMP.taskSyncSoon(new Runnable() {
|
TaskManager.IMP.taskSyncSoon(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING ? FaweQueue.RelightMode.OPTIMAL : FaweQueue.RelightMode.MINIMAL) || !Settings.ASYNC_LIGHTING;
|
||||||
TaskManager.IMP.taskSyncNow(new Runnable() {
|
TaskManager.IMP.taskSyncNow(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
fixLighting(fc, Settings.FIX_ALL_LIGHTING ? FaweQueue.RelightMode.OPTIMAL : FaweQueue.RelightMode.MINIMAL);
|
||||||
}
|
}
|
||||||
CHUNK chunk = (CHUNK) fc.getChunk();
|
CHUNK chunk = (CHUNK) fc.getChunk();
|
||||||
refreshChunk(getWorld(), chunk);
|
refreshChunk(getWorld(), chunk);
|
||||||
@ -31,6 +36,5 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
|||||||
|
|
||||||
public abstract void refreshChunk(WORLD world, CHUNK chunk);
|
public abstract void refreshChunk(WORLD world, CHUNK chunk);
|
||||||
|
|
||||||
@Override
|
public abstract CharFaweChunk getPrevious(CharFaweChunk fs, CHUNKSECTION sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception;
|
||||||
public abstract boolean fixLighting(FaweChunk fc, boolean fixAll);
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,14 @@ public class BytePair {
|
|||||||
|
|
||||||
int hash;
|
int hash;
|
||||||
|
|
||||||
|
public byte get0() {
|
||||||
|
return pair[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte get1() {
|
||||||
|
return pair[1];
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return pair[0] + (pair[1] << 8);
|
return pair[0] + (pair[1] << 8);
|
||||||
|
@ -117,7 +117,7 @@ public class EditSessionWrapper {
|
|||||||
return minY;
|
return minY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Extent getHistoryExtent(EditSession session, FaweLimit limit, Extent parent, FaweChangeSet set, FaweQueue queue, FawePlayer<?> player) {
|
public FaweChangeSet wrapChangeSet(EditSession session, FaweLimit limit, Extent parent, FaweChangeSet set, FaweQueue queue, FawePlayer<?> player) {
|
||||||
return new HistoryExtent(session, limit, parent, set, queue);
|
return set;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.boydti.fawe.object;
|
package com.boydti.fawe.object;
|
||||||
|
|
||||||
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.util.FaweQueue;
|
import com.boydti.fawe.util.FaweQueue;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
@ -7,6 +8,7 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
|
|||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class FaweChunk<T> {
|
public abstract class FaweChunk<T> {
|
||||||
|
|
||||||
@ -24,12 +26,23 @@ public abstract class FaweChunk<T> {
|
|||||||
this.z = z;
|
this.z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the chunk's location<br>
|
||||||
|
* - E.g. if you are cloning a chunk and want to set multiple
|
||||||
|
* @param parent
|
||||||
|
* @param x
|
||||||
|
* @param z
|
||||||
|
*/
|
||||||
public void setLoc(FaweQueue parent, int x, int z) {
|
public void setLoc(FaweQueue parent, int x, int z) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the parent queue this chunk belongs to
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public FaweQueue getParent() {
|
public FaweQueue getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
@ -42,24 +55,65 @@ public abstract class FaweChunk<T> {
|
|||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a unique hashcode for this chunk
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public long longHash() {
|
public long longHash() {
|
||||||
return (long) x << 32 | z & 0xFFFFFFFFL;
|
return (long) x << 32 | z & 0xFFFFFFFFL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a hashcode; unique below abs(x/z) < Short.MAX_VALUE
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return x << 16 | z & 0xFFFF;
|
return x << 16 | z & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the chunk to the queue
|
||||||
|
*/
|
||||||
public void addToQueue() {
|
public void addToQueue() {
|
||||||
parent.setChunk(this);
|
parent.setChunk(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix the lighting in this chunk
|
||||||
|
*/
|
||||||
public void fixLighting() {
|
public void fixLighting() {
|
||||||
parent.fixLighting(this, Settings.FIX_ALL_LIGHTING);
|
parent.fixLighting(this, Settings.FIX_ALL_LIGHTING ? FaweQueue.RelightMode.OPTIMAL : FaweQueue.RelightMode.MINIMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract char[][] getIdArrays();
|
/**
|
||||||
|
* This may return the raw value or constructed depending on the implementation<br>
|
||||||
|
* - The first index (i) is the layer (layer = y >> 4) (16 layers)<br>
|
||||||
|
* - The second array is length 4096 and contains the combined ids (cast to an int if you want)
|
||||||
|
*
|
||||||
|
* @see com.boydti.fawe.FaweCache#CACHE_I
|
||||||
|
* @see com.boydti.fawe.FaweCache#CACHE_J
|
||||||
|
* @see com.boydti.fawe.FaweCache#CACHE_X
|
||||||
|
* @see com.boydti.fawe.FaweCache#CACHE_Y
|
||||||
|
* @see com.boydti.fawe.FaweCache#CACHE_Z
|
||||||
|
*
|
||||||
|
* @return Combined id arrays
|
||||||
|
*/
|
||||||
|
public abstract char[][] getCombinedIdArrays();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the combined block id at a location<br>
|
||||||
|
* combined = (id <<<< 4) + data
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
* @param z
|
||||||
|
* @return The combined id
|
||||||
|
*/
|
||||||
|
public int getBlockCombinedId(int x, int y, int z) {
|
||||||
|
char[][] arrays = getCombinedIdArrays();
|
||||||
|
char[] array = arrays[y >> 4];
|
||||||
|
return array != null ? (array[FaweCache.CACHE_J[y][x][z]]) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill this chunk with a block
|
* Fill this chunk with a block
|
||||||
@ -91,6 +145,10 @@ public abstract class FaweChunk<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a task to run when this chunk is dispatched
|
||||||
|
* @param run
|
||||||
|
*/
|
||||||
public void addNotifyTask(Runnable run) {
|
public void addNotifyTask(Runnable run) {
|
||||||
if (run != null) {
|
if (run != null) {
|
||||||
tasks.add(run);
|
tasks.add(run);
|
||||||
@ -108,22 +166,61 @@ public abstract class FaweChunk<T> {
|
|||||||
tasks.clear();
|
tasks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the underlying chunk object
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public abstract T getChunk();
|
public abstract T getChunk();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a tile entity at a location<br>
|
||||||
|
* - May throw an error if an invalid block is at the location
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
* @param z
|
||||||
|
* @param tile
|
||||||
|
*/
|
||||||
public abstract void setTile(int x, int y, int z, CompoundTag tile);
|
public abstract void setTile(int x, int y, int z, CompoundTag tile);
|
||||||
|
|
||||||
public abstract void setEntity(CompoundTag entity);
|
public abstract void setEntity(CompoundTag entity);
|
||||||
|
|
||||||
public abstract void setBlock(final int x, final int y, final int z, final int id, final byte data);
|
public abstract void removeEntity(UUID uuid);
|
||||||
|
|
||||||
public abstract CompoundTag getTile(int x, int y, int z);
|
public abstract void setBlock(final int x, final int y, final int z, final int id, final byte data);
|
||||||
|
|
||||||
public abstract Set<CompoundTag> getEntities();
|
public abstract Set<CompoundTag> getEntities();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the UUID of entities being removed
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract Set<UUID> getEntityRemoves();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the map of location to tile entity<br>
|
||||||
|
* - The byte pair represents the location in the chunk<br>
|
||||||
|
* @see com.boydti.fawe.util.MathMan#unpair16x (get0) => x
|
||||||
|
* @see com.boydti.fawe.util.MathMan#unpair16y (get0) => z
|
||||||
|
* get1 => y
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public abstract Map<BytePair, CompoundTag> getTiles();
|
public abstract Map<BytePair, CompoundTag> getTiles();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the tile at a location
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
* @param z
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract CompoundTag getTile(int x, int y, int z);
|
||||||
|
|
||||||
public abstract void setBiome(final int x, final int z, final BaseBiome biome);
|
public abstract void setBiome(final int x, final int z, final BaseBiome biome);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spend time now so that the chunk can be more efficiently dispatched later<br>
|
||||||
|
* - Modifications after this call will be ignored
|
||||||
|
*/
|
||||||
public void optimize() {}
|
public void optimize() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,6 +21,7 @@ public abstract class FaweCommand<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean executeSafe(final FawePlayer<T> player, final String... args) {
|
public boolean executeSafe(final FawePlayer<T> player, final String... args) {
|
||||||
|
try {
|
||||||
if (player == null || !safe) {
|
if (player == null || !safe) {
|
||||||
execute(player, args);
|
execute(player, args);
|
||||||
return true;
|
return true;
|
||||||
@ -39,6 +40,10 @@ public abstract class FaweCommand<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean execute(final FawePlayer<T> player, final String... args);
|
public abstract boolean execute(final FawePlayer<T> player, final String... args);
|
||||||
|
@ -173,7 +173,7 @@ public abstract class FawePlayer<T> {
|
|||||||
FaweStreamChangeSet set = new DiskStorageHistory(world, uuid, index);
|
FaweStreamChangeSet set = new DiskStorageHistory(world, uuid, index);
|
||||||
EditSession edit = set.toEditSession(getPlayer());
|
EditSession edit = set.toEditSession(getPlayer());
|
||||||
if (world.equals(getWorld())) {
|
if (world.equals(getWorld())) {
|
||||||
session.remember(edit, false);
|
session.remember(edit, false, false);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -184,6 +184,15 @@ public abstract class FawePlayer<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a title
|
||||||
|
* @param head
|
||||||
|
* @param sub
|
||||||
|
*/
|
||||||
|
public abstract void sendTitle(String head, String sub);
|
||||||
|
|
||||||
|
public abstract void resetTitle();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the player's limit
|
* Get the player's limit
|
||||||
* @return
|
* @return
|
||||||
@ -370,4 +379,11 @@ public abstract class FawePlayer<T> {
|
|||||||
WorldEdit.getInstance().removeSession(getPlayer());
|
WorldEdit.getInstance().removeSession(getPlayer());
|
||||||
Fawe.get().unregister(getName());
|
Fawe.get().unregister(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new EditSession from this player
|
||||||
|
*/
|
||||||
|
public EditSession getNewEditSession() {
|
||||||
|
return WorldEdit.getInstance().getEditSessionFactory().getEditSession(getWorld(), -1, getPlayer());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,15 @@ package com.boydti.fawe.object;
|
|||||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.history.change.Change;
|
import com.sk89q.worldedit.history.change.Change;
|
||||||
|
import com.sk89q.worldedit.world.World;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
public class NullChangeSet extends FaweChangeSet {
|
public class NullChangeSet extends FaweChangeSet {
|
||||||
|
public NullChangeSet(World world) {
|
||||||
|
super(world);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean flush() {
|
public boolean flush() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.boydti.fawe.object.brush;
|
||||||
|
|
||||||
|
public class AbstractDelegateBrush {
|
||||||
|
}
|
@ -1,30 +1,23 @@
|
|||||||
package com.boydti.fawe.object.brush;
|
package com.boydti.fawe.object.brush;
|
||||||
|
|
||||||
import com.boydti.fawe.config.BBC;
|
import com.boydti.fawe.config.BBC;
|
||||||
import com.boydti.fawe.object.IntegerPair;
|
import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
|
||||||
import com.boydti.fawe.object.brush.heightmap.ArrayHeightMap;
|
|
||||||
import com.boydti.fawe.object.brush.heightmap.HeightMap;
|
|
||||||
import com.boydti.fawe.object.exception.FaweException;
|
import com.boydti.fawe.object.exception.FaweException;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
|
||||||
import com.sk89q.worldedit.command.tool.BrushTool;
|
import com.sk89q.worldedit.command.tool.BrushTool;
|
||||||
import com.sk89q.worldedit.command.tool.brush.Brush;
|
import com.sk89q.worldedit.command.tool.brush.Brush;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.mask.Masks;
|
import com.sk89q.worldedit.function.mask.Masks;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.awt.image.Raster;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashSet;
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
|
|
||||||
public class HeightBrush implements Brush {
|
public class HeightBrush implements Brush {
|
||||||
|
|
||||||
public final HeightMap heightMap;
|
public final ScalableHeightMap heightMap;
|
||||||
private final int rotation;
|
private final int rotation;
|
||||||
double yscale = 1;
|
double yscale = 1;
|
||||||
private final BrushTool tool;
|
private final BrushTool tool;
|
||||||
@ -36,57 +29,13 @@ public class HeightBrush implements Brush {
|
|||||||
if (file == null || !file.exists()) {
|
if (file == null || !file.exists()) {
|
||||||
// Since I can't be bothered using separate args, we'll get it from the filename
|
// Since I can't be bothered using separate args, we'll get it from the filename
|
||||||
if (file.getName().equalsIgnoreCase("#clipboard.png") && clipboard != null) {
|
if (file.getName().equalsIgnoreCase("#clipboard.png") && clipboard != null) {
|
||||||
Vector dim = clipboard.getDimensions();
|
heightMap = ScalableHeightMap.fromClipboard(clipboard);
|
||||||
byte[][] heightArray = new byte[dim.getBlockX()][dim.getBlockZ()];
|
|
||||||
int minX = clipboard.getMinimumPoint().getBlockX();
|
|
||||||
int minZ = clipboard.getMinimumPoint().getBlockZ();
|
|
||||||
int minY = clipboard.getMinimumPoint().getBlockY();
|
|
||||||
int maxY = clipboard.getMaximumPoint().getBlockY();
|
|
||||||
int clipHeight = maxY - minY + 1;
|
|
||||||
HashSet<IntegerPair> visited = new HashSet<>();
|
|
||||||
for (Vector pos : clipboard.getRegion()) {
|
|
||||||
IntegerPair pair = new IntegerPair((int) pos.x, (int) pos.z);
|
|
||||||
if (visited.contains(pair)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
visited.add(pair);
|
|
||||||
int xx = pos.getBlockX();
|
|
||||||
int zz = pos.getBlockZ();
|
|
||||||
int highestY = 0;
|
|
||||||
for (int y = minY; y <= maxY; y++) {
|
|
||||||
pos.y = y;
|
|
||||||
BaseBlock block = clipboard.getBlock(pos);
|
|
||||||
if (block != EditSession.nullBlock) {
|
|
||||||
highestY = y + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int pointHeight = Math.min(255, (256 * (highestY - minY)) / clipHeight);
|
|
||||||
int x = xx - minX;
|
|
||||||
int z = zz - minZ;
|
|
||||||
heightArray[x][z] = (byte) pointHeight;
|
|
||||||
}
|
|
||||||
heightMap = new ArrayHeightMap(heightArray);
|
|
||||||
} else {
|
} else {
|
||||||
heightMap = new HeightMap();
|
heightMap = new ScalableHeightMap();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
BufferedImage heightFile = ImageIO.read(file);
|
heightMap = ScalableHeightMap.fromPNG(file);
|
||||||
int width = heightFile.getWidth();
|
|
||||||
int length = heightFile.getHeight();
|
|
||||||
Raster data = heightFile.getData();
|
|
||||||
byte[][] array = new byte[width][length];
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
for (int z = 0; z < length; z++) {
|
|
||||||
int pixel = heightFile.getRGB(x, z);
|
|
||||||
int red = (pixel >> 16) & 0xFF;
|
|
||||||
int green = (pixel >> 8) & 0xFF;
|
|
||||||
int blue = (pixel >> 0) & 0xFF;
|
|
||||||
int intensity = (red + green + blue) / 3;
|
|
||||||
array[x][z] = (byte) intensity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
heightMap = new ArrayHeightMap(array);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new FaweException(BBC.BRUSH_HEIGHT_INVALID);
|
throw new FaweException(BBC.BRUSH_HEIGHT_INVALID);
|
||||||
}
|
}
|
||||||
@ -101,69 +50,6 @@ public class HeightBrush implements Brush {
|
|||||||
}
|
}
|
||||||
int size = (int) sizeDouble;
|
int size = (int) sizeDouble;
|
||||||
heightMap.setSize(size);
|
heightMap.setSize(size);
|
||||||
int size2 = size * size;
|
heightMap.apply(editSession, mask, position, size, rotation, yscale, true);
|
||||||
int startY = position.getBlockY() + size;
|
|
||||||
int endY = position.getBlockY() - size;
|
|
||||||
int cx = position.getBlockX();
|
|
||||||
int cz = position.getBlockZ();
|
|
||||||
Vector mutablePos = new Vector(0, 0, 0);
|
|
||||||
for (int x = -size; x <= size; x++) {
|
|
||||||
int xx = cx + x;
|
|
||||||
mutablePos.x = xx;
|
|
||||||
for (int z = -size; z <= size; z++) {
|
|
||||||
int zz = cz + z;
|
|
||||||
int raise;
|
|
||||||
switch (rotation) {
|
|
||||||
default:
|
|
||||||
raise = heightMap.getHeight(x, z);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
raise = heightMap.getHeight(z, x);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
raise = heightMap.getHeight(-x, -z);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
raise = heightMap.getHeight(-z, -x);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
raise = (int) (yscale * raise);
|
|
||||||
if (raise == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
mutablePos.z = zz;
|
|
||||||
int foundHeight = Integer.MAX_VALUE;
|
|
||||||
BaseBlock block = null;
|
|
||||||
for (int y = startY; y >= endY; y--) {
|
|
||||||
block = editSession.getLazyBlock(xx, y, zz);
|
|
||||||
if (block != EditSession.nullBlock) {
|
|
||||||
if (mask != null) {
|
|
||||||
mutablePos.y = y;
|
|
||||||
if (!mask.test(mutablePos)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foundHeight = y;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (foundHeight == Integer.MAX_VALUE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (raise > 0) {
|
|
||||||
for (int y = foundHeight + 1; y <= foundHeight + raise; y++) {
|
|
||||||
mutablePos.y = y;
|
|
||||||
editSession.setBlock(mutablePos, block);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int y = foundHeight; y > foundHeight + raise; y--) {
|
|
||||||
mutablePos.y = y;
|
|
||||||
editSession.setBlock(mutablePos, EditSession.nullBlock);
|
|
||||||
}
|
|
||||||
mutablePos.y = foundHeight + raise;
|
|
||||||
editSession.setBlock(mutablePos, block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.boydti.fawe.object.brush.heightmap;
|
package com.boydti.fawe.object.brush.heightmap;
|
||||||
|
|
||||||
public class ArrayHeightMap extends HeightMap {
|
public class ArrayHeightMap extends ScalableHeightMap {
|
||||||
// The heights
|
// The heights
|
||||||
private final byte[][] height;
|
private final byte[][] height;
|
||||||
// The height map width/length
|
// The height map width/length
|
||||||
@ -19,15 +19,15 @@ public class ArrayHeightMap extends HeightMap {
|
|||||||
public void setSize(int size) {
|
public void setSize(int size) {
|
||||||
super.setSize(size);
|
super.setSize(size);
|
||||||
this.rx = (double) width / (size << 1);
|
this.rx = (double) width / (size << 1);
|
||||||
this.rz = (double) width / (size << 1);
|
this.rz = (double) length / (size << 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getHeight(int x, int z) {
|
public double getHeight(int x, int z) {
|
||||||
x = (int) Math.max(0, Math.min(width - 1, (x + size) * rx));
|
x = (int) Math.max(0, Math.min(width - 1, (x + size) * rx));
|
||||||
z = (int) Math.max(0, Math.min(length - 1, (z + size) * rz));
|
z = (int) Math.max(0, Math.min(length - 1, (z + size) * rz));
|
||||||
return (((int) height[x][z] & 0xFF) * size) / 256;
|
return ((height[x][z] & 0xFF) * size) / 256d;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
package com.boydti.fawe.object.brush.heightmap;
|
|
||||||
|
|
||||||
import com.boydti.fawe.util.MathMan;
|
|
||||||
|
|
||||||
public class HeightMap {
|
|
||||||
public int size2;
|
|
||||||
public int size;
|
|
||||||
|
|
||||||
public HeightMap() {
|
|
||||||
setSize(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HeightMap(int size) {
|
|
||||||
setSize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSize(int size) {
|
|
||||||
this.size = size;
|
|
||||||
this.size2 = size * size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHeight(int x, int z) {
|
|
||||||
int dx = Math.abs(x);
|
|
||||||
int dz = Math.abs(z);
|
|
||||||
int d2 = dx * dx + dz * dz;
|
|
||||||
if (d2 > size2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return size - MathMan.sqrt(d2);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,152 @@
|
|||||||
|
package com.boydti.fawe.object.brush.heightmap;
|
||||||
|
|
||||||
|
import com.boydti.fawe.object.IntegerPair;
|
||||||
|
import com.boydti.fawe.object.PseudoRandom;
|
||||||
|
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.WorldVector;
|
||||||
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
|
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||||
|
import com.sk89q.worldedit.math.convolution.GaussianKernel;
|
||||||
|
import com.sk89q.worldedit.math.convolution.HeightMap;
|
||||||
|
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
|
||||||
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.Raster;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
public class ScalableHeightMap {
|
||||||
|
public int size2;
|
||||||
|
public int size;
|
||||||
|
|
||||||
|
public ScalableHeightMap() {
|
||||||
|
setSize(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScalableHeightMap(int size) {
|
||||||
|
setSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSize(int size) {
|
||||||
|
this.size = size;
|
||||||
|
this.size2 = size * size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeight(int x, int z) {
|
||||||
|
int dx = Math.abs(x);
|
||||||
|
int dz = Math.abs(z);
|
||||||
|
int d2 = dx * dx + dz * dz;
|
||||||
|
if (d2 > size2) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return size - MathMan.sqrtApprox(d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScalableHeightMap fromClipboard(Clipboard clipboard) {
|
||||||
|
Vector dim = clipboard.getDimensions();
|
||||||
|
byte[][] heightArray = new byte[dim.getBlockX()][dim.getBlockZ()];
|
||||||
|
int minX = clipboard.getMinimumPoint().getBlockX();
|
||||||
|
int minZ = clipboard.getMinimumPoint().getBlockZ();
|
||||||
|
int minY = clipboard.getMinimumPoint().getBlockY();
|
||||||
|
int maxY = clipboard.getMaximumPoint().getBlockY();
|
||||||
|
int clipHeight = maxY - minY + 1;
|
||||||
|
HashSet<IntegerPair> visited = new HashSet<>();
|
||||||
|
for (Vector pos : clipboard.getRegion()) {
|
||||||
|
IntegerPair pair = new IntegerPair((int) pos.x, (int) pos.z);
|
||||||
|
if (visited.contains(pair)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
visited.add(pair);
|
||||||
|
int xx = pos.getBlockX();
|
||||||
|
int zz = pos.getBlockZ();
|
||||||
|
int highestY = minY;
|
||||||
|
for (int y = minY; y <= maxY; y++) {
|
||||||
|
pos.y = y;
|
||||||
|
BaseBlock block = clipboard.getBlock(pos);
|
||||||
|
if (block != EditSession.nullBlock) {
|
||||||
|
highestY = y + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int pointHeight = Math.min(255, (256 * (highestY - minY)) / clipHeight);
|
||||||
|
int x = xx - minX;
|
||||||
|
int z = zz - minZ;
|
||||||
|
heightArray[x][z] = (byte) pointHeight;
|
||||||
|
}
|
||||||
|
return new ArrayHeightMap(heightArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScalableHeightMap fromPNG(File file) throws IOException {
|
||||||
|
BufferedImage heightFile = ImageIO.read(file);
|
||||||
|
int width = heightFile.getWidth();
|
||||||
|
int length = heightFile.getHeight();
|
||||||
|
Raster data = heightFile.getData();
|
||||||
|
byte[][] array = new byte[width][length];
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
for (int z = 0; z < length; z++) {
|
||||||
|
int pixel = heightFile.getRGB(x, z);
|
||||||
|
int red = (pixel >> 16) & 0xFF;
|
||||||
|
int green = (pixel >> 8) & 0xFF;
|
||||||
|
int blue = (pixel >> 0) & 0xFF;
|
||||||
|
int intensity = (red + green + blue) / 3;
|
||||||
|
array[x][z] = (byte) intensity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayHeightMap(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void apply(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth) throws MaxChangedBlocksException {
|
||||||
|
int diameter = 2 * size + 1;
|
||||||
|
int centerX = pos.getBlockX();
|
||||||
|
int centerZ = pos.getBlockZ();
|
||||||
|
int endY = pos.getBlockY() + size;
|
||||||
|
int startY = pos.getBlockY() - size;
|
||||||
|
int[] newData = new int[diameter * diameter];
|
||||||
|
Vector mutablePos = new Vector(0, 0, 0);
|
||||||
|
for (int x = -size; x <= size; x++) {
|
||||||
|
int xx = centerX + x;
|
||||||
|
mutablePos.x = xx;
|
||||||
|
for (int z = -size; z <= size; z++) {
|
||||||
|
int index = (z + size) * diameter + (x + size);
|
||||||
|
int zz = centerZ + z;
|
||||||
|
double raise;
|
||||||
|
switch (rotationMode) {
|
||||||
|
default:
|
||||||
|
raise = getHeight(x, z);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
raise = getHeight(z, x);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
raise = getHeight(-x, -z);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
raise = getHeight(-z, -x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
raise = (yscale * raise);
|
||||||
|
int random = PseudoRandom.random.random(256) < (int) ((raise - (int) raise) * 256) ? 1 : 0;
|
||||||
|
int height = session.getHighestTerrainBlock(xx, zz, 0, 255, true) + (int) raise + random;
|
||||||
|
newData[index] = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int iterations = 1;
|
||||||
|
WorldVector min = new WorldVector(LocalWorldAdapter.adapt(session.getWorld()), pos.subtract(size, 255, size));
|
||||||
|
Vector max = pos.add(size, 255, size);
|
||||||
|
Region region = new CuboidRegion(session.getWorld(), min, max);
|
||||||
|
HeightMap heightMap = new HeightMap(session, region, true);
|
||||||
|
if (smooth) {
|
||||||
|
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1));
|
||||||
|
newData = filter.filter(newData, diameter, diameter);
|
||||||
|
// MainUtil.smoothArray(newData, diameter, 1, 4);
|
||||||
|
}
|
||||||
|
heightMap.apply(newData);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.boydti.fawe.object.change;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
|
import com.boydti.fawe.object.extent.FastWorldEditExtent;
|
||||||
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
|
import com.sk89q.worldedit.history.UndoContext;
|
||||||
|
import com.sk89q.worldedit.history.change.Change;
|
||||||
|
|
||||||
|
public class MutableChunkChange implements Change {
|
||||||
|
|
||||||
|
public FaweChunk from;
|
||||||
|
public FaweChunk to;
|
||||||
|
|
||||||
|
public MutableChunkChange(FaweChunk from, FaweChunk to) {
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undo(UndoContext context) throws WorldEditException {
|
||||||
|
create(context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void redo(UndoContext context) throws WorldEditException {
|
||||||
|
create(context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void create(UndoContext context, boolean undo) {
|
||||||
|
Extent extent = context.getExtent();
|
||||||
|
if (extent.getClass() == FastWorldEditExtent.class) {
|
||||||
|
FastWorldEditExtent fwee = (FastWorldEditExtent) extent;
|
||||||
|
if (undo) {
|
||||||
|
fwee.getQueue().setChunk(from);
|
||||||
|
} else {
|
||||||
|
fwee.getQueue().setChunk(to);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Fawe.debug("FAWE doesn't support: " + context + " for " + getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
|
|||||||
import com.boydti.fawe.object.extent.FastWorldEditExtent;
|
import com.boydti.fawe.object.extent.FastWorldEditExtent;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.DoubleTag;
|
import com.sk89q.jnbt.DoubleTag;
|
||||||
|
import com.sk89q.jnbt.LongTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
@ -11,6 +12,7 @@ import com.sk89q.worldedit.history.UndoContext;
|
|||||||
import com.sk89q.worldedit.history.change.Change;
|
import com.sk89q.worldedit.history.change.Change;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class MutableEntityChange implements Change {
|
public class MutableEntityChange implements Change {
|
||||||
|
|
||||||
@ -26,6 +28,8 @@ public class MutableEntityChange implements Change {
|
|||||||
public void undo(UndoContext context) throws WorldEditException {
|
public void undo(UndoContext context) throws WorldEditException {
|
||||||
if (!create) {
|
if (!create) {
|
||||||
create(context);
|
create(context);
|
||||||
|
} else {
|
||||||
|
delete(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +37,36 @@ public class MutableEntityChange implements Change {
|
|||||||
public void redo(UndoContext context) throws WorldEditException {
|
public void redo(UndoContext context) throws WorldEditException {
|
||||||
if (create) {
|
if (create) {
|
||||||
create(context);
|
create(context);
|
||||||
|
} else {
|
||||||
|
delete(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(UndoContext context) {
|
||||||
|
Extent extent = context.getExtent();
|
||||||
|
if (extent.getClass() == FastWorldEditExtent.class) {
|
||||||
|
FastWorldEditExtent fwee = (FastWorldEditExtent) extent;
|
||||||
|
Map<String, Tag> map = tag.getValue();
|
||||||
|
long most;
|
||||||
|
long least;
|
||||||
|
if (map.containsKey("UUIDMost")) {
|
||||||
|
most = ((LongTag) map.get("UUIDMost")).getValue();
|
||||||
|
least = ((LongTag) map.get("UUIDLeast")).getValue();
|
||||||
|
} else if (map.containsKey("PersistentIDMSB")) {
|
||||||
|
most = ((LongTag) map.get("PersistentIDMSB")).getValue();
|
||||||
|
least = ((LongTag) map.get("PersistentIDLSB")).getValue();
|
||||||
|
} else {
|
||||||
|
Fawe.debug("Skipping entity without uuid.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<DoubleTag> pos = (List<DoubleTag>) map.get("Pos").getValue();
|
||||||
|
int x = (int) Math.round(pos.get(0).getValue());
|
||||||
|
int y = (int) Math.round(pos.get(1).getValue());
|
||||||
|
int z = (int) Math.round(pos.get(2).getValue());
|
||||||
|
UUID uuid = new UUID(most, least);
|
||||||
|
fwee.getQueue().removeEntity(x, y, z, uuid);
|
||||||
|
} else {
|
||||||
|
Fawe.debug("FAWE doesn't support: " + context + " for " + getClass() + " (bug Empire92)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
package com.boydti.fawe.object.changeset;
|
||||||
|
|
||||||
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
|
import com.boydti.fawe.object.RunnableVal2;
|
||||||
|
import com.boydti.fawe.object.change.MutableChunkChange;
|
||||||
|
import com.boydti.fawe.util.FaweQueue;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.worldedit.history.change.Change;
|
||||||
|
import com.sk89q.worldedit.world.World;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public class CPUOptimizedChangeSet extends FaweChangeSet {
|
||||||
|
|
||||||
|
public CPUOptimizedChangeSet(World world) {
|
||||||
|
super(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<Change> changes = new ArrayList<>();
|
||||||
|
|
||||||
|
public void addChangeTask(FaweQueue queue) {
|
||||||
|
queue.setChangeTask(new RunnableVal2<FaweChunk, FaweChunk>() {
|
||||||
|
@Override
|
||||||
|
public void run(final FaweChunk previous, final FaweChunk next) {
|
||||||
|
char[][] previousIds = previous.getCombinedIdArrays();
|
||||||
|
char[][] nextIds = next.getCombinedIdArrays();
|
||||||
|
for (int i = 0; i < nextIds.length; i++) {
|
||||||
|
if (nextIds[i] != null && previousIds[i] == null) {
|
||||||
|
previous.fillCuboid(0, 15, i << 4, (i << 4) + 15, 0, 15, 0, (byte) 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changes.add(new MutableChunkChange(previous, next));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
|
||||||
|
throw new UnsupportedOperationException("Invalid mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTileCreate(CompoundTag tag) {
|
||||||
|
throw new UnsupportedOperationException("Invalid mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTileRemove(CompoundTag tag) {
|
||||||
|
throw new UnsupportedOperationException("Invalid mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addEntityRemove(CompoundTag tag) {
|
||||||
|
throw new UnsupportedOperationException("Invalid mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addEntityCreate(CompoundTag tag) {
|
||||||
|
throw new UnsupportedOperationException("Invalid mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Change> getIterator(boolean redo) {
|
||||||
|
return changes.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return changes.size() * 65536; // num chunks * 65536 (guess of 65536 changes per chunk)
|
||||||
|
}
|
||||||
|
}
|
@ -16,8 +16,6 @@ import java.io.OutputStream;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.zip.GZIPOutputStream;
|
|
||||||
import net.jpountz.lz4.LZ4Compressor;
|
import net.jpountz.lz4.LZ4Compressor;
|
||||||
import net.jpountz.lz4.LZ4Factory;
|
import net.jpountz.lz4.LZ4Factory;
|
||||||
import net.jpountz.lz4.LZ4InputStream;
|
import net.jpountz.lz4.LZ4InputStream;
|
||||||
@ -56,20 +54,15 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
|
|
||||||
// NBT From
|
// NBT From
|
||||||
private NBTOutputStream osNBTF;
|
private NBTOutputStream osNBTF;
|
||||||
private GZIPOutputStream osNBTFG;
|
|
||||||
private AtomicInteger osNBTFI;
|
|
||||||
|
|
||||||
// NBT To
|
// NBT To
|
||||||
private NBTOutputStream osNBTT;
|
private NBTOutputStream osNBTT;
|
||||||
private GZIPOutputStream osNBTTG;
|
|
||||||
|
|
||||||
// Entity Create From
|
// Entity Create From
|
||||||
private NBTOutputStream osENTCF;
|
private NBTOutputStream osENTCF;
|
||||||
private GZIPOutputStream osENTCFG;
|
|
||||||
|
|
||||||
// Entity Create To
|
// Entity Create To
|
||||||
private NBTOutputStream osENTCT;
|
private NBTOutputStream osENTCT;
|
||||||
private GZIPOutputStream osENTCTG;
|
|
||||||
|
|
||||||
private World world;
|
private World world;
|
||||||
|
|
||||||
@ -82,6 +75,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DiskStorageHistory(World world, UUID uuid) {
|
public DiskStorageHistory(World world, UUID uuid) {
|
||||||
|
super(world);
|
||||||
String base = "history" + File.separator + world.getName() + File.separator + uuid;
|
String base = "history" + File.separator + world.getName() + File.separator + uuid;
|
||||||
File folder = new File(Fawe.imp().getDirectory(), base);
|
File folder = new File(Fawe.imp().getDirectory(), base);
|
||||||
int max = 0;
|
int max = 0;
|
||||||
@ -100,6 +94,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DiskStorageHistory(World world, UUID uuid, int index) {
|
public DiskStorageHistory(World world, UUID uuid, int index) {
|
||||||
|
super(world);
|
||||||
init(world, uuid, index);
|
init(world, uuid, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,27 +120,28 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean flush() {
|
public boolean flush() {
|
||||||
boolean flushed = false;
|
super.flush();
|
||||||
|
boolean flushed = osBD != null || osNBTF != null || osNBTT != null && osENTCF != null || osENTCT != null;
|
||||||
try {
|
try {
|
||||||
if (osBD != null) {
|
if (osBD != null) {
|
||||||
flushed = true;
|
|
||||||
osBD.flush();
|
|
||||||
osBD.close();
|
osBD.close();
|
||||||
osBD = null;
|
osBD = null;
|
||||||
}
|
}
|
||||||
if (osNBTF != null) {
|
if (osNBTF != null) {
|
||||||
flushed = true;
|
|
||||||
osNBTFG.flush();
|
|
||||||
osNBTF.close();
|
osNBTF.close();
|
||||||
osNBTF = null;
|
osNBTF = null;
|
||||||
osNBTFG = null;
|
|
||||||
}
|
}
|
||||||
if (osNBTT != null) {
|
if (osNBTT != null) {
|
||||||
flushed = true;
|
|
||||||
osNBTTG.flush();
|
|
||||||
osNBTT.close();
|
osNBTT.close();
|
||||||
osNBTT = null;
|
osNBTT = null;
|
||||||
osNBTTG = null;
|
}
|
||||||
|
if (osENTCF != null) {
|
||||||
|
osENTCF.close();
|
||||||
|
osENTCF = null;
|
||||||
|
}
|
||||||
|
if (osENTCT != null) {
|
||||||
|
osENTCT.close();
|
||||||
|
osENTCT = null;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -185,8 +181,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
}
|
}
|
||||||
enttFile.getParentFile().mkdirs();
|
enttFile.getParentFile().mkdirs();
|
||||||
enttFile.createNewFile();
|
enttFile.createNewFile();
|
||||||
osENTCTG = new GZIPOutputStream(new FileOutputStream(enttFile), true);
|
osENTCT = new NBTOutputStream(getCompressedOS(new FileOutputStream(enttFile)));
|
||||||
osENTCT = new NBTOutputStream(osENTCTG);
|
|
||||||
return osENTCT;
|
return osENTCT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,8 +192,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
}
|
}
|
||||||
entfFile.getParentFile().mkdirs();
|
entfFile.getParentFile().mkdirs();
|
||||||
entfFile.createNewFile();
|
entfFile.createNewFile();
|
||||||
osENTCFG = new GZIPOutputStream(new FileOutputStream(entfFile), true);
|
osENTCF = new NBTOutputStream(getCompressedOS(new FileOutputStream(entfFile)));
|
||||||
osENTCF = new NBTOutputStream(osENTCFG);
|
|
||||||
return osENTCF;
|
return osENTCF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,8 +203,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
}
|
}
|
||||||
nbttFile.getParentFile().mkdirs();
|
nbttFile.getParentFile().mkdirs();
|
||||||
nbttFile.createNewFile();
|
nbttFile.createNewFile();
|
||||||
osNBTTG = new GZIPOutputStream(new FileOutputStream(nbttFile), true);
|
osNBTT = new NBTOutputStream(getCompressedOS(new FileOutputStream(nbttFile)));
|
||||||
osNBTT = new NBTOutputStream(osNBTTG);
|
|
||||||
return osNBTT;
|
return osNBTT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,9 +214,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
}
|
}
|
||||||
nbtfFile.getParentFile().mkdirs();
|
nbtfFile.getParentFile().mkdirs();
|
||||||
nbtfFile.createNewFile();
|
nbtfFile.createNewFile();
|
||||||
osNBTFG = new GZIPOutputStream(new FileOutputStream(nbtfFile), true);
|
osNBTF = new NBTOutputStream(getCompressedOS(new FileOutputStream(nbtfFile)));
|
||||||
osNBTF = new NBTOutputStream(osNBTFG);
|
|
||||||
osNBTFI = new AtomicInteger();
|
|
||||||
return osNBTF;
|
return osNBTF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import com.boydti.fawe.object.FaweChunk;
|
|||||||
import com.boydti.fawe.object.RunnableVal2;
|
import com.boydti.fawe.object.RunnableVal2;
|
||||||
import com.boydti.fawe.util.FaweQueue;
|
import com.boydti.fawe.util.FaweQueue;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.BlockVector;
|
import com.sk89q.worldedit.BlockVector;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
@ -20,12 +21,36 @@ import com.sk89q.worldedit.history.change.Change;
|
|||||||
import com.sk89q.worldedit.history.change.EntityCreate;
|
import com.sk89q.worldedit.history.change.EntityCreate;
|
||||||
import com.sk89q.worldedit.history.change.EntityRemove;
|
import com.sk89q.worldedit.history.change.EntityRemove;
|
||||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||||
|
import com.sk89q.worldedit.world.World;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public abstract class FaweChangeSet implements ChangeSet {
|
public abstract class FaweChangeSet implements ChangeSet {
|
||||||
public abstract boolean flush();
|
|
||||||
|
private final World world;
|
||||||
|
|
||||||
|
public FaweChangeSet(World world) {
|
||||||
|
this.world = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public World getWorld() {
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean flush() {
|
||||||
|
try {
|
||||||
|
while (waiting.get() > 0) {
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.wait(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void add(int x, int y, int z, int combinedFrom, int combinedTo);
|
public abstract void add(int x, int y, int z, int combinedFrom, int combinedTo);
|
||||||
|
|
||||||
@ -47,7 +72,7 @@ public abstract class FaweChangeSet implements ChangeSet {
|
|||||||
|
|
||||||
public EditSession toEditSession(Player player) {
|
public EditSession toEditSession(Player player) {
|
||||||
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
|
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
|
||||||
EditSession edit = factory.getEditSession(player.getWorld(), -1, null, player);
|
EditSession edit = factory.getEditSession(world, -1, null, player);
|
||||||
edit.setChangeSet(this);
|
edit.setChangeSet(this);
|
||||||
edit.dequeue();
|
edit.dequeue();
|
||||||
return edit;
|
return edit;
|
||||||
@ -131,31 +156,32 @@ public abstract class FaweChangeSet implements ChangeSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AtomicInteger waiting = new AtomicInteger(0);
|
||||||
|
private Object lock = new Object();
|
||||||
|
|
||||||
public void addChangeTask(FaweQueue queue) {
|
public void addChangeTask(FaweQueue queue) {
|
||||||
queue.setChangeTask(new RunnableVal2<FaweChunk, FaweChunk>() {
|
queue.setChangeTask(new RunnableVal2<FaweChunk, FaweChunk>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(final FaweChunk previous, FaweChunk next) {
|
public void run(final FaweChunk previous, final FaweChunk next) {
|
||||||
/**
|
waiting.incrementAndGet();
|
||||||
* TODO cache NBT
|
TaskManager.IMP.async(new Runnable() {
|
||||||
* - Counter variable for nbt changes
|
@Override
|
||||||
* - Record biome changes
|
public void run() {
|
||||||
*/
|
try {
|
||||||
int cx = previous.getX();
|
int cx = previous.getX();
|
||||||
int cz = previous.getZ();
|
int cz = previous.getZ();
|
||||||
int bx = cx << 4;
|
int bx = cx << 4;
|
||||||
int bz = cz << 4;
|
int bz = cz << 4;
|
||||||
|
|
||||||
// Biome changes
|
// Biome changes
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block changes
|
// Block changes
|
||||||
{
|
{
|
||||||
// Current blocks
|
// Current blocks
|
||||||
char[][] currentIds = next.getIdArrays();
|
char[][] currentIds = next.getCombinedIdArrays();
|
||||||
// Previous blocks in modified sections (i.e. we skip sections that weren't modified)
|
// Previous blocks in modified sections (i.e. we skip sections that weren't modified)
|
||||||
char[][] previousIds = previous.getIdArrays();
|
char[][] previousIds = previous.getCombinedIdArrays();
|
||||||
for (int layer = 0; layer < currentIds.length; layer++) {
|
for (int layer = 0; layer < currentIds.length; layer++) {
|
||||||
char[] currentLayer = currentIds[layer];
|
char[] currentLayer = currentIds[layer];
|
||||||
char[] previousLayer = previousIds[layer];
|
char[] previousLayer = previousIds[layer];
|
||||||
@ -181,6 +207,7 @@ public abstract class FaweChangeSet implements ChangeSet {
|
|||||||
default:
|
default:
|
||||||
char combinedIdPrevious = previousLayer != null ? previousLayer[index] : 0;
|
char combinedIdPrevious = previousLayer != null ? previousLayer[index] : 0;
|
||||||
if (combinedIdCurrent != combinedIdPrevious) {
|
if (combinedIdCurrent != combinedIdPrevious) {
|
||||||
|
synchronized (lock) {
|
||||||
add(xx, yy, zz, combinedIdPrevious, combinedIdCurrent);
|
add(xx, yy, zz, combinedIdPrevious, combinedIdCurrent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,34 +216,52 @@ public abstract class FaweChangeSet implements ChangeSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Tile changes
|
// Tile changes
|
||||||
{
|
{
|
||||||
// Tiles created
|
// Tiles created
|
||||||
Map<BytePair, CompoundTag> tiles = next.getTiles();
|
Map<BytePair, CompoundTag> tiles = next.getTiles();
|
||||||
for (Map.Entry<BytePair, CompoundTag> entry : tiles.entrySet()) {
|
for (Map.Entry<BytePair, CompoundTag> entry : tiles.entrySet()) {
|
||||||
|
synchronized (lock) {
|
||||||
addTileCreate(entry.getValue());
|
addTileCreate(entry.getValue());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Tiles removed
|
// Tiles removed
|
||||||
tiles = previous.getTiles();
|
tiles = previous.getTiles();
|
||||||
for (Map.Entry<BytePair, CompoundTag> entry : tiles.entrySet()) {
|
for (Map.Entry<BytePair, CompoundTag> entry : tiles.entrySet()) {
|
||||||
|
synchronized (lock) {
|
||||||
addTileRemove(entry.getValue());
|
addTileRemove(entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Entity changes
|
// Entity changes
|
||||||
{
|
{
|
||||||
// Entities created
|
// Entities created
|
||||||
Set<CompoundTag> entities = next.getEntities();
|
Set<CompoundTag> entities = next.getEntities();
|
||||||
for (CompoundTag entityTag : entities) {
|
for (CompoundTag entityTag : entities) {
|
||||||
|
synchronized (lock) {
|
||||||
addEntityCreate(entityTag);
|
addEntityCreate(entityTag);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Entities removed
|
// Entities removed
|
||||||
entities = previous.getEntities();
|
entities = previous.getEntities();
|
||||||
for (CompoundTag entityTag : entities) {
|
for (CompoundTag entityTag : entities) {
|
||||||
|
synchronized (lock) {
|
||||||
addEntityRemove(entityTag);
|
addEntityRemove(entityTag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
waiting.decrementAndGet();
|
||||||
|
synchronized (lock) {
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,11 @@ import com.boydti.fawe.config.Settings;
|
|||||||
import com.boydti.fawe.object.change.MutableBlockChange;
|
import com.boydti.fawe.object.change.MutableBlockChange;
|
||||||
import com.boydti.fawe.object.change.MutableEntityChange;
|
import com.boydti.fawe.object.change.MutableEntityChange;
|
||||||
import com.boydti.fawe.object.change.MutableTileChange;
|
import com.boydti.fawe.object.change.MutableTileChange;
|
||||||
import com.google.common.collect.Iterators;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
import com.sk89q.jnbt.NBTOutputStream;
|
import com.sk89q.jnbt.NBTOutputStream;
|
||||||
import com.sk89q.worldedit.history.change.Change;
|
import com.sk89q.worldedit.history.change.Change;
|
||||||
|
import com.sk89q.worldedit.world.World;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -21,9 +21,12 @@ import net.jpountz.lz4.LZ4OutputStream;
|
|||||||
|
|
||||||
public abstract class FaweStreamChangeSet extends FaweChangeSet {
|
public abstract class FaweStreamChangeSet extends FaweChangeSet {
|
||||||
|
|
||||||
|
public FaweStreamChangeSet(World world) {
|
||||||
|
super(world);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
System.out.println("SIZE: " + blockSize);
|
|
||||||
// Flush so we can accurately get the size
|
// Flush so we can accurately get the size
|
||||||
flush();
|
flush();
|
||||||
return blockSize;
|
return blockSize;
|
||||||
@ -172,7 +175,6 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
|
|||||||
if (read0 == -1) {
|
if (read0 == -1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
System.out.println("r0: " + read0);
|
|
||||||
int x = ((byte) read0 & 0xFF) + ((byte) is.read() << 8) + originX;
|
int x = ((byte) read0 & 0xFF) + ((byte) is.read() << 8) + originX;
|
||||||
int z = ((byte) is.read() & 0xFF) + ((byte) is.read() << 8) + originZ;
|
int z = ((byte) is.read() & 0xFF) + ((byte) is.read() << 8) + originZ;
|
||||||
int y = is.read() & 0xff;
|
int y = is.read() & 0xff;
|
||||||
@ -192,7 +194,6 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
|
|||||||
change.id = (short) ((from2 << 4) + (from1 >> 4));
|
change.id = (short) ((from2 << 4) + (from1 >> 4));
|
||||||
change.data = (byte) (from1 & 0xf);
|
change.data = (byte) (from1 & 0xf);
|
||||||
}
|
}
|
||||||
System.out.println("CHANGE: " + change.id);
|
|
||||||
return change;
|
return change;
|
||||||
} catch (Exception ignoreEOF) {
|
} catch (Exception ignoreEOF) {
|
||||||
ignoreEOF.printStackTrace();
|
ignoreEOF.printStackTrace();
|
||||||
@ -206,10 +207,8 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
|
|||||||
last = read();
|
last = read();
|
||||||
}
|
}
|
||||||
if (last != null) {
|
if (last != null) {
|
||||||
System.out.println("HAS NEXT!");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
System.out.println("NO NEXT");
|
|
||||||
try {
|
try {
|
||||||
is.close();
|
is.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -333,18 +332,43 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<Change> getIterator(final boolean dir) {
|
public Iterator<Change> getIterator(final boolean dir) {
|
||||||
System.out.println("GET ITERATOR: " + dir);
|
|
||||||
flush();
|
flush();
|
||||||
try {
|
try {
|
||||||
Iterator<MutableTileChange> tileCreate = getTileIterator(getTileCreateIS(), true, dir);
|
final Iterator<MutableTileChange> tileCreate = getTileIterator(getTileCreateIS(), true, dir);
|
||||||
Iterator<MutableTileChange> tileRemove = getTileIterator(getTileRemoveIS(), false, dir);
|
final Iterator<MutableTileChange> tileRemove = getTileIterator(getTileRemoveIS(), false, dir);
|
||||||
|
|
||||||
Iterator<MutableEntityChange> entityCreate = getEntityIterator(getEntityCreateIS(), true, dir);
|
final Iterator<MutableEntityChange> entityCreate = getEntityIterator(getEntityCreateIS(), true, dir);
|
||||||
Iterator<MutableEntityChange> entityRemove = getEntityIterator(getEntityRemoveIS(), false, dir);
|
final Iterator<MutableEntityChange> entityRemove = getEntityIterator(getEntityRemoveIS(), false, dir);
|
||||||
|
|
||||||
Iterator<MutableBlockChange> blockChange = getBlockIterator(dir);
|
final Iterator<MutableBlockChange> blockChange = getBlockIterator(dir);
|
||||||
|
|
||||||
return Iterators.concat(tileCreate, tileRemove, entityCreate, entityRemove, blockChange);
|
return new Iterator<Change>() {
|
||||||
|
Iterator<Change>[] iterators = new Iterator[]{tileCreate, tileRemove, entityCreate, entityRemove, blockChange};
|
||||||
|
int i = 0;
|
||||||
|
Iterator<Change> current = iterators[0];
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
if (current.hasNext()) {
|
||||||
|
return true;
|
||||||
|
} else if (i >= iterators.length - 1) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
current = iterators[++i];
|
||||||
|
}
|
||||||
|
return hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
current.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Change next() {
|
||||||
|
return current.next();
|
||||||
|
}
|
||||||
|
};
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
package com.boydti.fawe.object.changeset;
|
package com.boydti.fawe.object.changeset;
|
||||||
|
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
import com.sk89q.jnbt.NBTOutputStream;
|
import com.sk89q.jnbt.NBTOutputStream;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.world.World;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import net.jpountz.lz4.LZ4Factory;
|
|
||||||
import net.jpountz.lz4.LZ4InputStream;
|
|
||||||
import net.jpountz.lz4.LZ4OutputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ChangeSet optimized for low memory usage
|
* ChangeSet optimized for low memory usage
|
||||||
@ -21,26 +18,67 @@ import net.jpountz.lz4.LZ4OutputStream;
|
|||||||
*/
|
*/
|
||||||
public class MemoryOptimizedHistory extends FaweStreamChangeSet {
|
public class MemoryOptimizedHistory extends FaweStreamChangeSet {
|
||||||
|
|
||||||
private final Actor actor;
|
private byte[] ids;
|
||||||
|
private ByteArrayOutputStream idsStream;
|
||||||
|
private OutputStream idsStreamZip;
|
||||||
|
|
||||||
public MemoryOptimizedHistory(Actor actor) {
|
private byte[] entC;
|
||||||
this.actor = actor;
|
private ByteArrayOutputStream entCStream;
|
||||||
|
private NBTOutputStream entCStreamZip;
|
||||||
|
|
||||||
|
private byte[] entR;
|
||||||
|
private ByteArrayOutputStream entRStream;
|
||||||
|
private NBTOutputStream entRStreamZip;
|
||||||
|
|
||||||
|
private byte[] tileC;
|
||||||
|
private ByteArrayOutputStream tileCStream;
|
||||||
|
private NBTOutputStream tileCStreamZip;
|
||||||
|
|
||||||
|
private byte[] tileR;
|
||||||
|
private ByteArrayOutputStream tileRStream;
|
||||||
|
private NBTOutputStream tileRStreamZip;
|
||||||
|
|
||||||
|
public MemoryOptimizedHistory(World world) {
|
||||||
|
super(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean flush() {
|
public boolean flush() {
|
||||||
if (idsStreamZip != null) {
|
super.flush();
|
||||||
try {
|
try {
|
||||||
idsStream.flush();
|
if (idsStream != null) {
|
||||||
idsStreamZip.flush();
|
|
||||||
idsStreamZip.close();
|
idsStreamZip.close();
|
||||||
ids = idsStream.toByteArray(true);
|
ids = idsStream.toByteArray();
|
||||||
idsStream = null;
|
idsStream = null;
|
||||||
idsStreamZip = null;
|
idsStreamZip = null;
|
||||||
} catch (IOException e) {
|
}
|
||||||
e.printStackTrace();
|
if (entCStream != null) {
|
||||||
|
entCStreamZip.close();
|
||||||
|
entC = entCStream.toByteArray();
|
||||||
|
entCStream = null;
|
||||||
|
entCStreamZip = null;
|
||||||
|
}
|
||||||
|
if (entRStream != null) {
|
||||||
|
entRStreamZip.close();
|
||||||
|
entR = entRStream.toByteArray();
|
||||||
|
entRStream = null;
|
||||||
|
entRStreamZip = null;
|
||||||
|
}
|
||||||
|
if (tileCStream != null) {
|
||||||
|
tileCStreamZip.close();
|
||||||
|
tileC = tileCStream.toByteArray();
|
||||||
|
tileCStream = null;
|
||||||
|
tileCStreamZip = null;
|
||||||
|
}
|
||||||
|
if (tileRStream != null) {
|
||||||
|
tileRStreamZip.close();
|
||||||
|
tileR = tileRStream.toByteArray();
|
||||||
|
tileRStream = null;
|
||||||
|
tileRStreamZip = null;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -50,75 +88,74 @@ public class MemoryOptimizedHistory extends FaweStreamChangeSet {
|
|||||||
return ids == null ? 0 : ids.length;
|
return ids == null ? 0 : ids.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] ids;
|
|
||||||
private FastByteArrayOutputStream idsStream;
|
|
||||||
private OutputStream idsStreamZip;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OutputStream getBlockOS(int x, int y, int z) throws IOException {
|
public OutputStream getBlockOS(int x, int y, int z) throws IOException {
|
||||||
if (idsStreamZip != null) {
|
if (idsStreamZip != null) {
|
||||||
return idsStreamZip;
|
return idsStreamZip;
|
||||||
}
|
}
|
||||||
LZ4Factory factory = LZ4Factory.fastestInstance();
|
|
||||||
idsStream = new FastByteArrayOutputStream(Settings.BUFFER_SIZE);
|
|
||||||
idsStreamZip = new LZ4OutputStream(idsStream, Settings.BUFFER_SIZE, factory.fastCompressor());
|
|
||||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
|
||||||
idsStreamZip = new LZ4OutputStream(idsStreamZip, Settings.BUFFER_SIZE, factory.highCompressor());
|
|
||||||
}
|
|
||||||
setOrigin(x, z);
|
setOrigin(x, z);
|
||||||
return idsStreamZip;
|
idsStream = new ByteArrayOutputStream(Settings.BUFFER_SIZE);
|
||||||
}
|
return idsStreamZip = getCompressedOS(idsStream);
|
||||||
|
|
||||||
@Override
|
|
||||||
public NBTOutputStream getEntityCreateOS() throws IOException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NBTOutputStream getEntityRemoveOS() throws IOException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NBTOutputStream getTileCreateOS() throws IOException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NBTOutputStream getTileRemoveOS() throws IOException {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream getBlockIS() {
|
public InputStream getBlockIS() {
|
||||||
if (ids == null) {
|
return ids == null ? null : getCompressedIS(new ByteArrayInputStream(ids));
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
InputStream is = new ByteArrayInputStream(ids);
|
|
||||||
is = new LZ4InputStream(is);
|
@Override
|
||||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
public NBTOutputStream getEntityCreateOS() throws IOException {
|
||||||
is = new LZ4InputStream(is);
|
if (entCStreamZip != null) {
|
||||||
|
return entCStreamZip;
|
||||||
}
|
}
|
||||||
return is;
|
entCStream = new ByteArrayOutputStream(Settings.BUFFER_SIZE);
|
||||||
|
return entCStreamZip = new NBTOutputStream(getCompressedOS(entCStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NBTOutputStream getEntityRemoveOS() throws IOException {
|
||||||
|
if (entRStreamZip != null) {
|
||||||
|
return entRStreamZip;
|
||||||
|
}
|
||||||
|
entRStream = new ByteArrayOutputStream(Settings.BUFFER_SIZE);
|
||||||
|
return entRStreamZip = new NBTOutputStream(getCompressedOS(entRStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NBTOutputStream getTileCreateOS() throws IOException {
|
||||||
|
if (tileCStreamZip != null) {
|
||||||
|
return tileCStreamZip;
|
||||||
|
}
|
||||||
|
tileCStream = new ByteArrayOutputStream(Settings.BUFFER_SIZE);
|
||||||
|
return tileCStreamZip = new NBTOutputStream(getCompressedOS(tileCStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NBTOutputStream getTileRemoveOS() throws IOException {
|
||||||
|
if (tileRStreamZip != null) {
|
||||||
|
return tileRStreamZip;
|
||||||
|
}
|
||||||
|
tileRStream = new ByteArrayOutputStream(Settings.BUFFER_SIZE);
|
||||||
|
return tileRStreamZip = new NBTOutputStream(getCompressedOS(tileRStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NBTInputStream getEntityCreateIS() throws IOException {
|
public NBTInputStream getEntityCreateIS() throws IOException {
|
||||||
return null;
|
return entC == null ? null : new NBTInputStream(getCompressedIS(new ByteArrayInputStream(entC)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NBTInputStream getEntityRemoveIS() throws IOException {
|
public NBTInputStream getEntityRemoveIS() throws IOException {
|
||||||
return null;
|
return entR == null ? null : new NBTInputStream(getCompressedIS(new ByteArrayInputStream(entR)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NBTInputStream getTileCreateIS() throws IOException {
|
public NBTInputStream getTileCreateIS() throws IOException {
|
||||||
return null;
|
return tileC == null ? null : new NBTInputStream(getCompressedIS(new ByteArrayInputStream(tileC)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NBTInputStream getTileRemoveIS() throws IOException {
|
public NBTInputStream getTileRemoveIS() throws IOException {
|
||||||
return null;
|
return tileR == null ? null : new NBTInputStream(getCompressedIS(new ByteArrayInputStream(tileR)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,6 +154,7 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
|
|||||||
case 178: {
|
case 178: {
|
||||||
if (block.hasNbtData()) {
|
if (block.hasNbtData()) {
|
||||||
CompoundTag nbt = block.getNbtData();
|
CompoundTag nbt = block.getNbtData();
|
||||||
|
MainUtil.setPosition(nbt, x, y, z);
|
||||||
queue.setTile(x, y, z, nbt);
|
queue.setTile(x, y, z, nbt);
|
||||||
}
|
}
|
||||||
queue.setBlock(x, y, z, id, (byte) block.getData());
|
queue.setBlock(x, y, z, id, (byte) block.getData());
|
||||||
|
@ -75,12 +75,12 @@ public class ProcessedWEExtent extends FaweRegionExtent {
|
|||||||
}
|
}
|
||||||
if (WEManager.IMP.maskContains(this.mask, (int) location.x, (int) location.z)) {
|
if (WEManager.IMP.maskContains(this.mask, (int) location.x, (int) location.z)) {
|
||||||
if (limit.MAX_CHANGES-- < 0) {
|
if (limit.MAX_CHANGES-- < 0) {
|
||||||
WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES);
|
WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return super.setBlock(location, block);
|
return super.setBlock(location, block);
|
||||||
} else if (limit.MAX_FAILS-- < 0) {
|
} else if (limit.MAX_FAILS-- < 0) {
|
||||||
WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES);
|
WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
package com.boydti.fawe.object.progress;
|
||||||
|
|
||||||
|
import com.boydti.fawe.config.BBC;
|
||||||
|
import com.boydti.fawe.config.Settings;
|
||||||
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
|
import com.boydti.fawe.object.RunnableVal2;
|
||||||
|
import com.boydti.fawe.util.FaweQueue;
|
||||||
|
import com.boydti.fawe.util.StringMan;
|
||||||
|
import com.boydti.fawe.util.TaskManager;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
public class DefaultProgressTracker extends RunnableVal2<FaweQueue.ProgressType, Integer> {
|
||||||
|
|
||||||
|
private final FawePlayer player;
|
||||||
|
private final long start;
|
||||||
|
|
||||||
|
public DefaultProgressTracker(FawePlayer player) {
|
||||||
|
this.start = System.currentTimeMillis();
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int amountQueue = 0;
|
||||||
|
private int amountDispatch = 0;
|
||||||
|
private long lastTick = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(FaweQueue.ProgressType type, Integer amount) {
|
||||||
|
switch (type) {
|
||||||
|
case DISPATCH:
|
||||||
|
amountDispatch = amount;
|
||||||
|
break;
|
||||||
|
case QUEUE:
|
||||||
|
amountQueue = amount;
|
||||||
|
break;
|
||||||
|
case DONE:
|
||||||
|
if (amountDispatch > 64) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (amountQueue > 64 || amountDispatch > 64) {
|
||||||
|
send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void done() {
|
||||||
|
TaskManager.IMP.task(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
final long time = System.currentTimeMillis() - start;
|
||||||
|
player.sendTitle("", BBC.PROGRESS_DONE.format(time / 1000d));
|
||||||
|
TaskManager.IMP.later(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
player.resetTitle();
|
||||||
|
}
|
||||||
|
}, 60);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send() {
|
||||||
|
TaskManager.IMP.task(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
long currentTick = Bukkit.getServer().getWorlds().get(0).getFullTime();
|
||||||
|
if (currentTick > lastTick + Settings.DISPLAY_PROGRESS_INTERVAL) {
|
||||||
|
lastTick = currentTick;
|
||||||
|
String queue = StringMan.padRight("" + amountQueue, 3);
|
||||||
|
String dispatch = StringMan.padRight("" + amountDispatch, 3);
|
||||||
|
player.sendTitle("", BBC.PROGRESS_MESSAGE.format(queue, dispatch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -10,14 +10,28 @@ import com.sk89q.worldedit.EditSession;
|
|||||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
|
|
||||||
public abstract class FaweQueue {
|
public abstract class FaweQueue {
|
||||||
|
|
||||||
|
public static enum ProgressType {
|
||||||
|
QUEUE,
|
||||||
|
DISPATCH,
|
||||||
|
DONE,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum RelightMode {
|
||||||
|
MINIMAL,
|
||||||
|
OPTIMAL,
|
||||||
|
ALL,
|
||||||
|
}
|
||||||
|
|
||||||
public final String world;
|
public final String world;
|
||||||
public LinkedBlockingDeque<EditSession> sessions;
|
public LinkedBlockingDeque<EditSession> sessions;
|
||||||
public long modified = System.currentTimeMillis();
|
public long modified = System.currentTimeMillis();
|
||||||
public RunnableVal2<FaweChunk, FaweChunk> changeTask;
|
public RunnableVal2<FaweChunk, FaweChunk> changeTask;
|
||||||
|
public RunnableVal2<ProgressType, Integer> progressTask;
|
||||||
|
|
||||||
public FaweQueue(String world) {
|
public FaweQueue(String world) {
|
||||||
this.world = world;
|
this.world = world;
|
||||||
@ -33,6 +47,16 @@ public abstract class FaweQueue {
|
|||||||
sessions.add(session);
|
sessions.add(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a progress task<br>
|
||||||
|
* - Progress type
|
||||||
|
* - Amount of type
|
||||||
|
* @param progressTask
|
||||||
|
*/
|
||||||
|
public void setProgressTracker(RunnableVal2<ProgressType, Integer> progressTask) {
|
||||||
|
this.progressTask = progressTask;
|
||||||
|
}
|
||||||
|
|
||||||
public Set<EditSession> getEditSessions() {
|
public Set<EditSession> getEditSessions() {
|
||||||
return sessions == null ? new HashSet<EditSession>() : new HashSet<>(sessions);
|
return sessions == null ? new HashSet<EditSession>() : new HashSet<>(sessions);
|
||||||
}
|
}
|
||||||
@ -53,13 +77,15 @@ public abstract class FaweQueue {
|
|||||||
|
|
||||||
public abstract void setEntity(int x, int y, int z, CompoundTag tag);
|
public abstract void setEntity(int x, int y, int z, CompoundTag tag);
|
||||||
|
|
||||||
|
public abstract void removeEntity(int x, int y, int z, UUID uuid);
|
||||||
|
|
||||||
public abstract boolean setBiome(final int x, final int z, final BaseBiome biome);
|
public abstract boolean setBiome(final int x, final int z, final BaseBiome biome);
|
||||||
|
|
||||||
public abstract FaweChunk<?> getChunk(int x, int z);
|
public abstract FaweChunk<?> getChunk(int x, int z);
|
||||||
|
|
||||||
public abstract void setChunk(final FaweChunk<?> chunk);
|
public abstract void setChunk(final FaweChunk<?> chunk);
|
||||||
|
|
||||||
public abstract boolean fixLighting(final FaweChunk<?> chunk, final boolean fixAll);
|
public abstract boolean fixLighting(final FaweChunk<?> chunk, RelightMode mode);
|
||||||
|
|
||||||
public abstract boolean isChunkLoaded(final int x, final int z);
|
public abstract boolean isChunkLoaded(final int x, final int z);
|
||||||
|
|
||||||
|
@ -70,6 +70,9 @@ public class MainUtil {
|
|||||||
try {
|
try {
|
||||||
int elements = set.size();
|
int elements = set.size();
|
||||||
int compressedSize = set.getCompressedSize();
|
int compressedSize = set.getCompressedSize();
|
||||||
|
if (compressedSize == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* BlockVector
|
* BlockVector
|
||||||
* - reference to the object --> 8 bytes
|
* - reference to the object --> 8 bytes
|
||||||
@ -90,10 +93,9 @@ public class MainUtil {
|
|||||||
* This compares FAWE's usage to standard WE.
|
* This compares FAWE's usage to standard WE.
|
||||||
*/
|
*/
|
||||||
int total = 128 * elements;
|
int total = 128 * elements;
|
||||||
int current = compressedSize;
|
|
||||||
|
|
||||||
int ratio = total / current;
|
int ratio = total / compressedSize;
|
||||||
int saved = total - current;
|
int saved = total - compressedSize;
|
||||||
|
|
||||||
if (ratio > 3 && Thread.currentThread() != Fawe.get().getMainThread() && actor != null && actor.isPlayer() && actor.getSessionKey().isActive()) {
|
if (ratio > 3 && Thread.currentThread() != Fawe.get().getMainThread() && actor != null && actor.isPlayer() && actor.getSessionKey().isActive()) {
|
||||||
BBC.COMPRESSED.send(actor, saved, ratio);
|
BBC.COMPRESSED.send(actor, saved, ratio);
|
||||||
@ -103,6 +105,31 @@ public class MainUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void smoothArray(int[] data, int width, int radius, int weight) {
|
||||||
|
int[] copy = data.clone();
|
||||||
|
int length = data.length / width;
|
||||||
|
int diameter = 2 * radius + 1;
|
||||||
|
weight += diameter * diameter - 1;
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
for (int y = 0; y < length; y++) {
|
||||||
|
int index = x + width * y;
|
||||||
|
int value = 0;
|
||||||
|
int count = 0;
|
||||||
|
for (int x2 = Math.max(0, x - radius); x2 <= Math.min(width - 1, x + radius); x2++) {
|
||||||
|
for (int y2 = Math.max(0, y - radius); y2 <= Math.min(length - 1, y + radius); y2++) {
|
||||||
|
count++;
|
||||||
|
int index2 = x2 + width * y2;
|
||||||
|
value += data[index2];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value += data[index] * (weight - count);
|
||||||
|
value = value / (weight);
|
||||||
|
data[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void warnDeprecated(Class... alternatives) {
|
public static void warnDeprecated(Class... alternatives) {
|
||||||
StackTraceElement[] stack = new RuntimeException().getStackTrace();
|
StackTraceElement[] stack = new RuntimeException().getStackTrace();
|
||||||
if (stack.length > 1) {
|
if (stack.length > 1) {
|
||||||
|
@ -89,11 +89,11 @@ public class SetQueue {
|
|||||||
// Disable the async catcher as it can't discern async vs parallel
|
// Disable the async catcher as it can't discern async vs parallel
|
||||||
SET_TASK.value2.startSet(true);
|
SET_TASK.value2.startSet(true);
|
||||||
try {
|
try {
|
||||||
if (Settings.UNSAFE_PARALLEL_THREADS <= 1) {
|
if (Settings.PARALLEL_THREADS <= 1) {
|
||||||
SET_TASK.run();
|
SET_TASK.run();
|
||||||
} else {
|
} else {
|
||||||
ArrayList<Thread> threads = new ArrayList<Thread>();
|
ArrayList<Thread> threads = new ArrayList<Thread>();
|
||||||
for (int i = 0; i < Settings.UNSAFE_PARALLEL_THREADS; i++) {
|
for (int i = 0; i < Settings.PARALLEL_THREADS; i++) {
|
||||||
threads.add(new Thread(SET_TASK));
|
threads.add(new Thread(SET_TASK));
|
||||||
}
|
}
|
||||||
for (Thread thread : threads) {
|
for (Thread thread : threads) {
|
||||||
@ -197,7 +197,6 @@ public class SetQueue {
|
|||||||
inactiveQueues.remove(queue);
|
inactiveQueues.remove(queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Settings.QUEUE_SIZE != -1) {
|
if (Settings.QUEUE_SIZE != -1) {
|
||||||
|
@ -40,6 +40,14 @@ public class StringMan {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String padRight(String s, int n) {
|
||||||
|
return String.format("%1$-" + n + "s", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String padLeft(String s, int n) {
|
||||||
|
return String.format("%1$" + n + "s", s);
|
||||||
|
}
|
||||||
|
|
||||||
public static String getString(final Object obj) {
|
public static String getString(final Object obj) {
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
return "null";
|
return "null";
|
||||||
|
@ -104,7 +104,6 @@ public abstract class TaskManager {
|
|||||||
/**
|
/**
|
||||||
* Break up a task and run it in fragments of 5ms.<br>
|
* Break up a task and run it in fragments of 5ms.<br>
|
||||||
* - Each task will run on the main thread.<br>
|
* - Each task will run on the main thread.<br>
|
||||||
* - Usualy wait time is around 25ms<br>
|
|
||||||
* @param objects - The list of objects to run the task for
|
* @param objects - The list of objects to run the task for
|
||||||
* @param task - The task to run on each object
|
* @param task - The task to run on each object
|
||||||
* @param whenDone - When the object task completes
|
* @param whenDone - When the object task completes
|
||||||
@ -133,6 +132,7 @@ public abstract class TaskManager {
|
|||||||
/**
|
/**
|
||||||
* Quickly run a task on the main thread, and wait for execution to finish:<br>
|
* Quickly run a task on the main thread, and wait for execution to finish:<br>
|
||||||
* - Useful if you need to access something from the Bukkit API from another thread<br>
|
* - Useful if you need to access something from the Bukkit API from another thread<br>
|
||||||
|
* - Usualy wait time is around 25ms<br>
|
||||||
* @param function
|
* @param function
|
||||||
* @param <T>
|
* @param <T>
|
||||||
* @return
|
* @return
|
||||||
@ -144,6 +144,7 @@ public abstract class TaskManager {
|
|||||||
/**
|
/**
|
||||||
* Quickly run a task on the main thread, and wait for execution to finish:<br>
|
* Quickly run a task on the main thread, and wait for execution to finish:<br>
|
||||||
* - Useful if you need to access something from the Bukkit API from another thread<br>
|
* - Useful if you need to access something from the Bukkit API from another thread<br>
|
||||||
|
* - Usualy wait time is around 25ms<br>
|
||||||
* @param function
|
* @param function
|
||||||
* @param timeout - How long to wait for execution
|
* @param timeout - How long to wait for execution
|
||||||
* @param <T>
|
* @param <T>
|
||||||
|
@ -5,6 +5,7 @@ import com.boydti.fawe.config.Settings;
|
|||||||
import com.boydti.fawe.object.FaweLocation;
|
import com.boydti.fawe.object.FaweLocation;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.object.RegionWrapper;
|
import com.boydti.fawe.object.RegionWrapper;
|
||||||
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
import com.boydti.fawe.object.exception.FaweException;
|
import com.boydti.fawe.object.exception.FaweException;
|
||||||
import com.boydti.fawe.object.extent.NullExtent;
|
import com.boydti.fawe.object.extent.NullExtent;
|
||||||
import com.boydti.fawe.regions.FaweMask;
|
import com.boydti.fawe.regions.FaweMask;
|
||||||
@ -58,14 +59,23 @@ public class WEManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a player's mask
|
||||||
|
* @param player
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public HashSet<RegionWrapper> getMask(final FawePlayer<?> player) {
|
public HashSet<RegionWrapper> getMask(final FawePlayer<?> player) {
|
||||||
|
return TaskManager.IMP.sync(new RunnableVal<HashSet<RegionWrapper>>() {
|
||||||
|
@Override
|
||||||
|
public void run(HashSet<RegionWrapper> value) {
|
||||||
final HashSet<RegionWrapper> regions = new HashSet<>();
|
final HashSet<RegionWrapper> regions = new HashSet<>();
|
||||||
if (player.hasPermission("fawe.bypass") || !Settings.REGION_RESTRICTIONS) {
|
if (player.hasPermission("fawe.bypass") || !Settings.REGION_RESTRICTIONS) {
|
||||||
regions.add(new RegionWrapper(Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE));
|
regions.add(new RegionWrapper(Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE));
|
||||||
player.deleteMeta("lastmask");
|
player.deleteMeta("lastmask");
|
||||||
return regions;
|
this.value = regions;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
for (final FaweMaskManager manager : this.managers) {
|
for (final FaweMaskManager manager : managers) {
|
||||||
if (player.hasPermission("fawe." + manager.getKey())) {
|
if (player.hasPermission("fawe." + manager.getKey())) {
|
||||||
final FaweMask mask = manager.getMask(player);
|
final FaweMask mask = manager.getMask(player);
|
||||||
if (mask != null) {
|
if (mask != null) {
|
||||||
@ -80,14 +90,19 @@ public class WEManager {
|
|||||||
for (RegionWrapper region : mask) {
|
for (RegionWrapper region : mask) {
|
||||||
if (region.isIn(loc.x, loc.z)) {
|
if (region.isIn(loc.x, loc.z)) {
|
||||||
player.deleteMeta("lastmask");
|
player.deleteMeta("lastmask");
|
||||||
return regions;
|
this.value = regions;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mask;
|
this.value = mask;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
player.setMeta("lastmask", regions);
|
player.setMeta("lastmask", regions);
|
||||||
return regions;
|
this.value = regions;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean intersects(final RegionWrapper region1, final RegionWrapper region2) {
|
public boolean intersects(final RegionWrapper region1, final RegionWrapper region2) {
|
||||||
|
@ -205,7 +205,7 @@ public class PlayerWrapper implements Player {
|
|||||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(Object value) {
|
public void run(Object value) {
|
||||||
edit.queue.next();
|
edit.getQueue().next();
|
||||||
setPosition(new Vector(x + 0.5, y, z + 0.5));
|
setPosition(new Vector(x + 0.5, y, z + 0.5));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -229,6 +229,7 @@ public class WorldWrapper extends AbstractWorld {
|
|||||||
@Override
|
@Override
|
||||||
public boolean regenerate(final Region region, final EditSession session) {
|
public boolean regenerate(final Region region, final EditSession session) {
|
||||||
final FaweQueue queue = session.getQueue();
|
final FaweQueue queue = session.getQueue();
|
||||||
|
queue.setChangeTask(null);
|
||||||
final FaweChangeSet fcs = (FaweChangeSet) session.getChangeSet();
|
final FaweChangeSet fcs = (FaweChangeSet) session.getChangeSet();
|
||||||
final FaweRegionExtent fe = session.getRegionExtent();
|
final FaweRegionExtent fe = session.getRegionExtent();
|
||||||
session.setChangeSet(fcs);
|
session.setChangeSet(fcs);
|
||||||
@ -274,22 +275,25 @@ public class WorldWrapper extends AbstractWorld {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Vector mutable = new Vector(0,0,0);
|
||||||
for (int x = 0; x < 16; x++) {
|
for (int x = 0; x < 16; x++) {
|
||||||
int xx = x + bx;
|
int xx = x + bx;
|
||||||
|
mutable.x = xx;
|
||||||
for (int z = 0; z < 16; z++) {
|
for (int z = 0; z < 16; z++) {
|
||||||
int zz = z + bz;
|
int zz = z + bz;
|
||||||
|
mutable.z = zz;
|
||||||
for (int y = 0; y < getMaxY() + 1; y++) {
|
for (int y = 0; y < getMaxY() + 1; y++) {
|
||||||
final Vector loc = new Vector(xx, y, zz);
|
mutable.y = y;
|
||||||
int from = queue.getCombinedId4Data(xx, y, zz);
|
int from = queue.getCombinedId4Data(xx, y, zz);
|
||||||
boolean contains = (fe != null && fe.contains(xx, y, zz)) && region.contains(loc);
|
boolean contains = (fe == null || fe.contains(xx, y, zz)) && region.contains(mutable);
|
||||||
if (contains) {
|
if (contains) {
|
||||||
if (fcs != null) {
|
if (fcs != null) {
|
||||||
if (!FaweCache.hasNBT(from >> 4)) {
|
if (!FaweCache.hasNBT(from >> 4)) {
|
||||||
fcs.add(xx, y, zz, from, 0);
|
fcs.add(xx, y, zz, from, 0);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
BaseBlock block = getLazyBlock(loc);
|
BaseBlock block = getLazyBlock(mutable);
|
||||||
fcs.add(loc, block, FaweCache.CACHE_BLOCK[0]);
|
fcs.add(mutable, block, FaweCache.CACHE_BLOCK[0]);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
fcs.add(xx, y, zz, from, 0);
|
fcs.add(xx, y, zz, from, 0);
|
||||||
}
|
}
|
||||||
@ -298,30 +302,14 @@ public class WorldWrapper extends AbstractWorld {
|
|||||||
} else {
|
} else {
|
||||||
short id = (short) (from >> 4);
|
short id = (short) (from >> 4);
|
||||||
byte data = (byte) (from & 0xf);
|
byte data = (byte) (from & 0xf);
|
||||||
if (!FaweCache.hasNBT(id)) {
|
|
||||||
queue.setBlock(xx, y, zz, id, data);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
final BaseBlock block = getBlock(loc);
|
|
||||||
final Vector v = new Vector(loc.x, loc.y, loc.z);
|
|
||||||
queue.addNotifyTask(cx, cz, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
setBlock(v, block, false);
|
|
||||||
} catch (WorldEditException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
queue.setBlock(xx, y, zz, id, data);
|
queue.setBlock(xx, y, zz, id, data);
|
||||||
|
if (FaweCache.hasNBT(id)) {
|
||||||
|
BaseBlock block = getBlock(new Vector(xx, y, zz));
|
||||||
|
if (block.hasNbtData()) {
|
||||||
|
queue.setTile(xx, y, zz, block.getNbtData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,11 @@ import com.boydti.fawe.config.Settings;
|
|||||||
import com.boydti.fawe.object.EditSessionWrapper;
|
import com.boydti.fawe.object.EditSessionWrapper;
|
||||||
import com.boydti.fawe.object.FaweLimit;
|
import com.boydti.fawe.object.FaweLimit;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
|
import com.boydti.fawe.object.HistoryExtent;
|
||||||
import com.boydti.fawe.object.NullChangeSet;
|
import com.boydti.fawe.object.NullChangeSet;
|
||||||
import com.boydti.fawe.object.RegionWrapper;
|
import com.boydti.fawe.object.RegionWrapper;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
|
import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet;
|
||||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||||
import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
|
import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
|
||||||
@ -38,6 +40,7 @@ import com.boydti.fawe.object.extent.FaweRegionExtent;
|
|||||||
import com.boydti.fawe.object.extent.MemoryCheckingExtent;
|
import com.boydti.fawe.object.extent.MemoryCheckingExtent;
|
||||||
import com.boydti.fawe.object.extent.NullExtent;
|
import com.boydti.fawe.object.extent.NullExtent;
|
||||||
import com.boydti.fawe.object.extent.ProcessedWEExtent;
|
import com.boydti.fawe.object.extent.ProcessedWEExtent;
|
||||||
|
import com.boydti.fawe.object.progress.DefaultProgressTracker;
|
||||||
import com.boydti.fawe.util.FaweQueue;
|
import com.boydti.fawe.util.FaweQueue;
|
||||||
import com.boydti.fawe.util.MemUtil;
|
import com.boydti.fawe.util.MemUtil;
|
||||||
import com.boydti.fawe.util.Perm;
|
import com.boydti.fawe.util.Perm;
|
||||||
@ -158,21 +161,21 @@ public class EditSession implements Extent {
|
|||||||
BEFORE_HISTORY, BEFORE_REORDER, BEFORE_CHANGE
|
BEFORE_HISTORY, BEFORE_REORDER, BEFORE_CHANGE
|
||||||
}
|
}
|
||||||
|
|
||||||
public World world;
|
private World world;
|
||||||
public Actor actor;
|
private Actor actor;
|
||||||
public FaweChangeSet changeSet;
|
private FaweChangeSet changeSet;
|
||||||
public EditSessionWrapper wrapper;
|
private EditSessionWrapper wrapper;
|
||||||
public MaskingExtent maskingExtent;
|
private MaskingExtent maskingExtent;
|
||||||
public FaweRegionExtent regionExtent;
|
private FaweRegionExtent regionExtent;
|
||||||
public Extent primaryExtent;
|
private Extent primaryExtent;
|
||||||
public Extent bypassReorderHistory;
|
private Extent bypassReorderHistory;
|
||||||
public Extent bypassHistory;
|
private Extent bypassHistory;
|
||||||
public Extent bypassNone;
|
private Extent bypassNone;
|
||||||
public SurvivalModeExtent lazySurvivalExtent;
|
private SurvivalModeExtent lazySurvivalExtent;
|
||||||
public boolean fastmode;
|
private boolean fastmode;
|
||||||
public Mask oldMask;
|
private Mask oldMask;
|
||||||
public FaweLimit limit = FaweLimit.MAX.copy();
|
private FaweLimit limit = FaweLimit.MAX.copy();
|
||||||
public FaweQueue queue;
|
private FaweQueue queue;
|
||||||
|
|
||||||
public static BaseBiome nullBiome = new BaseBiome(0);
|
public static BaseBiome nullBiome = new BaseBiome(0);
|
||||||
public static BaseBlock nullBlock = FaweCache.CACHE_BLOCK[0];
|
public static BaseBlock nullBlock = FaweCache.CACHE_BLOCK[0];
|
||||||
@ -229,13 +232,13 @@ public class EditSession implements Extent {
|
|||||||
this.bypassReorderHistory = extent;
|
this.bypassReorderHistory = extent;
|
||||||
this.bypassHistory = extent;
|
this.bypassHistory = extent;
|
||||||
this.bypassNone = extent;
|
this.bypassNone = extent;
|
||||||
this.changeSet = new NullChangeSet();
|
this.changeSet = new NullChangeSet(world);
|
||||||
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
|
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap the world
|
// Wrap the world
|
||||||
this.world = (world = new WorldWrapper((AbstractWorld) world));
|
this.world = (world instanceof WorldWrapper) ? world : (world = new WorldWrapper((AbstractWorld) world));
|
||||||
|
|
||||||
// Delegate some methods to an implementation specific class
|
// Delegate some methods to an implementation specific class
|
||||||
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
|
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
|
||||||
@ -252,7 +255,7 @@ public class EditSession implements Extent {
|
|||||||
this.bypassReorderHistory = extent;
|
this.bypassReorderHistory = extent;
|
||||||
this.bypassHistory = extent;
|
this.bypassHistory = extent;
|
||||||
this.bypassNone = extent;
|
this.bypassNone = extent;
|
||||||
this.changeSet = new NullChangeSet();
|
this.changeSet = new NullChangeSet(world);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,8 +264,10 @@ public class EditSession implements Extent {
|
|||||||
final FawePlayer fp = FawePlayer.wrap(actor);
|
final FawePlayer fp = FawePlayer.wrap(actor);
|
||||||
final LocalSession session = fp.getSession();
|
final LocalSession session = fp.getSession();
|
||||||
this.fastmode = session.hasFastMode();
|
this.fastmode = session.hasFastMode();
|
||||||
if (fp.hasWorldEditBypass()) {
|
boolean bypass = fp.hasWorldEditBypass();
|
||||||
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true);
|
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), bypass, true);
|
||||||
|
queue.setProgressTracker(new DefaultProgressTracker(fp));
|
||||||
|
if (bypass) {
|
||||||
queue.addEditSession(this);
|
queue.addEditSession(this);
|
||||||
// Bypass skips processing and area restrictions
|
// Bypass skips processing and area restrictions
|
||||||
extent = primaryExtent = new FastWorldEditExtent(world, queue);
|
extent = primaryExtent = new FastWorldEditExtent(world, queue);
|
||||||
@ -278,7 +283,6 @@ public class EditSession implements Extent {
|
|||||||
}
|
}
|
||||||
mask = null;
|
mask = null;
|
||||||
} else {
|
} else {
|
||||||
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), false, true);
|
|
||||||
queue.addEditSession(this);
|
queue.addEditSession(this);
|
||||||
this.limit = fp.getLimit();
|
this.limit = fp.getLimit();
|
||||||
mask = WEManager.IMP.getMask(fp);
|
mask = WEManager.IMP.getMask(fp);
|
||||||
@ -326,13 +330,13 @@ public class EditSession implements Extent {
|
|||||||
extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER);
|
extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER);
|
||||||
|
|
||||||
// History
|
// History
|
||||||
this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor);
|
this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : (Settings.COMBINE_HISTORY_STAGE && Settings.COMPRESSION_LEVEL == 0) ? new CPUOptimizedChangeSet(world) : new MemoryOptimizedHistory(world);
|
||||||
|
this.changeSet = this.wrapper.wrapChangeSet(this, limit, extent, this.changeSet, queue, fp);
|
||||||
if (Settings.COMBINE_HISTORY_STAGE) {
|
if (Settings.COMBINE_HISTORY_STAGE) {
|
||||||
changeSet.addChangeTask(queue);
|
changeSet.addChangeTask(queue);
|
||||||
} else {
|
} else {
|
||||||
extent = this.wrapper.getHistoryExtent(this, limit, extent, this.changeSet, queue, fp);
|
extent = new HistoryExtent(this, limit, extent, changeSet, queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Region restrictions if mask is not null
|
// Region restrictions if mask is not null
|
||||||
if (mask != null) {
|
if (mask != null) {
|
||||||
extent = this.regionExtent = new ProcessedWEExtent(extent, mask, limit);
|
extent = this.regionExtent = new ProcessedWEExtent(extent, mask, limit);
|
||||||
@ -367,6 +371,15 @@ public class EditSession implements Extent {
|
|||||||
return regionExtent;
|
return regionExtent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the actor
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Actor getActor() {
|
||||||
|
return actor;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean cancel() {
|
public boolean cancel() {
|
||||||
// Cancel this
|
// Cancel this
|
||||||
if (primaryExtent != null && queue != null) {
|
if (primaryExtent != null && queue != null) {
|
||||||
@ -388,6 +401,12 @@ public class EditSession implements Extent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addNotifyTask(Runnable whenDone) {
|
||||||
|
if (queue != null) {
|
||||||
|
queue.addNotifyTask(whenDone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public FastWorldEditExtent getPrimaryExtent() {
|
public FastWorldEditExtent getPrimaryExtent() {
|
||||||
return (FastWorldEditExtent) primaryExtent;
|
return (FastWorldEditExtent) primaryExtent;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
|||||||
import com.boydti.fawe.util.FaweQueue;
|
import com.boydti.fawe.util.FaweQueue;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.SetQueue;
|
import com.boydti.fawe.util.SetQueue;
|
||||||
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.jchronic.Chronic;
|
import com.sk89q.jchronic.Chronic;
|
||||||
import com.sk89q.jchronic.Options;
|
import com.sk89q.jchronic.Options;
|
||||||
import com.sk89q.jchronic.utils.Span;
|
import com.sk89q.jchronic.utils.Span;
|
||||||
@ -199,10 +200,16 @@ public class LocalSession {
|
|||||||
* @param editSession the edit session
|
* @param editSession the edit session
|
||||||
*/
|
*/
|
||||||
public void remember(EditSession editSession) {
|
public void remember(EditSession editSession) {
|
||||||
remember(editSession, true);
|
remember(editSession, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remember(final EditSession editSession, final boolean append) {
|
public void remember(final EditSession editSession, final boolean append, final boolean sendMessage) {
|
||||||
|
if (editSession == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Settings.STORE_HISTORY_ON_DISK) {
|
||||||
|
MAX_HISTORY_SIZE = Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
// Enqueue it
|
// Enqueue it
|
||||||
if (editSession.getQueue() != null) {
|
if (editSession.getQueue() != null) {
|
||||||
FaweQueue queue = editSession.getQueue();
|
FaweQueue queue = editSession.getQueue();
|
||||||
@ -215,9 +222,11 @@ public class LocalSession {
|
|||||||
if (editSession.size() == 0 || editSession.hasFastMode()) return;
|
if (editSession.size() == 0 || editSession.hasFastMode()) return;
|
||||||
|
|
||||||
// Destroy any sessions after this undo point
|
// Destroy any sessions after this undo point
|
||||||
|
if (append) {
|
||||||
while (historyPointer < history.size()) {
|
while (historyPointer < history.size()) {
|
||||||
history.remove(historyPointer);
|
history.remove(historyPointer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ChangeSet set = editSession.getChangeSet();
|
ChangeSet set = editSession.getChangeSet();
|
||||||
if (set instanceof FaweStreamChangeSet) {
|
if (set instanceof FaweStreamChangeSet) {
|
||||||
final FaweStreamChangeSet fcs = (FaweStreamChangeSet) set;
|
final FaweStreamChangeSet fcs = (FaweStreamChangeSet) set;
|
||||||
@ -225,14 +234,19 @@ public class LocalSession {
|
|||||||
editSession.getQueue().addNotifyTask(new Runnable() {
|
editSession.getQueue().addNotifyTask(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (fcs.flush() && append) {
|
TaskManager.IMP.async(new Runnable() {
|
||||||
MainUtil.sendCompressedMessage(fcs, editSession.actor);
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (fcs.flush() && append && sendMessage) {
|
||||||
|
MainUtil.sendCompressedMessage(fcs, editSession.getActor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if (fcs.flush() && append) {
|
if (fcs.flush() && append && sendMessage) {
|
||||||
MainUtil.sendCompressedMessage(fcs, editSession.actor);
|
MainUtil.sendCompressedMessage(fcs, editSession.getActor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,13 +255,15 @@ public class LocalSession {
|
|||||||
}
|
}
|
||||||
if (append) {
|
if (append) {
|
||||||
history.add(editSession);
|
history.add(editSession);
|
||||||
|
historyPointer = history.size();
|
||||||
} else {
|
} else {
|
||||||
history.add(0, editSession);
|
history.add(0, editSession);
|
||||||
|
historyPointer++;
|
||||||
}
|
}
|
||||||
while (history.size() > MAX_HISTORY_SIZE) {
|
while (history.size() > MAX_HISTORY_SIZE) {
|
||||||
history.remove(0);
|
history.remove(0);
|
||||||
|
historyPointer--;
|
||||||
}
|
}
|
||||||
historyPointer = append ? history.size() : historyPointer + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -278,7 +294,6 @@ public class LocalSession {
|
|||||||
newEditSession.enableQueue();
|
newEditSession.enableQueue();
|
||||||
newEditSession.setFastMode(fastMode);
|
newEditSession.setFastMode(fastMode);
|
||||||
editSession.undo(newEditSession);
|
editSession.undo(newEditSession);
|
||||||
System.out.println("UNDO: " + historyPointer + " | " + history.size());
|
|
||||||
return editSession;
|
return editSession;
|
||||||
} else {
|
} else {
|
||||||
historyPointer = 0;
|
historyPointer = 0;
|
||||||
@ -306,7 +321,6 @@ public class LocalSession {
|
|||||||
*/
|
*/
|
||||||
public EditSession redo(@Nullable BlockBag newBlockBag, Player player) {
|
public EditSession redo(@Nullable BlockBag newBlockBag, Player player) {
|
||||||
checkNotNull(player);
|
checkNotNull(player);
|
||||||
System.out.println("CHECK REDO: " + historyPointer + " | " + history.size());
|
|
||||||
if (historyPointer < history.size()) {
|
if (historyPointer < history.size()) {
|
||||||
EditSession editSession = history.get(historyPointer);
|
EditSession editSession = history.get(historyPointer);
|
||||||
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
|
EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
|
||||||
@ -315,10 +329,7 @@ public class LocalSession {
|
|||||||
newEditSession.setFastMode(fastMode);
|
newEditSession.setFastMode(fastMode);
|
||||||
editSession.redo(newEditSession);
|
editSession.redo(newEditSession);
|
||||||
++historyPointer;
|
++historyPointer;
|
||||||
System.out.println("CAN REDO");
|
|
||||||
return editSession;
|
return editSession;
|
||||||
} else {
|
|
||||||
System.out.println("POINTER");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -155,7 +155,7 @@ public class SelectionCommand extends SimpleCommand<Operation> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
queue.enqueue();
|
queue.enqueue();
|
||||||
editSession.setChangeSet(new NullChangeSet());
|
editSession.setChangeSet(new NullChangeSet(null));
|
||||||
BBC.OPERATION.send(actor, BBC.VISITOR_BLOCK.format(cuboid.getArea()));
|
BBC.OPERATION.send(actor, BBC.VISITOR_BLOCK.format(cuboid.getArea()));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ package com.sk89q.worldedit.extension.platform;
|
|||||||
import com.boydti.fawe.config.BBC;
|
import com.boydti.fawe.config.BBC;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.object.exception.FaweException;
|
import com.boydti.fawe.object.exception.FaweException;
|
||||||
import com.boydti.fawe.util.SetQueue;
|
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.boydti.fawe.wrappers.PlayerWrapper;
|
import com.boydti.fawe.wrappers.PlayerWrapper;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
@ -224,7 +223,6 @@ public final class CommandManager {
|
|||||||
TaskManager.IMP.async(new Runnable() {
|
TaskManager.IMP.async(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
System.out.println("COMMAND START!");
|
|
||||||
final Actor actor = platformManager.createProxyActor(event.getActor());
|
final Actor actor = platformManager.createProxyActor(event.getActor());
|
||||||
String[] split = commandDetection(event.getArguments().split(" "));
|
String[] split = commandDetection(event.getArguments().split(" "));
|
||||||
|
|
||||||
@ -233,11 +231,11 @@ public final class CommandManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalSession session = worldEdit.getSessionManager().get(actor);
|
final LocalSession session = worldEdit.getSessionManager().get(actor);
|
||||||
LocalConfiguration config = worldEdit.getConfiguration();
|
LocalConfiguration config = worldEdit.getConfiguration();
|
||||||
|
|
||||||
CommandLocals locals = new CommandLocals();
|
CommandLocals locals = new CommandLocals();
|
||||||
FawePlayer fp = FawePlayer.wrap(actor);
|
final FawePlayer fp = FawePlayer.wrap(actor);
|
||||||
if (fp != null) {
|
if (fp != null) {
|
||||||
if (fp.getMeta("fawe_action") != null) {
|
if (fp.getMeta("fawe_action") != null) {
|
||||||
BBC.WORLDEDIT_COMMAND_LIMIT.send(fp);
|
BBC.WORLDEDIT_COMMAND_LIMIT.send(fp);
|
||||||
@ -285,36 +283,33 @@ public final class CommandManager {
|
|||||||
log.log(Level.SEVERE, "An unknown error occurred", e);
|
log.log(Level.SEVERE, "An unknown error occurred", e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
System.out.println("DONE!");
|
final EditSession editSession = locals.get(EditSession.class);
|
||||||
if (fp != null) {
|
boolean delayed = false;
|
||||||
fp.deleteMeta("fawe_action");
|
|
||||||
}
|
|
||||||
EditSession editSession = locals.get(EditSession.class);
|
|
||||||
|
|
||||||
if (editSession != null) {
|
if (editSession != null) {
|
||||||
session.remember(editSession);
|
|
||||||
editSession.flushQueue();
|
editSession.flushQueue();
|
||||||
final long time = System.currentTimeMillis() - start;
|
worldEdit.flushBlockBag(actor, editSession);
|
||||||
if (time > 5 && editSession.size() != 0) {
|
}
|
||||||
SetQueue.IMP.addTask(new Runnable() {
|
if (fp != null) {
|
||||||
|
if (editSession != null && editSession.size() > 0 && editSession.getQueue() != null) {
|
||||||
|
delayed = true;
|
||||||
|
editSession.getQueue().addNotifyTask(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
session.remember(editSession, true, true);
|
||||||
|
fp.deleteMeta("fawe_action");
|
||||||
final long time = System.currentTimeMillis() - start;
|
final long time = System.currentTimeMillis() - start;
|
||||||
|
if (time > 5) {
|
||||||
BBC.ACTION_COMPLETE.send(actor, (time / 1000d));
|
BBC.ACTION_COMPLETE.send(actor, (time / 1000d));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (config.profile) {
|
|
||||||
int changed = editSession.getBlockChangeCount();
|
|
||||||
if (time > 0) {
|
|
||||||
double throughput = changed / (time / 1000.0);
|
|
||||||
actor.printDebug((time / 1000.0) + "s elapsed (history: " + changed + " changed; " + Math.round(throughput) + " blocks/sec).");
|
|
||||||
} else {
|
|
||||||
actor.printDebug((time / 1000.0) + "s elapsed.");
|
|
||||||
}
|
}
|
||||||
|
if (!delayed) {
|
||||||
|
if (fp != null) {
|
||||||
|
fp.deleteMeta("fawe_action");
|
||||||
}
|
}
|
||||||
|
session.remember(editSession, true, true);
|
||||||
worldEdit.flushBlockBag(actor, editSession);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
pom.xml
7
pom.xml
@ -29,6 +29,13 @@
|
|||||||
</includes>
|
</includes>
|
||||||
<directory>bukkit18/src/main/resources/</directory>
|
<directory>bukkit18/src/main/resources/</directory>
|
||||||
</resource>
|
</resource>
|
||||||
|
<resource>
|
||||||
|
<filtering>false</filtering>
|
||||||
|
<includes>
|
||||||
|
<include>**/*.*</include>
|
||||||
|
</includes>
|
||||||
|
<directory>core/src/main/resources/</directory>
|
||||||
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -47,11 +47,11 @@ public class SpongeCommand implements CommandCallable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<? extends Text> getHelp(final CommandSource cmd) {
|
public Optional<? extends Text> getHelp(final CommandSource cmd) {
|
||||||
return Optional.of(Text.of("/<fixlighting|stream|wea|wrg>"));
|
return Optional.of(Text.of("/<fixlighting|stream|wea|select>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Text getUsage(final CommandSource cmd) {
|
public Text getUsage(final CommandSource cmd) {
|
||||||
return Text.of("/<fixlighting|stream|wea|wrg>");
|
return Text.of("/<fixlighting|stream|wea|select>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.wor
|
|||||||
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
|
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
|
||||||
Chunk spongeChunk = (Chunk) nmsChunk;
|
Chunk spongeChunk = (Chunk) nmsChunk;
|
||||||
|
|
||||||
char[][] ids = ((SpongeChunk_1_8) fc).getIdArrays();
|
char[][] ids = ((SpongeChunk_1_8) fc).getCombinedIdArrays();
|
||||||
MutableBlockVolumeWorker<? extends Chunk> blockWorker = spongeChunk.getBlockWorker();
|
MutableBlockVolumeWorker<? extends Chunk> blockWorker = spongeChunk.getBlockWorker();
|
||||||
blockWorker.map(new BlockVolumeMapper() {
|
blockWorker.map(new BlockVolumeMapper() {
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user