Various fixe + Restructuring + Possible breakage
This commit is contained in:
parent
3a8d54bb78
commit
36fdbe55fe
@ -55,4 +55,6 @@ public abstract class ABukkitMain extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract FaweQueue getQueue(World world);
|
public abstract FaweQueue getQueue(World world);
|
||||||
|
|
||||||
|
public abstract FaweQueue getQueue(String world);
|
||||||
}
|
}
|
@ -150,6 +150,47 @@ public class FaweBukkit implements IFawe, Listener {
|
|||||||
private boolean hasNMS = true;
|
private boolean hasNMS = true;
|
||||||
private boolean playerChunk = false;
|
private boolean playerChunk = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getNewQueue(String world, boolean fast) {
|
||||||
|
if (playerChunk != (playerChunk = true)) {
|
||||||
|
try {
|
||||||
|
Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField();
|
||||||
|
fieldDirtyCount.setAccessible(true);
|
||||||
|
int mod = fieldDirtyCount.getModifiers();
|
||||||
|
if ((mod & Modifier.VOLATILE) == 0) {
|
||||||
|
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||||
|
modifiersField.setAccessible(true);
|
||||||
|
modifiersField.setInt(fieldDirtyCount, mod + Modifier.VOLATILE);
|
||||||
|
}
|
||||||
|
} catch (Throwable ignore) {}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return plugin.getQueue(world);
|
||||||
|
} catch (Throwable ignore) {}
|
||||||
|
// Disable incompatible settings
|
||||||
|
Settings.QUEUE.PARALLEL_THREADS = 1; // BukkitAPI placer is too slow to parallel thread at the chunk level
|
||||||
|
Settings.HISTORY.COMBINE_STAGES = false; // Performing a chunk copy (if possible) wouldn't be faster using the BukkitAPI
|
||||||
|
if (hasNMS) {
|
||||||
|
debug("====== NO NMS BLOCK PLACER FOUND ======");
|
||||||
|
debug("FAWE couldn't find a fast block placer");
|
||||||
|
debug("Bukkit version: " + Bukkit.getVersion());
|
||||||
|
debug("NMS label: " + plugin.getClass().getSimpleName().split("_")[1]);
|
||||||
|
debug("Fallback placer: " + BukkitQueue_All.class);
|
||||||
|
debug("=======================================");
|
||||||
|
debug("Download the version of FAWE for your platform");
|
||||||
|
debug(" - http://ci.athion.net/job/FastAsyncWorldEdit/lastSuccessfulBuild/artifact/target");
|
||||||
|
debug("=======================================");
|
||||||
|
TaskManager.IMP.laterAsync(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
MainUtil.sendAdmin("&cNo NMS placer found, see console!");
|
||||||
|
}
|
||||||
|
}, 1);
|
||||||
|
hasNMS = false;
|
||||||
|
}
|
||||||
|
return new BukkitQueue_All(world);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The FaweQueue is a core part of block placement<br>
|
* The FaweQueue is a core part of block placement<br>
|
||||||
* - The queue returned here is used in the SetQueue class (SetQueue handles the implementation specific queue)<br>
|
* - The queue returned here is used in the SetQueue class (SetQueue handles the implementation specific queue)<br>
|
||||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.v0;
|
|||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.example.CharFaweChunk;
|
import com.boydti.fawe.example.CharFaweChunk;
|
||||||
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
@ -17,7 +18,7 @@ import org.bukkit.Chunk;
|
|||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
public class BukkitChunk_All extends CharFaweChunk<Chunk> {
|
public class BukkitChunk_All extends CharFaweChunk<Chunk, BukkitQueue_All> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||||
@ -39,17 +40,23 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk> {
|
|||||||
private int index;
|
private int index;
|
||||||
private boolean place = true;
|
private boolean place = true;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
getChunk().load(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public void execute(long start) {
|
@Override
|
||||||
|
public FaweChunk call() {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
int recommended = 25 + BukkitQueue_All.ALLOCATE;
|
int recommended = 25 + BukkitQueue_All.ALLOCATE;
|
||||||
boolean more = true;
|
boolean more = true;
|
||||||
BukkitQueue_All parent = (BukkitQueue_All) getParent();
|
BukkitQueue_All parent = (BukkitQueue_All) getParent();
|
||||||
final Chunk chunk = getChunk();
|
final Chunk chunk = getChunk();
|
||||||
Object[] disableResult = parent.disableLighting(chunk);
|
Object[] disableResult = parent.disableLighting(chunk);
|
||||||
chunk.load(true);
|
|
||||||
final World world = chunk.getWorld();
|
final World world = chunk.getWorld();
|
||||||
char[][] sections = getCombinedIdArrays();
|
char[][] sections = getCombinedIdArrays();
|
||||||
if (layer == -1) {
|
if (layer == -1) {
|
||||||
@ -220,6 +227,7 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk> {
|
|||||||
this.addToQueue();
|
this.addToQueue();
|
||||||
}
|
}
|
||||||
parent.resetLighting(disableResult);
|
parent.resetLighting(disableResult);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBlock(Block block, int id, byte data) {
|
public void setBlock(Block block, int id, byte data) {
|
||||||
|
@ -42,6 +42,15 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BukkitQueue_0(String world) {
|
||||||
|
super(world);
|
||||||
|
setupAdapter(null);
|
||||||
|
if (!registered) {
|
||||||
|
registered = true;
|
||||||
|
Bukkit.getServer().getPluginManager().registerEvents(this, ((FaweBukkit) Fawe.imp()).getPlugin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getSaveFolder() {
|
public File getSaveFolder() {
|
||||||
return new File(Bukkit.getWorldContainer(), getWorldName() + File.separator + "region");
|
return new File(Bukkit.getWorldContainer(), getWorldName() + File.separator + "region");
|
||||||
@ -210,14 +219,4 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
|
|||||||
try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, true); } catch (Throwable ignore) {}
|
try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, true); } catch (Throwable ignore) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public FaweChunk getFaweChunk(int x, int z) {
|
|
||||||
return new CharFaweChunk<Chunk>(this, x, z) {
|
|
||||||
@Override
|
|
||||||
public Chunk getNewChunk() {
|
|
||||||
return BukkitQueue_0.this.getWorld().getChunkAt(getX(), getZ());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
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.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
@ -26,6 +25,16 @@ public class BukkitQueue_All extends BukkitQueue_0<Chunk, Chunk, Chunk> {
|
|||||||
if (Settings.QUEUE.EXTRA_TIME_MS != Integer.MIN_VALUE) {
|
if (Settings.QUEUE.EXTRA_TIME_MS != Integer.MIN_VALUE) {
|
||||||
ALLOCATE = Settings.QUEUE.EXTRA_TIME_MS;
|
ALLOCATE = Settings.QUEUE.EXTRA_TIME_MS;
|
||||||
Settings.QUEUE.EXTRA_TIME_MS = Integer.MIN_VALUE;
|
Settings.QUEUE.EXTRA_TIME_MS = Integer.MIN_VALUE;
|
||||||
|
Settings.QUEUE.PARALLEL_THREADS = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BukkitQueue_All(String world) {
|
||||||
|
super(world);
|
||||||
|
if (Settings.QUEUE.EXTRA_TIME_MS != Integer.MIN_VALUE) {
|
||||||
|
ALLOCATE = Settings.QUEUE.EXTRA_TIME_MS;
|
||||||
|
Settings.QUEUE.EXTRA_TIME_MS = Integer.MIN_VALUE;
|
||||||
|
Settings.QUEUE.PARALLEL_THREADS = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,21 +123,6 @@ public class BukkitQueue_All extends BukkitQueue_0<Chunk, Chunk, Chunk> {
|
|||||||
|
|
||||||
private int skip;
|
private int skip;
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
|
||||||
if (skip > 0) {
|
|
||||||
skip--;
|
|
||||||
fc.addToQueue();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
((BukkitChunk_All) fc).execute(start);
|
|
||||||
if (System.currentTimeMillis() - start > 50 || Fawe.get().getTPS() < TPS_TARGET) {
|
|
||||||
skip = 10;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startSet(boolean parallel) {
|
public void startSet(boolean parallel) {
|
||||||
super.startSet(true);
|
super.startSet(true);
|
||||||
|
@ -129,7 +129,7 @@ public class AsyncWorld implements World {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public synchronized static AsyncWorld create(final WorldCreator creator) {
|
public synchronized static AsyncWorld create(final WorldCreator creator) {
|
||||||
BukkitQueue_0 queue = (BukkitQueue_0) SetQueue.IMP.getNewQueue(FaweAPI.getWorld(creator.name()), true, false);
|
BukkitQueue_0 queue = (BukkitQueue_0) SetQueue.IMP.getNewQueue(creator.name(), true, false);
|
||||||
World world = queue.createWorld(creator);
|
World world = queue.createWorld(creator);
|
||||||
return wrap(world);
|
return wrap(world);
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,49 @@
|
|||||||
package com.boydti.fawe.bukkit.v1_10;
|
package com.boydti.fawe.bukkit.v1_10;
|
||||||
|
|
||||||
|
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.object.BytePair;
|
||||||
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.boydti.fawe.util.MathMan;
|
||||||
|
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.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import net.minecraft.server.v1_10_R1.Block;
|
import net.minecraft.server.v1_10_R1.Block;
|
||||||
|
import net.minecraft.server.v1_10_R1.BlockPosition;
|
||||||
|
import net.minecraft.server.v1_10_R1.ChunkSection;
|
||||||
import net.minecraft.server.v1_10_R1.DataBits;
|
import net.minecraft.server.v1_10_R1.DataBits;
|
||||||
import net.minecraft.server.v1_10_R1.DataPalette;
|
import net.minecraft.server.v1_10_R1.DataPalette;
|
||||||
import net.minecraft.server.v1_10_R1.DataPaletteBlock;
|
import net.minecraft.server.v1_10_R1.DataPaletteBlock;
|
||||||
import net.minecraft.server.v1_10_R1.DataPaletteGlobal;
|
import net.minecraft.server.v1_10_R1.DataPaletteGlobal;
|
||||||
|
import net.minecraft.server.v1_10_R1.Entity;
|
||||||
|
import net.minecraft.server.v1_10_R1.EntityPlayer;
|
||||||
|
import net.minecraft.server.v1_10_R1.EntityTypes;
|
||||||
import net.minecraft.server.v1_10_R1.IBlockData;
|
import net.minecraft.server.v1_10_R1.IBlockData;
|
||||||
|
import net.minecraft.server.v1_10_R1.NBTTagCompound;
|
||||||
|
import net.minecraft.server.v1_10_R1.TileEntity;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.craftbukkit.v1_10_R1.CraftChunk;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
|
||||||
public class BukkitChunk_1_10 extends CharFaweChunk<Chunk> {
|
public class BukkitChunk_1_10 extends CharFaweChunk<Chunk, BukkitQueue_1_10> {
|
||||||
|
|
||||||
public DataPaletteBlock[] sectionPalettes;
|
public DataPaletteBlock[] sectionPalettes;
|
||||||
|
|
||||||
@ -35,7 +64,7 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
public CharFaweChunk<Chunk, BukkitQueue_1_10> copy(boolean shallow) {
|
||||||
BukkitChunk_1_10 value = (BukkitChunk_1_10) super.copy(shallow);
|
BukkitChunk_1_10 value = (BukkitChunk_1_10) super.copy(shallow);
|
||||||
if (sectionPalettes != null) {
|
if (sectionPalettes != null) {
|
||||||
value.sectionPalettes = new DataPaletteBlock[16];
|
value.sectionPalettes = new DataPaletteBlock[16];
|
||||||
@ -125,4 +154,229 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
getChunk().load(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweChunk call() {
|
||||||
|
try {
|
||||||
|
final Chunk chunk = this.getChunk();
|
||||||
|
final World world = chunk.getWorld();
|
||||||
|
final boolean flag = world.getEnvironment() == World.Environment.NORMAL;
|
||||||
|
net.minecraft.server.v1_10_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
||||||
|
nmsChunk.f(true); // Set Modified
|
||||||
|
nmsChunk.mustSave = true;
|
||||||
|
net.minecraft.server.v1_10_R1.World nmsWorld = nmsChunk.world;
|
||||||
|
ChunkSection[] sections = nmsChunk.getSections();
|
||||||
|
Class<? extends net.minecraft.server.v1_10_R1.Chunk> clazzChunk = nmsChunk.getClass();
|
||||||
|
final Collection<Entity>[] entities = (Collection<Entity>[]) getParent().getEntitySlices.invoke(nmsChunk);
|
||||||
|
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
||||||
|
// Remove entities
|
||||||
|
for (int i = 0; i < entities.length; i++) {
|
||||||
|
int count = this.getCount(i);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
entities[i].clear();
|
||||||
|
} else {
|
||||||
|
char[] array = this.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 || y < 0 || y > 255) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HashSet<UUID> entsToRemove = this.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 = this.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) BukkitQueue_1_10.methodFromNative.invoke(BukkitQueue_1_10.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 (getParent().getChangeTask() != null) {
|
||||||
|
BukkitChunk_1_10 previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||||
|
getParent().getChangeTask().run(previous, this);
|
||||||
|
}
|
||||||
|
// Trim tiles
|
||||||
|
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
|
||||||
|
HashMap<BlockPosition, TileEntity> toRemove = null;
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<BlockPosition, TileEntity> tile = iterator.next();
|
||||||
|
BlockPosition pos = tile.getKey();
|
||||||
|
int lx = pos.getX() & 15;
|
||||||
|
int ly = pos.getY();
|
||||||
|
int lz = pos.getZ() & 15;
|
||||||
|
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||||
|
char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||||
|
if (array[k] != 0) {
|
||||||
|
if (toRemove == null) {
|
||||||
|
toRemove = new HashMap<>();
|
||||||
|
}
|
||||||
|
toRemove.put(tile.getKey(), tile.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toRemove != null) {
|
||||||
|
for (Map.Entry<BlockPosition, TileEntity> entry : toRemove.entrySet()) {
|
||||||
|
BlockPosition bp = entry.getKey();
|
||||||
|
TileEntity tile = entry.getValue();
|
||||||
|
tiles.remove(bp);
|
||||||
|
tile.y();
|
||||||
|
nmsWorld.s(bp);
|
||||||
|
tile.invalidateBlockCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Set blocks
|
||||||
|
for (int j = 0; j < sections.length; j++) {
|
||||||
|
int count = this.getCount(j);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ChunkSection section = sections[j];
|
||||||
|
if (section == null) {
|
||||||
|
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||||
|
section = sections[j] = getParent().newChunkSection(j << 4, flag, null);
|
||||||
|
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||||
|
getParent().setCount(0, count - this.getAir(j), section);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sections[j] = getParent().newChunkSection(j << 4, flag, array);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||||
|
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||||
|
getParent().setCount(0, count - this.getAir(j), section);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sections[j] = getParent().newChunkSection(j << 4, flag, array);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DataPaletteBlock nibble = section.getBlocks();
|
||||||
|
int nonEmptyBlockCount = 0;
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
short[][] i1 = FaweCache.CACHE_J[y];
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
short[] i2 = i1[z];
|
||||||
|
for (int x= 0; x < 16; x++) {
|
||||||
|
char combinedId = array[i2[x]];
|
||||||
|
switch (combinedId) {
|
||||||
|
case 0:
|
||||||
|
IBlockData existing = nibble.a(x, y, z);
|
||||||
|
if (existing != BukkitQueue_1_10.air) {
|
||||||
|
nonEmptyBlockCount++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case 1:
|
||||||
|
nibble.setBlock(x, y, z, BukkitQueue_1_10.air);
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
nonEmptyBlockCount++;
|
||||||
|
nibble.setBlock(x, y, z, getParent().IBD_CACHE[(int) combinedId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getParent().setCount(0, nonEmptyBlockCount, section);
|
||||||
|
}
|
||||||
|
// Set biomes
|
||||||
|
int[][] biomes = this.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 = this.getTiles();
|
||||||
|
int bx = this.getX() << 4;
|
||||||
|
int bz = this.getZ() << 4;
|
||||||
|
|
||||||
|
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||||
|
CompoundTag nativeTag = entry.getValue();
|
||||||
|
BytePair pair = entry.getKey();
|
||||||
|
BlockPosition pos = new BlockPosition(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos
|
||||||
|
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||||
|
if (tileEntity != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_10.methodFromNative.invoke(BukkitQueue_1_10.adapter, nativeTag);
|
||||||
|
tileEntity.a(tag); // ReadTagIntoTile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
MainUtil.handleError(e);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.v1_10;
|
|||||||
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.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
|
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
|
||||||
import com.boydti.fawe.object.io.FastByteArrayInputStream;
|
import com.boydti.fawe.object.io.FastByteArrayInputStream;
|
||||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||||
@ -31,6 +32,11 @@ public class BukkitMain_110 extends ABukkitMain {
|
|||||||
return new BukkitQueue_1_10(world);
|
return new BukkitQueue_1_10(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getQueue(String world) {
|
||||||
|
return new BukkitQueue_1_10(world);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
super.onEnable();
|
super.onEnable();
|
||||||
|
@ -4,7 +4,6 @@ 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.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
@ -12,26 +11,19 @@ import com.boydti.fawe.util.MathMan;
|
|||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.LongTag;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.internal.Constants;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
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.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
import net.minecraft.server.v1_10_R1.Block;
|
import net.minecraft.server.v1_10_R1.Block;
|
||||||
import net.minecraft.server.v1_10_R1.BlockPosition;
|
import net.minecraft.server.v1_10_R1.BlockPosition;
|
||||||
import net.minecraft.server.v1_10_R1.ChunkSection;
|
import net.minecraft.server.v1_10_R1.ChunkSection;
|
||||||
@ -62,26 +54,33 @@ import net.minecraft.server.v1_10_R1.WorldType;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.World.Environment;
|
|
||||||
import org.bukkit.WorldCreator;
|
import org.bukkit.WorldCreator;
|
||||||
import org.bukkit.craftbukkit.v1_10_R1.CraftChunk;
|
import org.bukkit.craftbukkit.v1_10_R1.CraftChunk;
|
||||||
import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
|
import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
|
||||||
import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
|
import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
import org.bukkit.event.world.WorldInitEvent;
|
import org.bukkit.event.world.WorldInitEvent;
|
||||||
import org.bukkit.event.world.WorldLoadEvent;
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
|
||||||
public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
|
public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
|
||||||
|
|
||||||
private static IBlockData air;
|
protected static IBlockData air;
|
||||||
private static Field fieldBits;
|
protected static Field fieldBits;
|
||||||
private static Method getEntitySlices;
|
protected static Method getEntitySlices;
|
||||||
|
|
||||||
public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE];
|
public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE];
|
||||||
|
|
||||||
public BukkitQueue_1_10(final com.sk89q.worldedit.world.World world) {
|
public BukkitQueue_1_10(final com.sk89q.worldedit.world.World world) {
|
||||||
super(world);
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BukkitQueue_1_10(final String world) {
|
||||||
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
checkVersion("v1_10_R1");
|
checkVersion("v1_10_R1");
|
||||||
if (air == null) {
|
if (air == null) {
|
||||||
try {
|
try {
|
||||||
@ -108,6 +107,11 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean next(int amount, ExecutorCompletionService pool, long time) {
|
||||||
|
return super.next(amount, pool, time);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSkyLight(ChunkSection section, int x, int y, int z, int value) {
|
public void setSkyLight(ChunkSection section, int x, int y, int z, int value) {
|
||||||
section.getSkyLightArray().a(x & 15, y & 15, z & 15, value);
|
section.getSkyLightArray().a(x & 15, y & 15, z & 15, value);
|
||||||
@ -118,8 +122,8 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
|||||||
section.getEmittedLightArray().a(x & 15, y & 15, z & 15, value);
|
section.getEmittedLightArray().a(x & 15, y & 15, z & 15, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataBits lastBits;
|
protected DataBits lastBits;
|
||||||
private DataPaletteBlock lastBlocks;
|
protected DataPaletteBlock lastBlocks;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World createWorld(final WorldCreator creator) {
|
public World createWorld(final WorldCreator creator) {
|
||||||
@ -354,7 +358,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
|||||||
nmsWorld.w(pos);
|
nmsWorld.w(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorldServer nmsWorld;
|
protected WorldServer nmsWorld;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World getImpWorld() {
|
public World getImpWorld() {
|
||||||
@ -402,10 +406,10 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharFaweChunk getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
|
public BukkitChunk_1_10 getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||||
Map<BlockPosition, TileEntity> tiles = (Map<BlockPosition, TileEntity>) tilesGeneric;
|
Map<BlockPosition, TileEntity> tiles = (Map<BlockPosition, TileEntity>) tilesGeneric;
|
||||||
Collection<Entity>[] entities = (Collection<Entity>[]) entitiesGeneric;
|
Collection<Entity>[] entities = (Collection<Entity>[]) entitiesGeneric;
|
||||||
CharFaweChunk previous = (CharFaweChunk) getFaweChunk(fs.getX(), fs.getZ());
|
BukkitChunk_1_10 previous = getFaweChunk(fs.getX(), fs.getZ());
|
||||||
// Copy blocks
|
// Copy blocks
|
||||||
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++) {
|
||||||
@ -481,7 +485,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
|||||||
return previous;
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||||
@ -507,228 +511,6 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
|||||||
return world.getChunkAt(x, z);
|
return world.getChunkAt(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComponents(final FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
|
||||||
final com.boydti.fawe.bukkit.v1_10.BukkitChunk_1_10 fs = (com.boydti.fawe.bukkit.v1_10.BukkitChunk_1_10) fc;
|
|
||||||
final Chunk chunk = (Chunk) fs.getChunk();
|
|
||||||
final World world = chunk.getWorld();
|
|
||||||
chunk.load(true);
|
|
||||||
try {
|
|
||||||
final boolean flag = world.getEnvironment() == Environment.NORMAL;
|
|
||||||
net.minecraft.server.v1_10_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
|
||||||
nmsChunk.f(true); // Set Modified
|
|
||||||
nmsChunk.mustSave = true;
|
|
||||||
net.minecraft.server.v1_10_R1.World nmsWorld = nmsChunk.world;
|
|
||||||
ChunkSection[] sections = nmsChunk.getSections();
|
|
||||||
Class<? extends net.minecraft.server.v1_10_R1.Chunk> clazzChunk = nmsChunk.getClass();
|
|
||||||
final Collection<Entity>[] entities = (Collection<Entity>[]) getEntitySlices.invoke(nmsChunk);
|
|
||||||
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
|
||||||
// Remove entities
|
|
||||||
for (int i = 0; i < entities.length; 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 || y < 0 || y > 255) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 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
|
|
||||||
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
|
|
||||||
HashMap<BlockPosition, TileEntity> toRemove = null;
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Map.Entry<BlockPosition, TileEntity> tile = iterator.next();
|
|
||||||
BlockPosition pos = tile.getKey();
|
|
||||||
int lx = pos.getX() & 15;
|
|
||||||
int ly = pos.getY();
|
|
||||||
int lz = pos.getZ() & 15;
|
|
||||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
|
||||||
char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
|
||||||
if (array[k] != 0) {
|
|
||||||
if (toRemove == null) {
|
|
||||||
toRemove = new HashMap<>();
|
|
||||||
}
|
|
||||||
toRemove.put(tile.getKey(), tile.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (toRemove != null) {
|
|
||||||
for (Entry<BlockPosition, TileEntity> entry : toRemove.entrySet()) {
|
|
||||||
BlockPosition bp = entry.getKey();
|
|
||||||
TileEntity tile = entry.getValue();
|
|
||||||
tiles.remove(bp);
|
|
||||||
tile.y();
|
|
||||||
nmsWorld.s(bp);
|
|
||||||
tile.invalidateBlockCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// Set blocks
|
|
||||||
for (int j = 0; j < sections.length; j++) {
|
|
||||||
int count = fs.getCount(j);
|
|
||||||
if (count == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ChunkSection section = sections[j];
|
|
||||||
if (section == null) {
|
|
||||||
if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) {
|
|
||||||
section = sections[j] = newChunkSection(j << 4, flag, null);
|
|
||||||
setPalette(section, fs.sectionPalettes[j]);
|
|
||||||
setCount(0, count - fs.getAir(j), section);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
sections[j] = newChunkSection(j << 4, flag, array);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if (count >= 4096) {
|
|
||||||
if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) {
|
|
||||||
setPalette(section, fs.sectionPalettes[j]);
|
|
||||||
setCount(0, count - fs.getAir(j), section);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
sections[j] = newChunkSection(j << 4, flag, array);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
DataPaletteBlock nibble = section.getBlocks();
|
|
||||||
int nonEmptyBlockCount = 0;
|
|
||||||
for (int y = 0; y < 16; y++) {
|
|
||||||
short[][] i1 = FaweCache.CACHE_J[y];
|
|
||||||
for (int z = 0; z < 16; z++) {
|
|
||||||
short[] i2 = i1[z];
|
|
||||||
for (int x= 0; x < 16; x++) {
|
|
||||||
char combinedId = array[i2[x]];
|
|
||||||
switch (combinedId) {
|
|
||||||
case 0:
|
|
||||||
IBlockData existing = nibble.a(x, y, z);
|
|
||||||
if (existing != air) {
|
|
||||||
nonEmptyBlockCount++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
case 1:
|
|
||||||
nibble.setBlock(x, y, z, air);
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
nonEmptyBlockCount++;
|
|
||||||
nibble.setBlock(x, y, z, IBD_CACHE[(int) combinedId]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCount(0, nonEmptyBlockCount, section);
|
|
||||||
}
|
|
||||||
// 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((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + 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) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean unloadChunk(final String world, final Chunk chunk) {
|
public boolean unloadChunk(final String world, final Chunk chunk) {
|
||||||
net.minecraft.server.v1_10_R1.Chunk c = ((CraftChunk) chunk).getHandle();
|
net.minecraft.server.v1_10_R1.Chunk c = ((CraftChunk) chunk).getHandle();
|
||||||
@ -740,7 +522,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweChunk getFaweChunk(int x, int z) {
|
public BukkitChunk_1_10 getFaweChunk(int x, int z) {
|
||||||
return new com.boydti.fawe.bukkit.v1_10.BukkitChunk_1_10(this, x, z);
|
return new com.boydti.fawe.bukkit.v1_10.BukkitChunk_1_10(this, x, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,41 @@
|
|||||||
package com.boydti.fawe.bukkit.v1_7;
|
package com.boydti.fawe.bukkit.v1_7;
|
||||||
|
|
||||||
|
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.object.BytePair;
|
||||||
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.boydti.fawe.util.MathMan;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.ListTag;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
import com.sk89q.worldedit.internal.Constants;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import net.minecraft.server.v1_7_R4.ChunkPosition;
|
||||||
|
import net.minecraft.server.v1_7_R4.ChunkSection;
|
||||||
|
import net.minecraft.server.v1_7_R4.Entity;
|
||||||
|
import net.minecraft.server.v1_7_R4.EntityPlayer;
|
||||||
|
import net.minecraft.server.v1_7_R4.EntityTypes;
|
||||||
|
import net.minecraft.server.v1_7_R4.NBTTagCompound;
|
||||||
import net.minecraft.server.v1_7_R4.NibbleArray;
|
import net.minecraft.server.v1_7_R4.NibbleArray;
|
||||||
|
import net.minecraft.server.v1_7_R4.TileEntity;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.craftbukkit.v1_7_R4.CraftChunk;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
|
||||||
public class BukkitChunk_1_7 extends CharFaweChunk<Chunk> {
|
public class BukkitChunk_1_7 extends CharFaweChunk<Chunk, BukkitQueue17> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Chunk getNewChunk() {
|
public Chunk getNewChunk() {
|
||||||
@ -87,7 +114,7 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
public BukkitChunk_1_7 copy(boolean shallow) {
|
||||||
BukkitChunk_1_7 copy = new BukkitChunk_1_7(getParent(), getX(), getZ());
|
BukkitChunk_1_7 copy = new BukkitChunk_1_7(getParent(), getX(), getZ());
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
copy.byteIds = byteIds;
|
copy.byteIds = byteIds;
|
||||||
@ -108,4 +135,232 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
getChunk().load(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweChunk call() {
|
||||||
|
CraftChunk chunk = (CraftChunk) this.getChunk();
|
||||||
|
net.minecraft.server.v1_7_R4.Chunk nmsChunk = chunk.getHandle();
|
||||||
|
nmsChunk.e(); // Modified
|
||||||
|
nmsChunk.mustSave = true;
|
||||||
|
net.minecraft.server.v1_7_R4.World nmsWorld = nmsChunk.world;
|
||||||
|
try {
|
||||||
|
final boolean flag = getParent().getWorld().getEnvironment() == World.Environment.NORMAL;
|
||||||
|
// Sections
|
||||||
|
ChunkSection[] sections = nmsChunk.getSections();
|
||||||
|
Map<ChunkPosition, TileEntity> tiles = nmsChunk.tileEntities;
|
||||||
|
Collection<Entity>[] entities = nmsChunk.entitySlices;
|
||||||
|
|
||||||
|
// Remove entities
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
int count = this.getCount(i);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
entities[i].clear();
|
||||||
|
} else {
|
||||||
|
char[] array = this.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;
|
||||||
|
}
|
||||||
|
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set entities
|
||||||
|
Set<UUID> createdEntities = new HashSet<>();
|
||||||
|
Set<CompoundTag> entitiesToSpawn = this.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) BukkitQueue17.methodFromNative.invoke(BukkitQueue17.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 (getParent().getChangeTask() != null) {
|
||||||
|
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||||
|
getParent().getChangeTask().run(previous, this);
|
||||||
|
}
|
||||||
|
// Trim tiles
|
||||||
|
Iterator<Map.Entry<ChunkPosition, TileEntity>> iterator = tiles.entrySet().iterator();
|
||||||
|
HashMap<ChunkPosition, TileEntity> toRemove = null;
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<ChunkPosition, TileEntity> tile = iterator.next();
|
||||||
|
ChunkPosition pos = tile.getKey();
|
||||||
|
int lx = pos.x & 15;
|
||||||
|
int ly = pos.y;
|
||||||
|
int lz = pos.z & 15;
|
||||||
|
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||||
|
char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||||
|
if (array[k] != 0) {
|
||||||
|
if (toRemove == null) {
|
||||||
|
toRemove = new HashMap<>();
|
||||||
|
}
|
||||||
|
toRemove.put(tile.getKey(), tile.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toRemove != null) {
|
||||||
|
for (Map.Entry<ChunkPosition, TileEntity> entry : toRemove.entrySet()) {
|
||||||
|
ChunkPosition bp = entry.getKey();
|
||||||
|
TileEntity tile = entry.getValue();
|
||||||
|
tiles.remove(bp);
|
||||||
|
tile.s();
|
||||||
|
nmsWorld.p(bp.x, bp.y, bp.z);
|
||||||
|
tile.u();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
HashSet<UUID> entsToRemove = this.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 blocks
|
||||||
|
for (int j = 0; j < sections.length; j++) {
|
||||||
|
if (this.getCount(j) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
byte[] newIdArray = this.getByteIdArray(j);
|
||||||
|
if (newIdArray == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NibbleArray newDataArray = this.getDataArray(j);
|
||||||
|
ChunkSection section = sections[j];
|
||||||
|
if ((section == null) || (this.getCount(j) >= 4096)) {
|
||||||
|
sections[j] = section = new ChunkSection(j << 4, flag);
|
||||||
|
section.setIdArray(newIdArray);
|
||||||
|
if (newDataArray != null) {
|
||||||
|
section.setDataArray(newDataArray);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
byte[] currentIdArray = (byte[]) BukkitQueue17.fieldIds.get(section);
|
||||||
|
NibbleArray currentDataArray = (NibbleArray) BukkitQueue17.fieldData.get(section);
|
||||||
|
boolean data = currentDataArray != null && newDataArray != null;
|
||||||
|
if (!data) {
|
||||||
|
section.setDataArray(newDataArray);
|
||||||
|
}
|
||||||
|
if (currentIdArray == null) {
|
||||||
|
section.setIdArray(newIdArray);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
boolean fill = true;
|
||||||
|
int solid = 0;
|
||||||
|
char[] charArray = this.getIdArray(j);
|
||||||
|
for (int k = 0; k < newIdArray.length; k++) {
|
||||||
|
char combined = charArray[k];
|
||||||
|
switch (combined) {
|
||||||
|
case 0:
|
||||||
|
fill = false;
|
||||||
|
continue;
|
||||||
|
case 1:
|
||||||
|
fill = false;
|
||||||
|
if (currentIdArray[k] != 0) {
|
||||||
|
solid++;
|
||||||
|
}
|
||||||
|
currentIdArray[k] = 0;
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
solid++;
|
||||||
|
currentIdArray[k] = newIdArray[k];
|
||||||
|
if (data) {
|
||||||
|
int dataByte = FaweCache.getData(combined);
|
||||||
|
int x = FaweCache.CACHE_X[0][k];
|
||||||
|
int y = FaweCache.CACHE_Y[0][k];
|
||||||
|
int z = FaweCache.CACHE_Z[0][k];
|
||||||
|
int newData = newDataArray.a(x, y, z);
|
||||||
|
currentDataArray.a(x, y, z, newData);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getParent().setCount(0, solid, section);
|
||||||
|
if (fill) {
|
||||||
|
this.setCount(j, Short.MAX_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set biomes
|
||||||
|
int[][] biomes = this.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.m()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; // Biome array
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set tiles
|
||||||
|
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
|
||||||
|
int bx = this.getX() << 4;
|
||||||
|
int bz = this.getZ() << 4;
|
||||||
|
|
||||||
|
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||||
|
CompoundTag nativeTag = entry.getValue();
|
||||||
|
BytePair pair = entry.getKey();
|
||||||
|
TileEntity tileEntity = nmsWorld.getTileEntity(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz);
|
||||||
|
if (tileEntity != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) BukkitQueue17.methodFromNative.invoke(BukkitQueue17.adapter, nativeTag);
|
||||||
|
tileEntity.a(tag); // ReadTagIntoTile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
MainUtil.handleError(e);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe.bukkit.v1_7;
|
|||||||
|
|
||||||
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.object.FaweQueue;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
|
|
||||||
public class BukkitMain_17 extends ABukkitMain {
|
public class BukkitMain_17 extends ABukkitMain {
|
||||||
@ -10,4 +11,9 @@ public class BukkitMain_17 extends ABukkitMain {
|
|||||||
public BukkitQueue_0 getQueue(World world) {
|
public BukkitQueue_0 getQueue(World world) {
|
||||||
return new BukkitQueue17(world);
|
return new BukkitQueue17(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getQueue(String world) {
|
||||||
|
return new BukkitQueue17(world);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package com.boydti.fawe.bukkit.v1_7;
|
package com.boydti.fawe.bukkit.v1_7;
|
||||||
|
|
||||||
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.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
@ -12,19 +10,14 @@ import com.boydti.fawe.util.MathMan;
|
|||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.internal.Constants;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -59,18 +52,26 @@ import org.bukkit.WorldCreator;
|
|||||||
import org.bukkit.craftbukkit.v1_7_R4.CraftChunk;
|
import org.bukkit.craftbukkit.v1_7_R4.CraftChunk;
|
||||||
import org.bukkit.craftbukkit.v1_7_R4.CraftServer;
|
import org.bukkit.craftbukkit.v1_7_R4.CraftServer;
|
||||||
import org.bukkit.craftbukkit.v1_7_R4.CraftWorld;
|
import org.bukkit.craftbukkit.v1_7_R4.CraftWorld;
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
import org.bukkit.event.world.WorldInitEvent;
|
import org.bukkit.event.world.WorldInitEvent;
|
||||||
import org.bukkit.event.world.WorldLoadEvent;
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
|
||||||
public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
|
public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
|
||||||
|
|
||||||
private static Field fieldData;
|
protected static Field fieldData;
|
||||||
private static Field fieldIds;
|
protected static Field fieldIds;
|
||||||
|
|
||||||
public BukkitQueue17(final com.sk89q.worldedit.world.World world) {
|
public BukkitQueue17(final com.sk89q.worldedit.world.World world) {
|
||||||
super(world);
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BukkitQueue17(final String world) {
|
||||||
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
checkVersion("v1_7_R4");
|
checkVersion("v1_7_R4");
|
||||||
if (fieldData == null) {
|
if (fieldData == null) {
|
||||||
try {
|
try {
|
||||||
@ -236,230 +237,6 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
|
|||||||
return world.getChunkAt(x, z);
|
return world.getChunkAt(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
|
||||||
BukkitChunk_1_7 fs = (BukkitChunk_1_7) fc;
|
|
||||||
CraftChunk chunk = (CraftChunk) fs.getChunk();
|
|
||||||
net.minecraft.server.v1_7_R4.Chunk nmsChunk = chunk.getHandle();
|
|
||||||
nmsChunk.e(); // Modified
|
|
||||||
nmsChunk.mustSave = true;
|
|
||||||
net.minecraft.server.v1_7_R4.World nmsWorld = nmsChunk.world;
|
|
||||||
try {
|
|
||||||
final boolean flag = getWorld().getEnvironment() == World.Environment.NORMAL;
|
|
||||||
// Sections
|
|
||||||
ChunkSection[] sections = nmsChunk.getSections();
|
|
||||||
Map<ChunkPosition, TileEntity> tiles = nmsChunk.tileEntities;
|
|
||||||
Collection<net.minecraft.server.v1_7_R4.Entity>[] entities = nmsChunk.entitySlices;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 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
|
|
||||||
Iterator<Map.Entry<ChunkPosition, TileEntity>> iterator = tiles.entrySet().iterator();
|
|
||||||
HashMap<ChunkPosition, TileEntity> toRemove = null;
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Map.Entry<ChunkPosition, TileEntity> tile = iterator.next();
|
|
||||||
ChunkPosition pos = tile.getKey();
|
|
||||||
int lx = pos.x & 15;
|
|
||||||
int ly = pos.y;
|
|
||||||
int lz = pos.z & 15;
|
|
||||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
|
||||||
char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
|
||||||
if (array[k] != 0) {
|
|
||||||
if (toRemove == null) {
|
|
||||||
toRemove = new HashMap<>();
|
|
||||||
}
|
|
||||||
toRemove.put(tile.getKey(), tile.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (toRemove != null) {
|
|
||||||
for (Map.Entry<ChunkPosition, TileEntity> entry : toRemove.entrySet()) {
|
|
||||||
ChunkPosition bp = entry.getKey();
|
|
||||||
TileEntity tile = entry.getValue();
|
|
||||||
tiles.remove(bp);
|
|
||||||
tile.s();
|
|
||||||
nmsWorld.p(bp.x, bp.y, bp.z);
|
|
||||||
tile.u();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
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 blocks
|
|
||||||
for (int j = 0; j < sections.length; j++) {
|
|
||||||
if (fs.getCount(j) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
byte[] newIdArray = fs.getByteIdArray(j);
|
|
||||||
if (newIdArray == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
NibbleArray newDataArray = fs.getDataArray(j);
|
|
||||||
ChunkSection section = sections[j];
|
|
||||||
if ((section == null) || (fs.getCount(j) >= 4096)) {
|
|
||||||
sections[j] = section = new ChunkSection(j << 4, flag);
|
|
||||||
section.setIdArray(newIdArray);
|
|
||||||
if (newDataArray != null) {
|
|
||||||
section.setDataArray(newDataArray);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
byte[] currentIdArray = (byte[]) fieldIds.get(section);
|
|
||||||
NibbleArray currentDataArray = (NibbleArray) fieldData.get(section);
|
|
||||||
boolean data = currentDataArray != null && newDataArray != null;
|
|
||||||
if (!data) {
|
|
||||||
section.setDataArray(newDataArray);
|
|
||||||
}
|
|
||||||
if (currentIdArray == null) {
|
|
||||||
section.setIdArray(newIdArray);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
boolean fill = true;
|
|
||||||
int solid = 0;
|
|
||||||
char[] charArray = fs.getIdArray(j);
|
|
||||||
for (int k = 0; k < newIdArray.length; k++) {
|
|
||||||
char combined = charArray[k];
|
|
||||||
switch (combined) {
|
|
||||||
case 0:
|
|
||||||
fill = false;
|
|
||||||
continue;
|
|
||||||
case 1:
|
|
||||||
fill = false;
|
|
||||||
if (currentIdArray[k] != 0) {
|
|
||||||
solid++;
|
|
||||||
}
|
|
||||||
currentIdArray[k] = 0;
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
solid++;
|
|
||||||
currentIdArray[k] = newIdArray[k];
|
|
||||||
if (data) {
|
|
||||||
int dataByte = FaweCache.getData(combined);
|
|
||||||
int x = FaweCache.CACHE_X[0][k];
|
|
||||||
int y = FaweCache.CACHE_Y[0][k];
|
|
||||||
int z = FaweCache.CACHE_Z[0][k];
|
|
||||||
int newData = newDataArray.a(x, y, z);
|
|
||||||
currentDataArray.a(x, y, z, newData);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCount(0, solid, section);
|
|
||||||
if (fill) {
|
|
||||||
fs.setCount(j, Short.MAX_VALUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.m()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome; // Biome array
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 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();
|
|
||||||
TileEntity tileEntity = nmsWorld.getTileEntity(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz);
|
|
||||||
if (tileEntity != null) {
|
|
||||||
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(adapter, nativeTag);
|
|
||||||
tileEntity.a(tag); // ReadTagIntoTile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
|
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
|
||||||
Class<? extends ChunkSection> clazz = section.getClass();
|
Class<? extends ChunkSection> clazz = section.getClass();
|
||||||
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
|
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
|
||||||
@ -625,7 +402,7 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
|
|||||||
nmsWorld.t(x, y, z);
|
nmsWorld.t(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorldServer nmsWorld;
|
protected WorldServer nmsWorld;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World getImpWorld() {
|
public World getImpWorld() {
|
||||||
|
@ -1,11 +1,39 @@
|
|||||||
package com.boydti.fawe.bukkit.v1_8;
|
package com.boydti.fawe.bukkit.v1_8;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.FaweCache;
|
||||||
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.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.ListTag;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
import com.sk89q.worldedit.internal.Constants;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import net.minecraft.server.v1_8_R3.BlockPosition;
|
||||||
|
import net.minecraft.server.v1_8_R3.ChunkSection;
|
||||||
|
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.NBTTagCompound;
|
||||||
|
import net.minecraft.server.v1_8_R3.TileEntity;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
|
||||||
public class BukkitChunk_1_8 extends CharFaweChunk<Chunk> {
|
public class BukkitChunk_1_8 extends CharFaweChunk<Chunk, BukkitQueue18R3> {
|
||||||
/**
|
/**
|
||||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||||
*
|
*
|
||||||
@ -21,4 +49,208 @@ public class BukkitChunk_1_8 extends CharFaweChunk<Chunk> {
|
|||||||
public Chunk getNewChunk() {
|
public Chunk getNewChunk() {
|
||||||
return Bukkit.getWorld(getParent().getWorldName()).getChunkAt(getX(), getZ());
|
return Bukkit.getWorld(getParent().getWorldName()).getChunkAt(getX(), getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
getChunk().load(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweChunk call() {
|
||||||
|
CraftChunk chunk = (CraftChunk) this.getChunk();
|
||||||
|
net.minecraft.server.v1_8_R3.Chunk nmsChunk = chunk.getHandle();
|
||||||
|
nmsChunk.f(true); // Modified
|
||||||
|
nmsChunk.mustSave = true;
|
||||||
|
net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld();
|
||||||
|
try {
|
||||||
|
final boolean flag = getParent().getWorld().getEnvironment() == World.Environment.NORMAL;
|
||||||
|
// Sections
|
||||||
|
ChunkSection[] sections = nmsChunk.getSections();
|
||||||
|
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
||||||
|
Collection<Entity>[] entities = nmsChunk.getEntitySlices();
|
||||||
|
|
||||||
|
// Remove entities
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
int count = this.getCount(i);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
entities[i].clear();
|
||||||
|
} else {
|
||||||
|
char[] array = this.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;
|
||||||
|
}
|
||||||
|
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set entities
|
||||||
|
Set<UUID> createdEntities = new HashSet<>();
|
||||||
|
Set<CompoundTag> entitiesToSpawn = this.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)BukkitQueue18R3.methodFromNative.invoke(BukkitQueue18R3.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 (getParent().getChangeTask() != null) {
|
||||||
|
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||||
|
getParent().getChangeTask().run(previous, this);
|
||||||
|
}
|
||||||
|
// Trim tiles
|
||||||
|
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
|
||||||
|
HashMap<BlockPosition, TileEntity> toRemove = null;
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<BlockPosition, TileEntity> tile = iterator.next();
|
||||||
|
BlockPosition pos = tile.getKey();
|
||||||
|
int lx = pos.getX() & 15;
|
||||||
|
int ly = pos.getY();
|
||||||
|
int lz = pos.getZ() & 15;
|
||||||
|
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||||
|
char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||||
|
if (array[k] != 0) {
|
||||||
|
if (toRemove == null) {
|
||||||
|
toRemove = new HashMap<>();
|
||||||
|
}
|
||||||
|
toRemove.put(tile.getKey(), tile.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toRemove != null) {
|
||||||
|
for (Map.Entry<BlockPosition, TileEntity> entry : toRemove.entrySet()) {
|
||||||
|
BlockPosition bp = entry.getKey();
|
||||||
|
TileEntity tile = entry.getValue();
|
||||||
|
tiles.remove(bp);
|
||||||
|
tile.y();
|
||||||
|
nmsWorld.t(bp);
|
||||||
|
tile.E();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
HashSet<UUID> entsToRemove = this.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 blocks
|
||||||
|
for (int j = 0; j < sections.length; j++) {
|
||||||
|
if (this.getCount(j) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char[] newArray = this.getIdArray(j);
|
||||||
|
if (newArray == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ChunkSection section = sections[j];
|
||||||
|
if (section != null && BukkitQueue18R3.isDirty != null) {
|
||||||
|
BukkitQueue18R3.isDirty.set(section, true);
|
||||||
|
}
|
||||||
|
if ((section == null) || (this.getCount(j) >= 4096)) {
|
||||||
|
section = new ChunkSection(j << 4, flag, newArray);
|
||||||
|
sections[j] = section;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char[] currentArray = section.getIdArray();
|
||||||
|
int solid = 0;
|
||||||
|
for (int k = 0; k < newArray.length; k++) {
|
||||||
|
char n = newArray[k];
|
||||||
|
switch (n) {
|
||||||
|
case 0:
|
||||||
|
continue;
|
||||||
|
case 1:
|
||||||
|
if (currentArray[k] > 1) {
|
||||||
|
solid++;
|
||||||
|
currentArray[k] = 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
solid++;
|
||||||
|
currentArray[k] = n;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getParent().setCount(0, solid, section);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set biomes
|
||||||
|
int[][] biomes = this.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 = this.getTiles();
|
||||||
|
int bx = this.getX() << 4;
|
||||||
|
int bz = this.getZ() << 4;
|
||||||
|
|
||||||
|
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||||
|
CompoundTag nativeTag = entry.getValue();
|
||||||
|
BytePair pair = entry.getKey();
|
||||||
|
BlockPosition pos = new BlockPosition(pair.get0x() + bx, pair.get1() & 0xFF, pair.get0y() + bz); // Set pos
|
||||||
|
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||||
|
if (tileEntity != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) BukkitQueue18R3.methodFromNative.invoke(BukkitQueue18R3.adapter, nativeTag);
|
||||||
|
tileEntity.a(tag); // ReadTagIntoTile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
MainUtil.handleError(e);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ 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.object.FaweQueue;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
|
|
||||||
public class BukkitMain_18 extends ABukkitMain {
|
public class BukkitMain_18 extends ABukkitMain {
|
||||||
@ -10,4 +11,9 @@ public class BukkitMain_18 extends ABukkitMain {
|
|||||||
public BukkitQueue_0 getQueue(World world) {
|
public BukkitQueue_0 getQueue(World world) {
|
||||||
return new BukkitQueue18R3(world);
|
return new BukkitQueue18R3(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getQueue(String world) {
|
||||||
|
return new BukkitQueue18R3(world);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ 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.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
@ -12,20 +11,14 @@ import com.boydti.fawe.util.MathMan;
|
|||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||||
import com.sk89q.worldedit.internal.Constants;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -60,7 +53,6 @@ import org.bukkit.WorldCreator;
|
|||||||
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
||||||
import org.bukkit.craftbukkit.v1_8_R3.CraftServer;
|
import org.bukkit.craftbukkit.v1_8_R3.CraftServer;
|
||||||
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
|
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
import org.bukkit.event.world.WorldInitEvent;
|
import org.bukkit.event.world.WorldInitEvent;
|
||||||
import org.bukkit.event.world.WorldLoadEvent;
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
@ -74,6 +66,11 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
|
|||||||
checkVersion("v1_8_R3");
|
checkVersion("v1_8_R3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BukkitQueue18R3(final String world) {
|
||||||
|
super(world);
|
||||||
|
checkVersion("v1_8_R3");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setupAdapter(BukkitImplAdapter adapter) {
|
public void setupAdapter(BukkitImplAdapter adapter) {
|
||||||
if (this.adapter == null) {
|
if (this.adapter == null) {
|
||||||
@ -235,206 +232,6 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
|
|||||||
return world.getChunkAt(x, z);
|
return world.getChunkAt(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@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();
|
|
||||||
nmsChunk.f(true); // Modified
|
|
||||||
nmsChunk.mustSave = true;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 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
|
|
||||||
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
|
|
||||||
HashMap<BlockPosition, TileEntity> toRemove = null;
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Map.Entry<BlockPosition, TileEntity> tile = iterator.next();
|
|
||||||
BlockPosition pos = tile.getKey();
|
|
||||||
int lx = pos.getX() & 15;
|
|
||||||
int ly = pos.getY();
|
|
||||||
int lz = pos.getZ() & 15;
|
|
||||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
|
||||||
char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
|
||||||
if (array[k] != 0) {
|
|
||||||
if (toRemove == null) {
|
|
||||||
toRemove = new HashMap<>();
|
|
||||||
}
|
|
||||||
toRemove.put(tile.getKey(), tile.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (toRemove != null) {
|
|
||||||
for (Map.Entry<BlockPosition, TileEntity> entry : toRemove.entrySet()) {
|
|
||||||
BlockPosition bp = entry.getKey();
|
|
||||||
TileEntity tile = entry.getValue();
|
|
||||||
tiles.remove(bp);
|
|
||||||
tile.y();
|
|
||||||
nmsWorld.t(bp);
|
|
||||||
tile.E();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
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 blocks
|
|
||||||
for (int j = 0; j < sections.length; j++) {
|
|
||||||
if (fs.getCount(j) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
char[] newArray = fs.getIdArray(j);
|
|
||||||
if (newArray == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ChunkSection section = sections[j];
|
|
||||||
if (section != null && isDirty != null) {
|
|
||||||
isDirty.set(section, true);
|
|
||||||
}
|
|
||||||
if ((section == null) || (fs.getCount(j) >= 4096)) {
|
|
||||||
section = new ChunkSection(j << 4, flag, newArray);
|
|
||||||
sections[j] = section;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
char[] currentArray = section.getIdArray();
|
|
||||||
int solid = 0;
|
|
||||||
for (int k = 0; k < newArray.length; k++) {
|
|
||||||
char n = newArray[k];
|
|
||||||
switch (n) {
|
|
||||||
case 0:
|
|
||||||
continue;
|
|
||||||
case 1:
|
|
||||||
if (currentArray[k] > 1) {
|
|
||||||
solid++;
|
|
||||||
currentArray[k] = 0;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
solid++;
|
|
||||||
currentArray[k] = n;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCount(0, solid, section);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(pair.get0x() + bx, pair.get1() & 0xFF, pair.get0y() + 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) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
|
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
|
||||||
Class<? extends ChunkSection> clazz = section.getClass();
|
Class<? extends ChunkSection> clazz = section.getClass();
|
||||||
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
|
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
|
||||||
|
@ -1,20 +1,51 @@
|
|||||||
package com.boydti.fawe.bukkit.v1_9;
|
package com.boydti.fawe.bukkit.v1_9;
|
||||||
|
|
||||||
|
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.object.BytePair;
|
||||||
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.boydti.fawe.util.MathMan;
|
||||||
|
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.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import net.minecraft.server.v1_9_R2.Block;
|
import net.minecraft.server.v1_9_R2.Block;
|
||||||
|
import net.minecraft.server.v1_9_R2.BlockPosition;
|
||||||
|
import net.minecraft.server.v1_9_R2.Blocks;
|
||||||
|
import net.minecraft.server.v1_9_R2.ChunkSection;
|
||||||
import net.minecraft.server.v1_9_R2.DataBits;
|
import net.minecraft.server.v1_9_R2.DataBits;
|
||||||
import net.minecraft.server.v1_9_R2.DataPalette;
|
import net.minecraft.server.v1_9_R2.DataPalette;
|
||||||
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
|
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
|
||||||
import net.minecraft.server.v1_9_R2.DataPaletteGlobal;
|
import net.minecraft.server.v1_9_R2.DataPaletteGlobal;
|
||||||
|
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.IBlockData;
|
||||||
|
import net.minecraft.server.v1_9_R2.NBTTagCompound;
|
||||||
|
import net.minecraft.server.v1_9_R2.TileEntity;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Biome;
|
||||||
|
import org.bukkit.craftbukkit.v1_9_R2.CraftChunk;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
|
||||||
public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
|
public class BukkitChunk_1_9 extends CharFaweChunk<Chunk, BukkitQueue_1_9_R1> {
|
||||||
|
|
||||||
public DataPaletteBlock[] sectionPalettes;
|
public DataPaletteBlock[] sectionPalettes;
|
||||||
|
|
||||||
@ -35,7 +66,7 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
public BukkitChunk_1_9 copy(boolean shallow) {
|
||||||
BukkitChunk_1_9 value = (BukkitChunk_1_9) super.copy(shallow);
|
BukkitChunk_1_9 value = (BukkitChunk_1_9) super.copy(shallow);
|
||||||
if (sectionPalettes != null) {
|
if (sectionPalettes != null) {
|
||||||
value.sectionPalettes = new DataPaletteBlock[16];
|
value.sectionPalettes = new DataPaletteBlock[16];
|
||||||
@ -125,4 +156,252 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
getChunk().load(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweChunk call() {
|
||||||
|
final Chunk chunk = (Chunk) this.getChunk();
|
||||||
|
final World world = chunk.getWorld();
|
||||||
|
try {
|
||||||
|
final boolean flag = world.getEnvironment() == World.Environment.NORMAL;
|
||||||
|
net.minecraft.server.v1_9_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
||||||
|
nmsChunk.f(true); // Modified
|
||||||
|
nmsChunk.mustSave = true;
|
||||||
|
net.minecraft.server.v1_9_R2.World nmsWorld = nmsChunk.world;
|
||||||
|
ChunkSection[] sections = nmsChunk.getSections();
|
||||||
|
Class<? extends net.minecraft.server.v1_9_R2.Chunk> clazzChunk = nmsChunk.getClass();
|
||||||
|
final Field ef = clazzChunk.getDeclaredField("entitySlices");
|
||||||
|
final Collection<Entity>[] entities = (Collection<Entity>[]) ef.get(nmsChunk);
|
||||||
|
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
||||||
|
// Remove entities
|
||||||
|
for (int i = 0; i < entities.length; i++) {
|
||||||
|
int count = this.getCount(i);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
entities[i].clear();
|
||||||
|
} else {
|
||||||
|
char[] array = this.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 || y < 0 || y > 255) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HashSet<UUID> entsToRemove = this.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 = this.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) BukkitQueue_1_9_R1.methodFromNative.invoke(BukkitQueue_1_9_R1.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 (getParent().getChangeTask() != null) {
|
||||||
|
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||||
|
getParent().getChangeTask().run(previous, this);
|
||||||
|
}
|
||||||
|
// Trim tiles
|
||||||
|
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
|
||||||
|
HashMap<BlockPosition, TileEntity> toRemove = null;
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<BlockPosition, TileEntity> tile = iterator.next();
|
||||||
|
BlockPosition pos = tile.getKey();
|
||||||
|
int lx = pos.getX() & 15;
|
||||||
|
int ly = pos.getY();
|
||||||
|
int lz = pos.getZ() & 15;
|
||||||
|
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||||
|
char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||||
|
if (array[k] != 0) {
|
||||||
|
if (toRemove == null) {
|
||||||
|
toRemove = new HashMap<>();
|
||||||
|
}
|
||||||
|
toRemove.put(tile.getKey(), tile.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toRemove != null) {
|
||||||
|
for (Map.Entry<BlockPosition, TileEntity> entry : toRemove.entrySet()) {
|
||||||
|
BlockPosition bp = entry.getKey();
|
||||||
|
TileEntity tile = entry.getValue();
|
||||||
|
tiles.remove(bp);
|
||||||
|
tile.y();
|
||||||
|
nmsWorld.s(bp);
|
||||||
|
tile.invalidateBlockCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Set blocks
|
||||||
|
for (int j = 0; j < sections.length; j++) {
|
||||||
|
int count = this.getCount(j);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ChunkSection section = sections[j];
|
||||||
|
if (section == null) {
|
||||||
|
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||||
|
section = sections[j] = getParent().newChunkSection(j << 4, flag, null);
|
||||||
|
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||||
|
getParent().setCount(0, count - this.getAir(j), section);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sections[j] = getParent().newChunkSection(j << 4, flag, array);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||||
|
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||||
|
getParent().setCount(0, count - this.getAir(j), section);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sections[j] = getParent().newChunkSection(j << 4, flag, array);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DataPaletteBlock nibble = section.getBlocks();
|
||||||
|
Field fieldBits = nibble.getClass().getDeclaredField("b");
|
||||||
|
fieldBits.setAccessible(true);
|
||||||
|
DataBits bits = (DataBits) fieldBits.get(nibble);
|
||||||
|
|
||||||
|
Field fieldPalette = nibble.getClass().getDeclaredField("c");
|
||||||
|
fieldPalette.setAccessible(true);
|
||||||
|
DataPalette palette = (DataPalette) fieldPalette.get(nibble);
|
||||||
|
int nonEmptyBlockCount = 0;
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
|
||||||
|
switch (combinedId) {
|
||||||
|
case 0:
|
||||||
|
IBlockData existing = nibble.a(x, y, z);
|
||||||
|
if (existing != BukkitQueue_1_9_R1.air) {
|
||||||
|
nonEmptyBlockCount++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case 1:
|
||||||
|
nibble.setBlock(x, y, z, Blocks.AIR.getBlockData());
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
nonEmptyBlockCount++;
|
||||||
|
nibble.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getParent().setCount(0, nonEmptyBlockCount, section);
|
||||||
|
}
|
||||||
|
// Set biomes
|
||||||
|
int[][] biomes = this.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 = this.getTiles();
|
||||||
|
int bx = this.getX() << 4;
|
||||||
|
int bz = this.getZ() << 4;
|
||||||
|
|
||||||
|
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||||
|
CompoundTag nativeTag = entry.getValue();
|
||||||
|
BytePair pair = entry.getKey();
|
||||||
|
BlockPosition pos = new BlockPosition(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos
|
||||||
|
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||||
|
if (tileEntity != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_9_R1.methodFromNative.invoke(BukkitQueue_1_9_R1.adapter, nativeTag);
|
||||||
|
tileEntity.a(tag); // ReadTagIntoTile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
MainUtil.handleError(e);
|
||||||
|
}
|
||||||
|
final int[][] biomes = this.getBiomeArray();
|
||||||
|
final Biome[] values = Biome.values();
|
||||||
|
if (biomes != null) {
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
final int[] array = biomes[x];
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
final int biome = array[z];
|
||||||
|
if (biome == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
chunk.getBlock(x, 0, z).setBiome(values[biome]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ 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.object.FaweQueue;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
|
|
||||||
public class BukkitMain_19 extends ABukkitMain {
|
public class BukkitMain_19 extends ABukkitMain {
|
||||||
@ -9,4 +10,9 @@ public class BukkitMain_19 extends ABukkitMain {
|
|||||||
public BukkitQueue_0 getQueue(World world) {
|
public BukkitQueue_0 getQueue(World world) {
|
||||||
return new BukkitQueue_1_9_R1(world);
|
return new BukkitQueue_1_9_R1(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getQueue(String world) {
|
||||||
|
return new BukkitQueue_1_9_R1(world);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ 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.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
@ -12,32 +11,22 @@ import com.boydti.fawe.util.MathMan;
|
|||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.LongTag;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.internal.Constants;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.minecraft.server.v1_9_R2.Block;
|
import net.minecraft.server.v1_9_R2.Block;
|
||||||
import net.minecraft.server.v1_9_R2.BlockPosition;
|
import net.minecraft.server.v1_9_R2.BlockPosition;
|
||||||
import net.minecraft.server.v1_9_R2.Blocks;
|
|
||||||
import net.minecraft.server.v1_9_R2.ChunkSection;
|
import net.minecraft.server.v1_9_R2.ChunkSection;
|
||||||
import net.minecraft.server.v1_9_R2.DataBits;
|
import net.minecraft.server.v1_9_R2.DataBits;
|
||||||
import net.minecraft.server.v1_9_R2.DataPalette;
|
|
||||||
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
|
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
|
||||||
import net.minecraft.server.v1_9_R2.Entity;
|
import net.minecraft.server.v1_9_R2.Entity;
|
||||||
import net.minecraft.server.v1_9_R2.EntityPlayer;
|
import net.minecraft.server.v1_9_R2.EntityPlayer;
|
||||||
@ -63,24 +52,30 @@ import net.minecraft.server.v1_9_R2.WorldType;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.World.Environment;
|
|
||||||
import org.bukkit.WorldCreator;
|
import org.bukkit.WorldCreator;
|
||||||
import org.bukkit.block.Biome;
|
|
||||||
import org.bukkit.craftbukkit.v1_9_R2.CraftChunk;
|
import org.bukkit.craftbukkit.v1_9_R2.CraftChunk;
|
||||||
import org.bukkit.craftbukkit.v1_9_R2.CraftServer;
|
import org.bukkit.craftbukkit.v1_9_R2.CraftServer;
|
||||||
import org.bukkit.craftbukkit.v1_9_R2.CraftWorld;
|
import org.bukkit.craftbukkit.v1_9_R2.CraftWorld;
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
import org.bukkit.event.world.WorldInitEvent;
|
import org.bukkit.event.world.WorldInitEvent;
|
||||||
import org.bukkit.event.world.WorldLoadEvent;
|
import org.bukkit.event.world.WorldLoadEvent;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
|
||||||
public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
|
public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
|
||||||
|
|
||||||
private static IBlockData air;
|
protected static IBlockData air;
|
||||||
private static Field fieldBits;
|
protected static Field fieldBits;
|
||||||
|
|
||||||
public BukkitQueue_1_9_R1(final com.sk89q.worldedit.world.World world) {
|
public BukkitQueue_1_9_R1(final com.sk89q.worldedit.world.World world) {
|
||||||
super(world);
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BukkitQueue_1_9_R1(final String world) {
|
||||||
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
checkVersion("v1_9_R2");
|
checkVersion("v1_9_R2");
|
||||||
if (air == null) {
|
if (air == null) {
|
||||||
try {
|
try {
|
||||||
@ -287,7 +282,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
|
|||||||
nmsWorld.w(pos);
|
nmsWorld.w(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorldServer nmsWorld;
|
protected WorldServer nmsWorld;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World getImpWorld() {
|
public World getImpWorld() {
|
||||||
@ -442,7 +437,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
|
|||||||
return previous;
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||||
@ -468,251 +463,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
|
|||||||
return world.getChunkAt(x, z);
|
return world.getChunkAt(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 World world = chunk.getWorld();
|
|
||||||
chunk.load(true);
|
|
||||||
try {
|
|
||||||
final boolean flag = world.getEnvironment() == Environment.NORMAL;
|
|
||||||
net.minecraft.server.v1_9_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
|
||||||
nmsChunk.f(true); // Modified
|
|
||||||
nmsChunk.mustSave = true;
|
|
||||||
net.minecraft.server.v1_9_R2.World nmsWorld = nmsChunk.world;
|
|
||||||
ChunkSection[] sections = nmsChunk.getSections();
|
|
||||||
Class<? extends net.minecraft.server.v1_9_R2.Chunk> clazzChunk = nmsChunk.getClass();
|
|
||||||
final Field ef = clazzChunk.getDeclaredField("entitySlices");
|
|
||||||
final Collection<Entity>[] entities = (Collection<Entity>[]) ef.get(nmsChunk);
|
|
||||||
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
|
||||||
// Remove entities
|
|
||||||
for (int i = 0; i < entities.length; 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 || y < 0 || y > 255) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 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
|
|
||||||
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
|
|
||||||
HashMap<BlockPosition, TileEntity> toRemove = null;
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Map.Entry<BlockPosition, TileEntity> tile = iterator.next();
|
|
||||||
BlockPosition pos = tile.getKey();
|
|
||||||
int lx = pos.getX() & 15;
|
|
||||||
int ly = pos.getY();
|
|
||||||
int lz = pos.getZ() & 15;
|
|
||||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
|
||||||
char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
|
||||||
if (array[k] != 0) {
|
|
||||||
if (toRemove == null) {
|
|
||||||
toRemove = new HashMap<>();
|
|
||||||
}
|
|
||||||
toRemove.put(tile.getKey(), tile.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (toRemove != null) {
|
|
||||||
for (Entry<BlockPosition, TileEntity> entry : toRemove.entrySet()) {
|
|
||||||
BlockPosition bp = entry.getKey();
|
|
||||||
TileEntity tile = entry.getValue();
|
|
||||||
tiles.remove(bp);
|
|
||||||
tile.y();
|
|
||||||
nmsWorld.s(bp);
|
|
||||||
tile.invalidateBlockCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// Set blocks
|
|
||||||
for (int j = 0; j < sections.length; j++) {
|
|
||||||
int count = fs.getCount(j);
|
|
||||||
if (count == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ChunkSection section = sections[j];
|
|
||||||
if (section == null) {
|
|
||||||
if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) {
|
|
||||||
section = sections[j] = newChunkSection(j << 4, flag, null);
|
|
||||||
setPalette(section, fs.sectionPalettes[j]);
|
|
||||||
setCount(0, count - fs.getAir(j), section);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
sections[j] = newChunkSection(j << 4, flag, array);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if (count >= 4096) {
|
|
||||||
if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) {
|
|
||||||
setPalette(section, fs.sectionPalettes[j]);
|
|
||||||
setCount(0, count - fs.getAir(j), section);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
sections[j] = newChunkSection(j << 4, flag, array);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
DataPaletteBlock nibble = section.getBlocks();
|
|
||||||
Field fieldBits = nibble.getClass().getDeclaredField("b");
|
|
||||||
fieldBits.setAccessible(true);
|
|
||||||
DataBits bits = (DataBits) fieldBits.get(nibble);
|
|
||||||
|
|
||||||
Field fieldPalette = nibble.getClass().getDeclaredField("c");
|
|
||||||
fieldPalette.setAccessible(true);
|
|
||||||
DataPalette palette = (DataPalette) fieldPalette.get(nibble);
|
|
||||||
int nonEmptyBlockCount = 0;
|
|
||||||
for (int y = 0; y < 16; y++) {
|
|
||||||
for (int z = 0; z < 16; z++) {
|
|
||||||
for (int x = 0; x < 16; x++) {
|
|
||||||
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
|
|
||||||
switch (combinedId) {
|
|
||||||
case 0:
|
|
||||||
IBlockData existing = nibble.a(x, y, z);
|
|
||||||
if (existing != air) {
|
|
||||||
nonEmptyBlockCount++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
case 1:
|
|
||||||
nibble.setBlock(x, y, z, Blocks.AIR.getBlockData());
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
nonEmptyBlockCount++;
|
|
||||||
nibble.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCount(0, nonEmptyBlockCount, section);
|
|
||||||
}
|
|
||||||
// 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((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + 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) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
final int[][] biomes = fs.getBiomeArray();
|
|
||||||
final Biome[] values = Biome.values();
|
|
||||||
if (biomes != null) {
|
|
||||||
for (int x = 0; x < 16; x++) {
|
|
||||||
final int[] array = biomes[x];
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int z = 0; z < 16; z++) {
|
|
||||||
final int biome = array[z];
|
|
||||||
if (biome == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
chunk.getBlock(x, 0, z).setBiome(values[biome]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean unloadChunk(final String world, final Chunk chunk) {
|
public boolean unloadChunk(final String world, final Chunk chunk) {
|
||||||
net.minecraft.server.v1_9_R2.Chunk c = ((CraftChunk) chunk).getHandle();
|
net.minecraft.server.v1_9_R2.Chunk c = ((CraftChunk) chunk).getHandle();
|
||||||
@ -769,8 +519,8 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
|
|||||||
return MathMan.pair16(ibd.c(), ibd.d());
|
return MathMan.pair16(ibd.c(), ibd.d());
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataBits lastBits;
|
protected DataBits lastBits;
|
||||||
private DataPaletteBlock lastBlocks;
|
protected DataPaletteBlock lastBlocks;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void relightBlock(int x, int y, int z) {
|
public void relightBlock(int x, int y, int z) {
|
||||||
|
@ -435,7 +435,7 @@ public class Fawe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupMemoryListener() {
|
private void setupMemoryListener() {
|
||||||
if (Settings.MAX_MEMORY_PERCENT < 1) {
|
if (Settings.MAX_MEMORY_PERCENT < 1 || Settings.MAX_MEMORY_PERCENT > 99) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -98,9 +98,8 @@ public class FaweAPI {
|
|||||||
return FawePlayer.wrap(obj);
|
return FawePlayer.wrap(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static FaweQueue createQueue(String worldName, boolean autoqueue) {
|
public static FaweQueue createQueue(String worldName, boolean autoqueue) {
|
||||||
return SetQueue.IMP.getNewQueue(getWorld(worldName), true, autoqueue);
|
return SetQueue.IMP.getNewQueue(worldName, true, autoqueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +25,8 @@ public interface IFawe {
|
|||||||
|
|
||||||
public FaweQueue getNewQueue(World world, boolean fast);
|
public FaweQueue getNewQueue(World world, boolean fast);
|
||||||
|
|
||||||
|
public FaweQueue getNewQueue(String world, boolean fast);
|
||||||
|
|
||||||
public String getWorldName(World world);
|
public String getWorldName(World world);
|
||||||
|
|
||||||
public Collection<FaweMaskManager> getMaskManagers();
|
public Collection<FaweMaskManager> getMaskManagers();
|
||||||
|
@ -15,7 +15,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
public abstract class CharFaweChunk<T, V extends FaweQueue> extends FaweChunk<T> {
|
||||||
|
|
||||||
public char[][] ids;
|
public char[][] ids;
|
||||||
public short[] count;
|
public short[] count;
|
||||||
@ -47,6 +47,11 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
|||||||
this.relight = new short[HEIGHT >> 4];
|
this.relight = new short[HEIGHT >> 4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V getParent() {
|
||||||
|
return (V) super.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T getChunk() {
|
public T getChunk() {
|
||||||
if (this.chunk == null) {
|
if (this.chunk == null) {
|
||||||
@ -358,8 +363,8 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharFaweChunk<T> copy(boolean shallow) {
|
public CharFaweChunk<T, V> copy(boolean shallow) {
|
||||||
CharFaweChunk<T> copy = (CharFaweChunk<T>) getParent().getFaweChunk(getX(), getZ());
|
CharFaweChunk<T, V> copy = (CharFaweChunk<T, V>) getParent().getFaweChunk(getX(), getZ());
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
copy.ids = ids;
|
copy.ids = ids;
|
||||||
copy.air = air;
|
copy.air = air;
|
||||||
|
@ -3,12 +3,13 @@ package com.boydti.fawe.example;
|
|||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
|
|
||||||
public class DefaultFaweQueueMap implements IFaweQueueMap {
|
public class DefaultFaweQueueMap implements IFaweQueueMap {
|
||||||
|
|
||||||
@ -21,26 +22,25 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
|
|||||||
/**
|
/**
|
||||||
* Map of chunks in the queue
|
* Map of chunks in the queue
|
||||||
*/
|
*/
|
||||||
public ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<>(8, 0.9f, 1);
|
public ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<Long, FaweChunk>(8, 0.9f, 1) {
|
||||||
public ConcurrentLinkedDeque<FaweChunk> chunks = new ConcurrentLinkedDeque<FaweChunk>() {
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(FaweChunk o) {
|
public FaweChunk put(Long key, FaweChunk value) {
|
||||||
if (parent.getProgressTask() != null) {
|
if (parent.getProgressTask() != null) {
|
||||||
parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1);
|
parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1);
|
||||||
}
|
}
|
||||||
return super.add(o);
|
return super.put(key, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<FaweChunk> getFaweCunks() {
|
public Collection<FaweChunk> getFaweCunks() {
|
||||||
return new HashSet<>(chunks);
|
return new HashSet<>(blocks.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void forEachChunk(RunnableVal<FaweChunk> onEach) {
|
public void forEachChunk(RunnableVal<FaweChunk> onEach) {
|
||||||
for (FaweChunk chunk : chunks) {
|
for (Map.Entry<Long, FaweChunk> entry : blocks.entrySet()) {
|
||||||
onEach.run(chunk);
|
onEach.run(entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,6 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
|
|||||||
return previous;
|
return previous;
|
||||||
}
|
}
|
||||||
this.blocks.put(pair, chunk);
|
this.blocks.put(pair, chunk);
|
||||||
chunks.add(chunk);
|
|
||||||
}
|
}
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
@ -77,9 +76,7 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
|
|||||||
public void add(FaweChunk chunk) {
|
public void add(FaweChunk chunk) {
|
||||||
long pair = MathMan.pairInt(chunk.getX(), chunk.getZ());
|
long pair = MathMan.pairInt(chunk.getX(), chunk.getZ());
|
||||||
FaweChunk previous = this.blocks.put(pair, chunk);
|
FaweChunk previous = this.blocks.put(pair, chunk);
|
||||||
if (previous == null) {
|
if (previous != null) {
|
||||||
chunks.add(chunk);
|
|
||||||
} else {
|
|
||||||
blocks.put(pair, previous);
|
blocks.put(pair, previous);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,12 +85,11 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
|
|||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
blocks.clear();
|
blocks.clear();
|
||||||
chunks.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return chunks.size();
|
return blocks.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private FaweChunk getNewFaweChunk(int cx, int cz) {
|
private FaweChunk getNewFaweChunk(int cx, int cz) {
|
||||||
@ -105,24 +101,59 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
|
|||||||
private int lastZ = Integer.MIN_VALUE;
|
private int lastZ = Integer.MIN_VALUE;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean next() {
|
public boolean next(int amount, ExecutorCompletionService pool, long time) {
|
||||||
|
lastWrappedChunk = null;
|
||||||
lastX = Integer.MIN_VALUE;
|
lastX = Integer.MIN_VALUE;
|
||||||
lastZ = Integer.MIN_VALUE;
|
lastZ = Integer.MIN_VALUE;
|
||||||
try {
|
try {
|
||||||
if (this.blocks.isEmpty()) {
|
int added = 0;
|
||||||
return false;
|
Iterator<Map.Entry<Long, FaweChunk>> iter = blocks.entrySet().iterator();
|
||||||
|
if (amount == 1) {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
do {
|
||||||
|
if (iter.hasNext()) {
|
||||||
|
FaweChunk chunk = iter.next().getValue();
|
||||||
|
iter.remove();
|
||||||
|
parent.start(chunk);
|
||||||
|
chunk.call();
|
||||||
|
parent.end(chunk);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (System.currentTimeMillis() - start < time);
|
||||||
|
return !blocks.isEmpty();
|
||||||
}
|
}
|
||||||
synchronized (blocks) {
|
boolean result = true;
|
||||||
FaweChunk chunk = chunks.poll();
|
for (int i = 0; i < amount && (result = iter.hasNext()); i++, added++) {
|
||||||
if (chunk != null) {
|
Map.Entry<Long, FaweChunk> item = iter.next();
|
||||||
blocks.remove(chunk.longHash());
|
FaweChunk chunk = item.getValue();
|
||||||
parent.execute(chunk);
|
parent.start(chunk);
|
||||||
return true;
|
pool.submit(chunk);
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
if (result) {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
while (System.currentTimeMillis() - start < time) {
|
||||||
|
for (int i = 0; i < amount && (iter.hasNext()); i++, added++) {
|
||||||
|
Map.Entry<Long, FaweChunk> item = iter.next();
|
||||||
|
FaweChunk chunk = item.getValue();
|
||||||
|
parent.start(chunk);
|
||||||
|
pool.submit(chunk);
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < amount; i++, added--) {
|
||||||
|
FaweChunk fc = ((FaweChunk) pool.take().get());
|
||||||
|
parent.end(fc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < added; i++) {
|
||||||
|
FaweChunk fc = ((FaweChunk) pool.take().get());
|
||||||
|
parent.end(fc);
|
||||||
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
MainUtil.handleError(e);
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return false;
|
return !blocks.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.boydti.fawe.example;
|
|||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
|
|
||||||
public interface IFaweQueueMap {
|
public interface IFaweQueueMap {
|
||||||
|
|
||||||
@ -20,5 +21,5 @@ public interface IFaweQueueMap {
|
|||||||
|
|
||||||
int size();
|
int size();
|
||||||
|
|
||||||
boolean next();
|
boolean next(int size, ExecutorCompletionService dispatcher, long time);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||||
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
import java.util.concurrent.ForkJoinPool;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -36,6 +37,11 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
this(world, null);
|
this(world, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MappedFaweQueue(final String world) {
|
||||||
|
super(world);
|
||||||
|
map = new DefaultFaweQueueMap(this);
|
||||||
|
}
|
||||||
|
|
||||||
public MappedFaweQueue(final World world, IFaweQueueMap map) {
|
public MappedFaweQueue(final World world, IFaweQueueMap map) {
|
||||||
super(world);
|
super(world);
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
@ -99,8 +105,6 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
|
|
||||||
public abstract boolean regenerateChunk(WORLD world, int x, int z);
|
public abstract boolean regenerateChunk(WORLD world, int x, int z);
|
||||||
|
|
||||||
public abstract boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract FaweChunk getFaweChunk(int x, int z);
|
public abstract FaweChunk getFaweChunk(int x, int z);
|
||||||
|
|
||||||
@ -192,10 +196,19 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean next() {
|
public boolean next(int amount, ExecutorCompletionService pool, long time) {
|
||||||
return map.next();
|
return map.next(amount, pool, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void start(FaweChunk chunk) {
|
||||||
|
chunk.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void end(FaweChunk chunk) {
|
||||||
|
chunk.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void runTasks() {
|
public void runTasks() {
|
||||||
if (getProgressTask() != null) {
|
if (getProgressTask() != null) {
|
||||||
getProgressTask().run(ProgressType.DONE, 1);
|
getProgressTask().run(ProgressType.DONE, 1);
|
||||||
@ -224,31 +237,6 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
|||||||
|
|
||||||
private int dispatched = 0;
|
private int dispatched = 0;
|
||||||
|
|
||||||
public boolean execute(final FaweChunk fc) {
|
|
||||||
if (fc == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Set blocks / entities / biome
|
|
||||||
if (getProgressTask() != null) {
|
|
||||||
getProgressTask().run(ProgressType.QUEUE, map.size());
|
|
||||||
getProgressTask().run(ProgressType.DISPATCH, ++dispatched);
|
|
||||||
}
|
|
||||||
if (getChangeTask() != null) {
|
|
||||||
if (!this.setComponents(fc, new RunnableVal<FaweChunk>() {
|
|
||||||
@Override
|
|
||||||
public void run(FaweChunk before) {
|
|
||||||
getChangeTask().run(before, fc);
|
|
||||||
}
|
|
||||||
})) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (!this.setComponents(fc, null)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
fc.executeNotifyTasks();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
map.clear();
|
map.clear();
|
||||||
|
@ -22,6 +22,12 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
|||||||
addRelightTask();
|
addRelightTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NMSMappedFaweQueue(String world) {
|
||||||
|
super(world);
|
||||||
|
this.maxY = 256;
|
||||||
|
addRelightTask();
|
||||||
|
}
|
||||||
|
|
||||||
public NMSMappedFaweQueue(World world, IFaweQueueMap map) {
|
public NMSMappedFaweQueue(World world, IFaweQueueMap map) {
|
||||||
super(world, map);
|
super(world, map);
|
||||||
this.maxY = world.getMaxY();
|
this.maxY = world.getMaxY();
|
||||||
@ -47,35 +53,32 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
|||||||
private NMSRelighter relighter;
|
private NMSRelighter relighter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(FaweChunk fc) {
|
public void end(FaweChunk chunk) {
|
||||||
if (super.execute(fc)) {
|
super.end(chunk);
|
||||||
sendChunk(fc);
|
if (Settings.LIGHTING.MODE == 0) {
|
||||||
if (Settings.LIGHTING.MODE == 0) {
|
return;
|
||||||
return true;
|
}
|
||||||
|
if (relighter == null) {
|
||||||
|
relighter = new NMSRelighter(this);
|
||||||
|
}
|
||||||
|
if (Settings.LIGHTING.MODE == 2) {
|
||||||
|
relighter.addChunk(chunk.getX(), chunk.getZ(), null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CharFaweChunk cfc = (CharFaweChunk) chunk;
|
||||||
|
boolean relight = false;
|
||||||
|
boolean[] fix = new boolean[(maxY + 1) >> 4];
|
||||||
|
boolean sky = hasSky();
|
||||||
|
for (int i = 0; i < cfc.ids.length; i++) {
|
||||||
|
if ((sky && ((cfc.getAir(i) & 4095) != 0 || (cfc.getCount(i) & 4095) != 0)) || cfc.getRelight(i) != 0) {
|
||||||
|
relight = true;
|
||||||
|
fix[i] = true;
|
||||||
}
|
}
|
||||||
if (relighter == null) {
|
}
|
||||||
relighter = new NMSRelighter(this);
|
if (relight) {
|
||||||
}
|
relighter.addChunk(chunk.getX(), chunk.getZ(), fix);
|
||||||
if (Settings.LIGHTING.MODE == 2) {
|
|
||||||
relighter.addChunk(fc.getX(), fc.getZ(), null);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
CharFaweChunk chunk = (CharFaweChunk) fc;
|
|
||||||
boolean relight = false;
|
|
||||||
boolean[] fix = new boolean[(maxY + 1) >> 4];
|
|
||||||
boolean sky = hasSky();
|
|
||||||
for (int i = 0; i < chunk.ids.length; i++) {
|
|
||||||
if ((sky && ((chunk.getAir(i) & 4095) != 0 || (chunk.getCount(i) & 4095) != 0)) || chunk.getRelight(i) != 0) {
|
|
||||||
relight = true;
|
|
||||||
fix[i] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (relight) {
|
|
||||||
relighter.addChunk(chunk.getX(), chunk.getZ(), fix);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
refreshChunk(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,4 +92,9 @@ public class NullFaweChunk extends FaweChunk<Void> {
|
|||||||
public FaweChunk<Void> copy(boolean shallow) {
|
public FaweChunk<Void> copy(boolean shallow) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweChunk call() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,4 +402,9 @@ public class MCAChunk extends FaweChunk<Void> {
|
|||||||
public Void getChunk() {
|
public Void getChunk() {
|
||||||
throw new UnsupportedOperationException("Not applicable for this");
|
throw new UnsupportedOperationException("Not applicable for this");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweChunk call() {
|
||||||
|
throw new UnsupportedOperationException("Not supported");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import com.boydti.fawe.example.CharFaweChunk;
|
|||||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
|
||||||
import com.boydti.fawe.object.RunnableVal4;
|
import com.boydti.fawe.object.RunnableVal4;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
@ -141,11 +140,6 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
|
|||||||
throw new UnsupportedOperationException("Not supported");
|
throw new UnsupportedOperationException("Not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
|
||||||
throw new UnsupportedOperationException("Not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharFaweChunk getPrevious(CharFaweChunk fs, FaweChunk sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception {
|
public CharFaweChunk getPrevious(CharFaweChunk fs, FaweChunk sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||||
throw new UnsupportedOperationException("Not supported");
|
throw new UnsupportedOperationException("Not supported");
|
||||||
|
@ -14,6 +14,7 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
|
|
||||||
public class MCAQueueMap implements IFaweQueueMap {
|
public class MCAQueueMap implements IFaweQueueMap {
|
||||||
|
|
||||||
@ -150,20 +151,26 @@ public class MCAQueueMap implements IFaweQueueMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean next() {
|
public boolean next(int size, ExecutorCompletionService dispatcher, long time) {
|
||||||
lastX = Integer.MIN_VALUE;
|
lastX = Integer.MIN_VALUE;
|
||||||
lastZ = Integer.MIN_VALUE;
|
lastZ = Integer.MIN_VALUE;
|
||||||
lastFileX = Integer.MIN_VALUE;
|
lastFileX = Integer.MIN_VALUE;
|
||||||
lastFileZ = Integer.MIN_VALUE;
|
lastFileZ = Integer.MIN_VALUE;
|
||||||
if (!mcaFileMap.isEmpty()) {
|
if (!mcaFileMap.isEmpty()) {
|
||||||
Iterator<Map.Entry<Long, MCAFile>> iter = mcaFileMap.entrySet().iterator();
|
Iterator<Map.Entry<Long, MCAFile>> iter = mcaFileMap.entrySet().iterator();
|
||||||
if (iter.hasNext()) {
|
boolean result;
|
||||||
MCAFile file = iter.next().getValue();
|
long start = System.currentTimeMillis();
|
||||||
iter.remove();
|
do {
|
||||||
file.flush();
|
if (result = iter.hasNext()) {
|
||||||
file.close();
|
MCAFile file = iter.next().getValue();
|
||||||
return true;
|
iter.remove();
|
||||||
}
|
file.flush();
|
||||||
|
file.close();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (System.currentTimeMillis() - start < time);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
if (isHybridQueue) {
|
if (isHybridQueue) {
|
||||||
boolean value = queue.next();
|
boolean value = queue.next();
|
||||||
|
@ -9,8 +9,9 @@ import java.util.ArrayDeque;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
public abstract class FaweChunk<T> {
|
public abstract class FaweChunk<T> implements Callable<FaweChunk> {
|
||||||
|
|
||||||
private FaweQueue parent;
|
private FaweQueue parent;
|
||||||
private int x,z;
|
private int x,z;
|
||||||
@ -267,4 +268,11 @@ public abstract class FaweChunk<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract FaweChunk<T> copy(boolean shallow);
|
public abstract FaweChunk<T> copy(boolean shallow);
|
||||||
|
|
||||||
|
public void start() {};
|
||||||
|
|
||||||
|
public void end() {};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract FaweChunk call();
|
||||||
}
|
}
|
||||||
|
@ -82,10 +82,7 @@ public abstract class FawePlayer<T> {
|
|||||||
Field fieldPlayer = actor.getClass().getDeclaredField("player");
|
Field fieldPlayer = actor.getClass().getDeclaredField("player");
|
||||||
fieldPlayer.setAccessible(true);
|
fieldPlayer.setAccessible(true);
|
||||||
return wrap(fieldPlayer.get(actor));
|
return wrap(fieldPlayer.get(actor));
|
||||||
} catch (Throwable e) {
|
} catch (Throwable ignore) {}
|
||||||
MainUtil.handleError(e);
|
|
||||||
return Fawe.imp().wrap(actor.getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (obj instanceof Actor) {
|
if (obj instanceof Actor) {
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package com.boydti.fawe.object;
|
package com.boydti.fawe.object;
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.FaweAPI;
|
||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.config.BBC;
|
import com.boydti.fawe.config.BBC;
|
||||||
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.object.exception.FaweException;
|
import com.boydti.fawe.object.exception.FaweException;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
@ -23,6 +25,7 @@ import java.util.HashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||||
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public abstract class FaweQueue {
|
public abstract class FaweQueue {
|
||||||
@ -34,6 +37,10 @@ public abstract class FaweQueue {
|
|||||||
private RunnableVal2<FaweChunk, FaweChunk> changeTask;
|
private RunnableVal2<FaweChunk, FaweChunk> changeTask;
|
||||||
private RunnableVal2<ProgressType, Integer> progressTask;
|
private RunnableVal2<ProgressType, Integer> progressTask;
|
||||||
|
|
||||||
|
public FaweQueue(String world) {
|
||||||
|
this.world = world;
|
||||||
|
}
|
||||||
|
|
||||||
public FaweQueue(World world) {
|
public FaweQueue(World world) {
|
||||||
this.weWorld = world;
|
this.weWorld = world;
|
||||||
this.world = Fawe.imp().getWorldName(world);
|
this.world = Fawe.imp().getWorldName(world);
|
||||||
@ -62,7 +69,7 @@ public abstract class FaweQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public World getWEWorld() {
|
public World getWEWorld() {
|
||||||
return weWorld;
|
return weWorld != null ? weWorld : (weWorld = FaweAPI.getWorld(world));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getWorldName() {
|
public String getWorldName() {
|
||||||
@ -226,11 +233,19 @@ public abstract class FaweQueue {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public boolean next() {
|
||||||
|
int amount = Settings.QUEUE.PARALLEL_THREADS;
|
||||||
|
ExecutorCompletionService service = SetQueue.IMP.getCompleterService();
|
||||||
|
long time = 20; // 30ms
|
||||||
|
return next(amount, service, time);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the FaweChunk and sets the requested blocks
|
* Gets the FaweChunk and sets the requested blocks
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public abstract boolean next();
|
public abstract boolean next(int amount, ExecutorCompletionService pool, long time);
|
||||||
|
|
||||||
public void saveMemory() {
|
public void saveMemory() {
|
||||||
MainUtil.sendAdmin(BBC.OOM.s());
|
MainUtil.sendAdmin(BBC.OOM.s());
|
||||||
@ -369,6 +384,8 @@ public abstract class FaweQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void runTasks();
|
||||||
|
|
||||||
public boolean enqueue() {
|
public boolean enqueue() {
|
||||||
return SetQueue.IMP.enqueue(this);
|
return SetQueue.IMP.enqueue(this);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.boydti.fawe.object.player;
|
||||||
|
|
||||||
|
public class DefaultFawePlayer {
|
||||||
|
}
|
@ -31,7 +31,7 @@ public class PlotSquaredFeature extends FaweMaskManager {
|
|||||||
try {
|
try {
|
||||||
// If it's going to fail, throw an error now rather than later
|
// If it's going to fail, throw an error now rather than later
|
||||||
QueueProvider provider = QueueProvider.of(FaweLocalBlockQueue.class, null);
|
QueueProvider provider = QueueProvider.of(FaweLocalBlockQueue.class, null);
|
||||||
GlobalBlockQueue.IMP.setProvider(provider);
|
GlobalBlockQueue.IMP = new GlobalBlockQueue(provider, 1);
|
||||||
HybridPlotManager.REGENERATIVE_CLEAR = false;
|
HybridPlotManager.REGENERATIVE_CLEAR = false;
|
||||||
Fawe.debug(" - QueueProvider: " + FaweLocalBlockQueue.class);
|
Fawe.debug(" - QueueProvider: " + FaweLocalBlockQueue.class);
|
||||||
Fawe.debug(" - HybridPlotManager.REGENERATIVE_CLEAR: " + HybridPlotManager.REGENERATIVE_CLEAR);
|
Fawe.debug(" - HybridPlotManager.REGENERATIVE_CLEAR: " + HybridPlotManager.REGENERATIVE_CLEAR);
|
||||||
|
@ -12,6 +12,7 @@ import java.util.Collection;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||||
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
|
|
||||||
public class DelegateFaweQueue extends FaweQueue {
|
public class DelegateFaweQueue extends FaweQueue {
|
||||||
private FaweQueue parent;
|
private FaweQueue parent;
|
||||||
@ -169,6 +170,11 @@ public class DelegateFaweQueue extends FaweQueue {
|
|||||||
return parent.next();
|
return parent.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean next(int amount, ExecutorCompletionService pool, long time) {
|
||||||
|
return parent.next(amount, pool, time);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveMemory() {
|
public void saveMemory() {
|
||||||
parent.saveMemory();
|
parent.saveMemory();
|
||||||
@ -234,6 +240,11 @@ public class DelegateFaweQueue extends FaweQueue {
|
|||||||
return parent.size();
|
return parent.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runTasks() {
|
||||||
|
parent.runTasks();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean enqueue() {
|
public boolean enqueue() {
|
||||||
return parent.enqueue();
|
return parent.enqueue();
|
||||||
|
@ -3,13 +3,13 @@ package com.boydti.fawe.util;
|
|||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.object.RunnableVal2;
|
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||||
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
import java.util.concurrent.ForkJoinPool;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -40,23 +40,17 @@ public class SetQueue {
|
|||||||
*/
|
*/
|
||||||
private final ConcurrentLinkedDeque<Runnable> emptyTasks = new ConcurrentLinkedDeque<>();
|
private final ConcurrentLinkedDeque<Runnable> emptyTasks = new ConcurrentLinkedDeque<>();
|
||||||
|
|
||||||
private final RunnableVal2<Long, FaweQueue> SET_TASK = new RunnableVal2<Long, FaweQueue>() {
|
|
||||||
@Override
|
|
||||||
public void run(Long free, FaweQueue queue) {
|
|
||||||
do {
|
|
||||||
final boolean current = queue.next();
|
|
||||||
if (current == false) {
|
|
||||||
lastSuccess = last;
|
|
||||||
if (inactiveQueues.size() == 0 && activeQueues.size() == 0) {
|
|
||||||
runEmptyTasks();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} while (((SetQueue.this.secondLast = System.currentTimeMillis()) - SetQueue.this.last) < free);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private ForkJoinPool pool = new ForkJoinPool();
|
private ForkJoinPool pool = new ForkJoinPool();
|
||||||
|
private ExecutorCompletionService completer = new ExecutorCompletionService(pool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see TaskManager#getPublicForkJoinPool()
|
||||||
|
* @return ForkJoinPool
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public ExecutorCompletionService getCompleterService() {
|
||||||
|
return completer;
|
||||||
|
}
|
||||||
|
|
||||||
public SetQueue() {
|
public SetQueue() {
|
||||||
tasks = new ConcurrentLinkedDeque<>();
|
tasks = new ConcurrentLinkedDeque<>();
|
||||||
@ -65,56 +59,55 @@ public class SetQueue {
|
|||||||
TaskManager.IMP.repeat(new Runnable() {
|
TaskManager.IMP.repeat(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (!tasks.isEmpty() && Fawe.get().getTimer().isAbove(18.5)) {
|
try {
|
||||||
tasks.poll().run();
|
while (!tasks.isEmpty() && Fawe.get().getTimer().isAbove(18.5)) {
|
||||||
}
|
tasks.poll().run();
|
||||||
if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) {
|
}
|
||||||
lastSuccess = System.currentTimeMillis();
|
if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) {
|
||||||
runEmptyTasks();
|
lastSuccess = System.currentTimeMillis();
|
||||||
return;
|
runEmptyTasks();
|
||||||
}
|
return;
|
||||||
if (!MemUtil.isMemoryFree()) {
|
}
|
||||||
final int mem = MemUtil.calculateMemory();
|
if (!MemUtil.isMemoryFree()) {
|
||||||
if (mem != Integer.MAX_VALUE) {
|
final int mem = MemUtil.calculateMemory();
|
||||||
if ((mem <= 1) && Settings.CRASH_MITIGATION) {
|
if (mem != Integer.MAX_VALUE) {
|
||||||
for (FaweQueue queue : getAllQueues()) {
|
if ((mem <= 1) && Settings.CRASH_MITIGATION) {
|
||||||
queue.saveMemory();
|
for (FaweQueue queue : getAllQueues()) {
|
||||||
|
queue.saveMemory();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (SetQueue.this.forceChunkSet()) {
|
||||||
|
System.gc();
|
||||||
|
} else {
|
||||||
|
SetQueue.this.runEmptyTasks();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (SetQueue.this.forceChunkSet()) {
|
}
|
||||||
System.gc();
|
FaweQueue queue = getNextQueue();
|
||||||
} else {
|
if (queue == null || !Fawe.get().getTimer().isAbove(18.5)) {
|
||||||
SetQueue.this.runEmptyTasks();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
if (Thread.currentThread() != Fawe.get().getMainThread()) {
|
||||||
SET_TASK.value1 = Settings.QUEUE.EXTRA_TIME_MS + 50 + Math.min((50 + SetQueue.this.last) - (SetQueue.this.last = System.currentTimeMillis()), SetQueue.this.secondLast - System.currentTimeMillis());
|
throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread");
|
||||||
SET_TASK.value2 = getNextQueue();
|
|
||||||
if (SET_TASK.value2 == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Thread.currentThread() != Fawe.get().getMainThread()) {
|
|
||||||
throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread");
|
|
||||||
}
|
|
||||||
// Disable the async catcher as it can't discern async vs parallel
|
|
||||||
boolean parallel = Settings.QUEUE.PARALLEL_THREADS > 1;
|
|
||||||
SET_TASK.value2.startSet(parallel);
|
|
||||||
try {
|
|
||||||
if (Settings.QUEUE.PARALLEL_THREADS <= 1 || !Fawe.get().isJava8()) {
|
|
||||||
SET_TASK.run();
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < Settings.QUEUE.PARALLEL_THREADS; i++) {
|
|
||||||
pool.submit(SET_TASK);
|
|
||||||
}
|
|
||||||
pool.awaitQuiescence(Settings.QUEUE.DISCARD_AFTER_MS, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
}
|
||||||
|
long time = Settings.QUEUE.EXTRA_TIME_MS + 50 + Math.min((50 + SetQueue.this.last) - (SetQueue.this.last = System.currentTimeMillis()), SetQueue.this.secondLast - System.currentTimeMillis());
|
||||||
|
// Disable the async catcher as it can't discern async vs parallel
|
||||||
|
boolean parallel = Settings.QUEUE.PARALLEL_THREADS > 1;
|
||||||
|
queue.startSet(parallel);
|
||||||
|
try {
|
||||||
|
if (!queue.next(Settings.QUEUE.PARALLEL_THREADS, getCompleterService(), time)) {
|
||||||
|
queue.runTasks();
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
pool.awaitQuiescence(Settings.QUEUE.DISCARD_AFTER_MS, TimeUnit.MILLISECONDS);
|
||||||
|
completer = new ExecutorCompletionService(pool);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
secondLast = System.currentTimeMillis();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
MainUtil.handleError(e);
|
e.printStackTrace();
|
||||||
} finally {
|
|
||||||
// Enable it again (note that we are still on the main thread)
|
|
||||||
SET_TASK.value2.endSet(parallel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 1);
|
}, 1);
|
||||||
@ -156,6 +149,7 @@ public class SetQueue {
|
|||||||
public void dequeue(FaweQueue queue) {
|
public void dequeue(FaweQueue queue) {
|
||||||
inactiveQueues.remove(queue);
|
inactiveQueues.remove(queue);
|
||||||
activeQueues.remove(queue);
|
activeQueues.remove(queue);
|
||||||
|
queue.runTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<FaweQueue> getAllQueues() {
|
public Collection<FaweQueue> getAllQueues() {
|
||||||
@ -181,44 +175,34 @@ public class SetQueue {
|
|||||||
return queue;
|
return queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FaweQueue getNewQueue(String world, boolean fast, boolean autoqueue) {
|
||||||
|
FaweQueue queue = Fawe.imp().getNewQueue(world, fast);
|
||||||
|
if (autoqueue) {
|
||||||
|
inactiveQueues.add(queue);
|
||||||
|
}
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
public void flush(FaweQueue queue) {
|
public void flush(FaweQueue queue) {
|
||||||
SET_TASK.value1 = Long.MAX_VALUE;
|
queue.startSet(Settings.QUEUE.PARALLEL_THREADS > 1);
|
||||||
SET_TASK.value2 = queue;
|
|
||||||
if (SET_TASK.value2 == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Thread.currentThread() != Fawe.get().getMainThread()) {
|
|
||||||
throw new IllegalStateException("Must be flushed on the main thread!");
|
|
||||||
}
|
|
||||||
// Disable the async catcher as it can't discern async vs parallel
|
|
||||||
boolean parallel = Settings.QUEUE.PARALLEL_THREADS > 1;
|
|
||||||
SET_TASK.value2.startSet(parallel);
|
|
||||||
try {
|
try {
|
||||||
if (!parallel || !Fawe.get().isJava8()) {
|
queue.next(Settings.QUEUE.PARALLEL_THREADS, getCompleterService(), Long.MAX_VALUE);
|
||||||
SET_TASK.run();
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < Settings.QUEUE.PARALLEL_THREADS; i++) {
|
|
||||||
pool.submit(SET_TASK);
|
|
||||||
}
|
|
||||||
pool.awaitQuiescence(Settings.QUEUE.DISCARD_AFTER_MS, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
pool.awaitQuiescence(Settings.QUEUE.DISCARD_AFTER_MS, TimeUnit.MILLISECONDS);
|
||||||
|
completer = new ExecutorCompletionService(pool);
|
||||||
MainUtil.handleError(e);
|
MainUtil.handleError(e);
|
||||||
} finally {
|
|
||||||
// Enable it again (note that we are still on the main thread)
|
|
||||||
SET_TASK.value2.endSet(parallel);
|
|
||||||
dequeue(queue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FaweQueue getNextQueue() {
|
public FaweQueue getNextQueue() {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
while (activeQueues.size() > 0) {
|
while (!activeQueues.isEmpty()) {
|
||||||
FaweQueue queue = activeQueues.peek();
|
FaweQueue queue = activeQueues.peek();
|
||||||
if (queue != null && queue.size() > 0) {
|
if (queue != null && queue.size() > 0) {
|
||||||
queue.setModified(now);
|
queue.setModified(now);
|
||||||
return queue;
|
return queue;
|
||||||
} else {
|
} else {
|
||||||
|
queue.runTasks();
|
||||||
activeQueues.poll();
|
activeQueues.poll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,6 +218,7 @@ public class SetQueue {
|
|||||||
total += queue.size();
|
total += queue.size();
|
||||||
if (queue.size() == 0) {
|
if (queue.size() == 0) {
|
||||||
if (age > Settings.QUEUE.DISCARD_AFTER_MS) {
|
if (age > Settings.QUEUE.DISCARD_AFTER_MS) {
|
||||||
|
queue.runTasks();
|
||||||
iter.remove();
|
iter.remove();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -265,6 +250,8 @@ public class SetQueue {
|
|||||||
if (set) {
|
if (set) {
|
||||||
activeQueues.add(queue);
|
activeQueues.add(queue);
|
||||||
return set;
|
return set;
|
||||||
|
} else {
|
||||||
|
queue.runTasks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,6 +272,9 @@ public class SetQueue {
|
|||||||
}
|
}
|
||||||
if (diff > Settings.QUEUE.DISCARD_AFTER_MS) {
|
if (diff > Settings.QUEUE.DISCARD_AFTER_MS) {
|
||||||
// These edits never finished
|
// These edits never finished
|
||||||
|
for (FaweQueue queue : tmp) {
|
||||||
|
queue.runTasks();
|
||||||
|
}
|
||||||
inactiveQueues.clear();
|
inactiveQueues.clear();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -214,7 +214,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.getQueue().next();
|
edit.getQueue().flush();
|
||||||
setPosition(new Vector(x + 0.5, y, z + 0.5));
|
setPosition(new Vector(x + 0.5, y, z + 0.5));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -162,7 +162,7 @@ public class NavigationCommands {
|
|||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
aliases = { "jumpto", "j" },
|
aliases = { "jumpto", "j" },
|
||||||
usage = "jumpto [world,x,y,z]",
|
usage = "[world,x,y,z]",
|
||||||
desc = "Teleport to a location",
|
desc = "Teleport to a location",
|
||||||
min = 0,
|
min = 0,
|
||||||
max = 1
|
max = 1
|
||||||
|
@ -151,7 +151,7 @@ public class SelectionCommand extends SimpleCommand<Operation> {
|
|||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
BBC.OPERATION.send(actor, BBC.VISITOR_BLOCK.format(cuboid.getArea()));
|
BBC.OPERATION.send(actor, BBC.VISITOR_BLOCK.format(cuboid.getArea()));
|
||||||
queue.flush();
|
queue.flush();
|
||||||
BBC.ACTION_COMPLETE.send(actor, start);
|
BBC.ACTION_COMPLETE.send(actor, (System.currentTimeMillis() - start) / 1000);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
@ -118,6 +118,11 @@ public class FaweForge implements IFawe {
|
|||||||
return new ForgeQueue_All(world);
|
return new ForgeQueue_All(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||||
|
return new ForgeQueue_All(world);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<FaweMaskManager> getMaskManagers() {
|
public Collection<FaweMaskManager> getMaskManagers() {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
@ -1,19 +1,42 @@
|
|||||||
package com.boydti.fawe.forge.v0;
|
package com.boydti.fawe.forge.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.object.BytePair;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.boydti.fawe.util.MathMan;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.ListTag;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.state.IBlockState;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityList;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.BitArray;
|
import net.minecraft.util.BitArray;
|
||||||
|
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.chunk.BlockStateContainer;
|
import net.minecraft.world.chunk.BlockStateContainer;
|
||||||
import net.minecraft.world.chunk.BlockStatePaletteRegistry;
|
import net.minecraft.world.chunk.BlockStatePaletteRegistry;
|
||||||
import net.minecraft.world.chunk.Chunk;
|
import net.minecraft.world.chunk.Chunk;
|
||||||
import net.minecraft.world.chunk.IBlockStatePalette;
|
import net.minecraft.world.chunk.IBlockStatePalette;
|
||||||
|
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||||
|
|
||||||
public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||||
|
|
||||||
public BlockStateContainer[] sectionPalettes;
|
public BlockStateContainer[] sectionPalettes;
|
||||||
|
|
||||||
@ -35,7 +58,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
public ForgeChunk_All copy(boolean shallow) {
|
||||||
ForgeChunk_All value = (ForgeChunk_All) super.copy(shallow);
|
ForgeChunk_All value = (ForgeChunk_All) super.copy(shallow);
|
||||||
if (sectionPalettes != null) {
|
if (sectionPalettes != null) {
|
||||||
value.sectionPalettes = new BlockStateContainer[16];
|
value.sectionPalettes = new BlockStateContainer[16];
|
||||||
@ -111,4 +134,210 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ForgeChunk_All call() {
|
||||||
|
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
|
||||||
|
nmsChunk.setModified(true);
|
||||||
|
net.minecraft.world.World nmsWorld = getParent().getWorld();
|
||||||
|
try {
|
||||||
|
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||||
|
// Sections
|
||||||
|
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||||
|
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||||
|
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||||
|
// Remove entities
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
int count = this.getCount(i);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
||||||
|
} else {
|
||||||
|
char[] array = this.getIdArray(i);
|
||||||
|
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||||
|
for (Entity entity : ents) {
|
||||||
|
if (entity instanceof EntityPlayer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int x = ((int) Math.round(entity.posX) & 15);
|
||||||
|
int z = ((int) Math.round(entity.posZ) & 15);
|
||||||
|
int y = (int) Math.round(entity.posY);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set entities
|
||||||
|
Set<UUID> createdEntities = new HashSet<>();
|
||||||
|
Set<CompoundTag> entitiesToSpawn = this.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();
|
||||||
|
NBTTagCompound tag = (NBTTagCompound)ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||||
|
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
|
||||||
|
if (entity != null) {
|
||||||
|
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
||||||
|
nmsWorld.spawnEntityInWorld(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Run change task if applicable
|
||||||
|
if (getParent().getChangeTask() != null) {
|
||||||
|
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||||
|
getParent().getChangeTask().run(previous, this);
|
||||||
|
}
|
||||||
|
// Trim tiles
|
||||||
|
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||||
|
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||||
|
BlockPos pos = tile.getKey();
|
||||||
|
int lx = pos.getX() & 15;
|
||||||
|
int ly = pos.getY();
|
||||||
|
int lz = pos.getZ() & 15;
|
||||||
|
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||||
|
char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||||
|
if (array[k] != 0) {
|
||||||
|
tile.getValue().invalidate();;
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HashSet<UUID> entsToRemove = this.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Efficiently merge sections
|
||||||
|
for (int j = 0; j < sections.length; j++) {
|
||||||
|
int count = this.getCount(j);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ExtendedBlockStorage section = sections[j];
|
||||||
|
if (section == null) {
|
||||||
|
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||||
|
section = sections[j] = new ExtendedBlockStorage(j << 4, flag);
|
||||||
|
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||||
|
getParent().setCount(0, count - this.getAir(j), section);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
||||||
|
}
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||||
|
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||||
|
getParent().setCount(0, count - this.getAir(j), section);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlockStateContainer nibble = section.getData();
|
||||||
|
int nonEmptyBlockCount = 0;
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
|
||||||
|
switch (combinedId) {
|
||||||
|
case 0:
|
||||||
|
IBlockState existing = nibble.get(x, y, z);
|
||||||
|
if (existing != ForgeQueue_All.air) {
|
||||||
|
nonEmptyBlockCount++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case 1:
|
||||||
|
nibble.set(x, y, z, ForgeQueue_All.air);
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
nonEmptyBlockCount++;
|
||||||
|
nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getParent().setCount(0, nonEmptyBlockCount, section);
|
||||||
|
}
|
||||||
|
// Set biomes
|
||||||
|
int[][] biomes = this.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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set tiles
|
||||||
|
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
|
||||||
|
int bx = this.getX() << 4;
|
||||||
|
int bz = this.getZ() << 4;
|
||||||
|
|
||||||
|
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||||
|
CompoundTag nativeTag = entry.getValue();
|
||||||
|
BytePair pair = entry.getKey();
|
||||||
|
BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos
|
||||||
|
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||||
|
if (tileEntity != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||||
|
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
MainUtil.handleError(e);
|
||||||
|
}
|
||||||
|
int[][] biomes = this.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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,21 @@
|
|||||||
package com.boydti.fawe.forge.v0;
|
package com.boydti.fawe.forge.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;
|
||||||
import com.boydti.fawe.object.BytePair;
|
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
|
||||||
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.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -57,11 +50,20 @@ import net.minecraftforge.common.DimensionManager;
|
|||||||
|
|
||||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||||
|
|
||||||
private static Method methodFromNative;
|
protected static Method methodFromNative;
|
||||||
private static Method methodToNative;
|
protected static Method methodToNative;
|
||||||
|
|
||||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||||
super(world);
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForgeQueue_All(String world) {
|
||||||
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
if (methodFromNative == null) {
|
if (methodFromNative == null) {
|
||||||
try {
|
try {
|
||||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||||
@ -76,7 +78,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
getImpWorld();
|
getImpWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||||
@ -292,216 +294,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
return previous;
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final IBlockState air = Blocks.AIR.getDefaultState();
|
protected final static IBlockState air = Blocks.AIR.getDefaultState();
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
|
||||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
|
||||||
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
|
|
||||||
nmsChunk.setModified(true);
|
|
||||||
net.minecraft.world.World nmsWorld = getWorld();
|
|
||||||
try {
|
|
||||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
|
||||||
// Sections
|
|
||||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
|
||||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
|
||||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
|
||||||
|
|
||||||
|
|
||||||
// Remove entities
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
int count = fs.getCount(i);
|
|
||||||
if (count == 0) {
|
|
||||||
continue;
|
|
||||||
} else if (count >= 4096) {
|
|
||||||
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
|
||||||
} 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.posX) & 15);
|
|
||||||
int z = ((int) Math.round(entity.posZ) & 15);
|
|
||||||
int y = (int) Math.round(entity.posY);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 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();
|
|
||||||
NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag);
|
|
||||||
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
|
|
||||||
if (entity != null) {
|
|
||||||
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
|
||||||
nmsWorld.spawnEntityInWorld(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Run change task if applicable
|
|
||||||
if (changeTask != null) {
|
|
||||||
CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false);
|
|
||||||
changeTask.run(previous);
|
|
||||||
}
|
|
||||||
// Trim tiles
|
|
||||||
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
|
||||||
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
|
||||||
BlockPos pos = tile.getKey();
|
|
||||||
int lx = pos.getX() & 15;
|
|
||||||
int ly = pos.getY();
|
|
||||||
int lz = pos.getZ() & 15;
|
|
||||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
|
||||||
char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
|
||||||
if (array[k] != 0) {
|
|
||||||
tile.getValue().invalidate();;
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Efficiently merge sections
|
|
||||||
for (int j = 0; j < sections.length; j++) {
|
|
||||||
int count = fs.getCount(j);
|
|
||||||
if (count == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ExtendedBlockStorage section = sections[j];
|
|
||||||
if (section == null) {
|
|
||||||
if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) {
|
|
||||||
section = sections[j] = new ExtendedBlockStorage(j << 4, flag);
|
|
||||||
setPalette(section, fs.sectionPalettes[j]);
|
|
||||||
setCount(0, count - fs.getAir(j), section);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
|
||||||
}
|
|
||||||
} else if (count >= 4096) {
|
|
||||||
if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) {
|
|
||||||
setPalette(section, fs.sectionPalettes[j]);
|
|
||||||
setCount(0, count - fs.getAir(j), section);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BlockStateContainer nibble = section.getData();
|
|
||||||
int nonEmptyBlockCount = 0;
|
|
||||||
for (int y = 0; y < 16; y++) {
|
|
||||||
for (int z = 0; z < 16; z++) {
|
|
||||||
for (int x = 0; x < 16; x++) {
|
|
||||||
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
|
|
||||||
switch (combinedId) {
|
|
||||||
case 0:
|
|
||||||
IBlockState existing = nibble.get(x, y, z);
|
|
||||||
if (existing != air) {
|
|
||||||
nonEmptyBlockCount++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
case 1:
|
|
||||||
nibble.set(x, y, z, air);
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
nonEmptyBlockCount++;
|
|
||||||
nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCount(0, nonEmptyBlockCount, section);
|
|
||||||
}
|
|
||||||
// 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.getBiomeArray()[((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();
|
|
||||||
BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos
|
|
||||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
|
||||||
if (tileEntity != null) {
|
|
||||||
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag);
|
|
||||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException {
|
public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException {
|
||||||
Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data");
|
Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data");
|
||||||
@ -604,7 +397,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
nmsWorld.checkLight(pos);
|
nmsWorld.checkLight(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorldServer nmsWorld;
|
protected WorldServer nmsWorld;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World getImpWorld() {
|
public World getImpWorld() {
|
||||||
|
@ -115,6 +115,11 @@ public class FaweForge implements IFawe {
|
|||||||
return new ForgeQueue_All(world);
|
return new ForgeQueue_All(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||||
|
return new ForgeQueue_All(world);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<FaweMaskManager> getMaskManagers() {
|
public Collection<FaweMaskManager> getMaskManagers() {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
@ -1,14 +1,36 @@
|
|||||||
package com.boydti.fawe.forge.v0;
|
package com.boydti.fawe.forge.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.object.BytePair;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.boydti.fawe.util.MathMan;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.ListTag;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityList;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.world.ChunkPosition;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.chunk.Chunk;
|
import net.minecraft.world.chunk.Chunk;
|
||||||
import net.minecraft.world.chunk.NibbleArray;
|
import net.minecraft.world.chunk.NibbleArray;
|
||||||
|
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||||
|
|
||||||
public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||||
|
|
||||||
public byte[][] byteIds;
|
public byte[][] byteIds;
|
||||||
public NibbleArray[] datas;
|
public NibbleArray[] datas;
|
||||||
@ -83,7 +105,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
public ForgeChunk_All copy(boolean shallow) {
|
||||||
ForgeChunk_All copy = new ForgeChunk_All(getParent(), getX(), getZ());
|
ForgeChunk_All copy = new ForgeChunk_All(getParent(), getX(), getZ());
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
copy.byteIds = byteIds;
|
copy.byteIds = byteIds;
|
||||||
@ -104,4 +126,229 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ForgeChunk_All call() {
|
||||||
|
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
|
||||||
|
net.minecraft.world.World nmsWorld = nmsChunk.worldObj;
|
||||||
|
nmsChunk.setChunkModified();
|
||||||
|
nmsChunk.sendUpdates = true;
|
||||||
|
try {
|
||||||
|
boolean flag = !nmsWorld.provider.hasNoSky;
|
||||||
|
// Sections
|
||||||
|
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||||
|
Map<ChunkPosition, TileEntity> tiles = nmsChunk.chunkTileEntityMap;
|
||||||
|
List<Entity>[] entities = nmsChunk.entityLists;
|
||||||
|
|
||||||
|
// Remove entities
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
int count = this.getCount(i);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
entities[i].clear();
|
||||||
|
} else {
|
||||||
|
char[] array = this.getIdArray(i);
|
||||||
|
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||||
|
for (Entity entity : ents) {
|
||||||
|
if (entity instanceof EntityPlayer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int x = ((int) Math.round(entity.posX) & 15);
|
||||||
|
int z = ((int) Math.round(entity.posZ) & 15);
|
||||||
|
int y = (int) Math.round(entity.posY);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set entities
|
||||||
|
Set<UUID> createdEntities = new HashSet<>();
|
||||||
|
Set<CompoundTag> entitiesToSpawn = this.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();
|
||||||
|
NBTTagCompound tag = (NBTTagCompound)ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||||
|
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
|
||||||
|
if (entity != null) {
|
||||||
|
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
||||||
|
nmsWorld.spawnEntityInWorld(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Run change task if applicable
|
||||||
|
if (getParent().getChangeTask() != null) {
|
||||||
|
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||||
|
getParent().getChangeTask().run(previous, this);
|
||||||
|
}
|
||||||
|
// Trim tiles
|
||||||
|
Set<Map.Entry<ChunkPosition, TileEntity>> entryset = tiles.entrySet();
|
||||||
|
Iterator<Map.Entry<ChunkPosition, TileEntity>> iterator = entryset.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<ChunkPosition, TileEntity> tile = iterator.next();
|
||||||
|
ChunkPosition pos = tile.getKey();
|
||||||
|
int lx = pos.chunkPosX & 15;
|
||||||
|
int ly = pos.chunkPosY;
|
||||||
|
int lz = pos.chunkPosZ & 15;
|
||||||
|
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||||
|
char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||||
|
if (array[k] != 0) {
|
||||||
|
tile.getValue().invalidate();;
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HashSet<UUID> entsToRemove = this.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Efficiently merge sections
|
||||||
|
for (int j = 0; j < sections.length; j++) {
|
||||||
|
if (this.getCount(j) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
byte[] newIdArray = this.getByteIdArray(j);
|
||||||
|
if (newIdArray == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NibbleArray newDataArray = this.getDataArray(j);
|
||||||
|
ExtendedBlockStorage section = sections[j];
|
||||||
|
if ((section == null) || (this.getCount(j) >= 4096)) {
|
||||||
|
sections[j] = section = new ExtendedBlockStorage(j << 4, !getParent().getWorld().provider.hasNoSky);
|
||||||
|
section.setBlockLSBArray(newIdArray);
|
||||||
|
section.setBlockMetadataArray(newDataArray);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
byte[] currentIdArray = section.getBlockLSBArray();
|
||||||
|
NibbleArray currentDataArray = section.getMetadataArray();
|
||||||
|
boolean data = currentDataArray != null;
|
||||||
|
if (!data) {
|
||||||
|
section.setBlockMetadataArray(newDataArray);
|
||||||
|
}
|
||||||
|
boolean fill = true;
|
||||||
|
int solid = 0;
|
||||||
|
char[] charArray = this.getIdArray(j);
|
||||||
|
for (int k = 0; k < newIdArray.length; k++) {
|
||||||
|
char combined = charArray[k];
|
||||||
|
switch (combined) {
|
||||||
|
case 0:
|
||||||
|
fill = false;
|
||||||
|
continue;
|
||||||
|
case 1:
|
||||||
|
fill = false;
|
||||||
|
if (currentIdArray[k] != 0) {
|
||||||
|
solid++;
|
||||||
|
}
|
||||||
|
currentIdArray[k] = 0;
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
solid++;
|
||||||
|
currentIdArray[k] = newIdArray[k];
|
||||||
|
if (data) {
|
||||||
|
int dataByte = FaweCache.getData(combined);
|
||||||
|
int x = FaweCache.CACHE_X[0][k];
|
||||||
|
int y = FaweCache.CACHE_Y[0][k];
|
||||||
|
int z = FaweCache.CACHE_Z[0][k];
|
||||||
|
int newData = newDataArray.get(x, y, z);
|
||||||
|
currentDataArray.set(x, y, z, newData);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getParent().setCount(0, solid, section);
|
||||||
|
if (fill) {
|
||||||
|
this.setCount(j, Short.MAX_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set biomes
|
||||||
|
int[][] biomes = this.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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set tiles
|
||||||
|
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
|
||||||
|
int bx = this.getX() << 4;
|
||||||
|
int bz = this.getZ() << 4;
|
||||||
|
|
||||||
|
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||||
|
CompoundTag nativeTag = entry.getValue();
|
||||||
|
BytePair pair = entry.getKey();
|
||||||
|
int x = MathMan.unpair16x((byte) pair.get0()) + bx;
|
||||||
|
int y = pair.get1() & 0xFF;
|
||||||
|
int z = MathMan.unpair16y((byte) pair.get0()) + bz;
|
||||||
|
TileEntity tileEntity = nmsWorld.getTileEntity(x, y, z);
|
||||||
|
if (tileEntity != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||||
|
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
MainUtil.handleError(e);
|
||||||
|
}
|
||||||
|
int[][] biomes = this.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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasEntities(Chunk nmsChunk) {
|
||||||
|
for (int i = 0; i < nmsChunk.entityLists.length; i++) {
|
||||||
|
List slice = nmsChunk.entityLists[i];
|
||||||
|
if (slice != null && !slice.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package com.boydti.fawe.forge.v0;
|
package com.boydti.fawe.forge.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;
|
||||||
import com.boydti.fawe.object.BytePair;
|
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.IntegerPair;
|
import com.boydti.fawe.object.IntegerPair;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
@ -12,17 +10,14 @@ import com.boydti.fawe.util.MainUtil;
|
|||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
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.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -52,11 +47,20 @@ import net.minecraftforge.common.DimensionManager;
|
|||||||
|
|
||||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||||
|
|
||||||
private static Method methodFromNative;
|
protected static Method methodFromNative;
|
||||||
private static Method methodToNative;
|
protected static Method methodToNative;
|
||||||
|
|
||||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||||
super(world);
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForgeQueue_All(String world) {
|
||||||
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
if (methodFromNative == null) {
|
if (methodFromNative == null) {
|
||||||
try {
|
try {
|
||||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||||
@ -199,7 +203,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
protected final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(IntegerPair loc) {
|
public void run(IntegerPair loc) {
|
||||||
Chunk chunk = getWorld().getChunkProvider().provideChunk(loc.x, loc.z);
|
Chunk chunk = getWorld().getChunkProvider().provideChunk(loc.x, loc.z);
|
||||||
@ -264,223 +268,6 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
|
||||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
|
||||||
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
|
|
||||||
net.minecraft.world.World nmsWorld = nmsChunk.worldObj;
|
|
||||||
nmsChunk.setChunkModified();
|
|
||||||
nmsChunk.sendUpdates = true;
|
|
||||||
try {
|
|
||||||
boolean flag = !nmsWorld.provider.hasNoSky;
|
|
||||||
// Sections
|
|
||||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
|
||||||
Map<ChunkPosition, TileEntity> tiles = nmsChunk.chunkTileEntityMap;
|
|
||||||
List<Entity>[] entities = nmsChunk.entityLists;
|
|
||||||
|
|
||||||
// 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.posX) & 15);
|
|
||||||
int z = ((int) Math.round(entity.posZ) & 15);
|
|
||||||
int y = (int) Math.round(entity.posY);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 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();
|
|
||||||
NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag);
|
|
||||||
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
|
|
||||||
if (entity != null) {
|
|
||||||
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
|
||||||
nmsWorld.spawnEntityInWorld(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Run change task if applicable
|
|
||||||
if (changeTask != null) {
|
|
||||||
CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false);
|
|
||||||
changeTask.run(previous);
|
|
||||||
}
|
|
||||||
// Trim tiles
|
|
||||||
Set<Map.Entry<ChunkPosition, TileEntity>> entryset = tiles.entrySet();
|
|
||||||
Iterator<Map.Entry<ChunkPosition, TileEntity>> iterator = entryset.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Map.Entry<ChunkPosition, TileEntity> tile = iterator.next();
|
|
||||||
ChunkPosition pos = tile.getKey();
|
|
||||||
int lx = pos.chunkPosX & 15;
|
|
||||||
int ly = pos.chunkPosY;
|
|
||||||
int lz = pos.chunkPosZ & 15;
|
|
||||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
|
||||||
char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
|
||||||
if (array[k] != 0) {
|
|
||||||
tile.getValue().invalidate();;
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Efficiently merge sections
|
|
||||||
for (int j = 0; j < sections.length; j++) {
|
|
||||||
if (fs.getCount(j) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
byte[] newIdArray = fs.getByteIdArray(j);
|
|
||||||
if (newIdArray == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
NibbleArray newDataArray = fs.getDataArray(j);
|
|
||||||
ExtendedBlockStorage section = sections[j];
|
|
||||||
if ((section == null) || (fs.getCount(j) >= 4096)) {
|
|
||||||
sections[j] = section = new ExtendedBlockStorage(j << 4, !getWorld().provider.hasNoSky);
|
|
||||||
section.setBlockLSBArray(newIdArray);
|
|
||||||
section.setBlockMetadataArray(newDataArray);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
byte[] currentIdArray = section.getBlockLSBArray();
|
|
||||||
NibbleArray currentDataArray = section.getMetadataArray();
|
|
||||||
boolean data = currentDataArray != null;
|
|
||||||
if (!data) {
|
|
||||||
section.setBlockMetadataArray(newDataArray);
|
|
||||||
}
|
|
||||||
boolean fill = true;
|
|
||||||
int solid = 0;
|
|
||||||
char[] charArray = fs.getIdArray(j);
|
|
||||||
for (int k = 0; k < newIdArray.length; k++) {
|
|
||||||
char combined = charArray[k];
|
|
||||||
switch (combined) {
|
|
||||||
case 0:
|
|
||||||
fill = false;
|
|
||||||
continue;
|
|
||||||
case 1:
|
|
||||||
fill = false;
|
|
||||||
if (currentIdArray[k] != 0) {
|
|
||||||
solid++;
|
|
||||||
}
|
|
||||||
currentIdArray[k] = 0;
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
solid++;
|
|
||||||
currentIdArray[k] = newIdArray[k];
|
|
||||||
if (data) {
|
|
||||||
int dataByte = FaweCache.getData(combined);
|
|
||||||
int x = FaweCache.CACHE_X[0][k];
|
|
||||||
int y = FaweCache.CACHE_Y[0][k];
|
|
||||||
int z = FaweCache.CACHE_Z[0][k];
|
|
||||||
int newData = newDataArray.get(x, y, z);
|
|
||||||
currentDataArray.set(x, y, z, newData);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCount(0, solid, section);
|
|
||||||
if (fill) {
|
|
||||||
fs.setCount(j, Short.MAX_VALUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.getBiomeArray()[((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();
|
|
||||||
int x = MathMan.unpair16x((byte) pair.get0()) + bx;
|
|
||||||
int y = pair.get1() & 0xFF;
|
|
||||||
int z = MathMan.unpair16y((byte) pair.get0()) + bz;
|
|
||||||
TileEntity tileEntity = nmsWorld.getTileEntity(x, y, z);
|
|
||||||
if (tileEntity != null) {
|
|
||||||
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag);
|
|
||||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
||||||
Class<? extends ExtendedBlockStorage> clazz = section.getClass();
|
Class<? extends ExtendedBlockStorage> clazz = section.getClass();
|
||||||
Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c"); // tickRefCount
|
Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c"); // tickRefCount
|
||||||
@ -599,7 +386,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
nmsWorld.func_147451_t(x, y, z);
|
nmsWorld.func_147451_t(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorldServer nmsWorld;
|
protected WorldServer nmsWorld;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World getImpWorld() {
|
public World getImpWorld() {
|
||||||
|
@ -118,6 +118,11 @@ public class FaweForge implements IFawe {
|
|||||||
return new ForgeQueue_All(world);
|
return new ForgeQueue_All(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||||
|
return new ForgeQueue_All(world);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<FaweMaskManager> getMaskManagers() {
|
public Collection<FaweMaskManager> getMaskManagers() {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
@ -1,11 +1,35 @@
|
|||||||
package com.boydti.fawe.forge.v0;
|
package com.boydti.fawe.forge.v0;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.example.CharFaweChunk;
|
import com.boydti.fawe.example.CharFaweChunk;
|
||||||
|
import com.boydti.fawe.object.BytePair;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.boydti.fawe.util.MathMan;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.ListTag;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityList;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.util.BlockPos;
|
||||||
|
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.chunk.Chunk;
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||||
|
|
||||||
public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||||
/**
|
/**
|
||||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||||
*
|
*
|
||||||
@ -22,4 +46,209 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
|||||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||||
return world.getChunkProvider().provideChunk(getX(), getZ());
|
return world.getChunkProvider().provideChunk(getX(), getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ForgeChunk_All call() {
|
||||||
|
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
|
||||||
|
nmsChunk.setModified(true);
|
||||||
|
nmsChunk.setHasEntities(true);
|
||||||
|
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
||||||
|
try {
|
||||||
|
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||||
|
// Sections
|
||||||
|
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||||
|
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||||
|
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||||
|
|
||||||
|
|
||||||
|
// Remove entities
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
int count = this.getCount(i);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
||||||
|
} else {
|
||||||
|
char[] array = this.getIdArray(i);
|
||||||
|
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||||
|
for (Entity entity : ents) {
|
||||||
|
if (entity instanceof EntityPlayer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int x = ((int) Math.round(entity.posX) & 15);
|
||||||
|
int z = ((int) Math.round(entity.posZ) & 15);
|
||||||
|
int y = (int) Math.round(entity.posY);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set entities
|
||||||
|
Set<UUID> createdEntities = new HashSet<>();
|
||||||
|
Set<CompoundTag> entitiesToSpawn = this.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();
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||||
|
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
|
||||||
|
if (entity != null) {
|
||||||
|
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
||||||
|
nmsWorld.spawnEntityInWorld(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Run change task if applicable
|
||||||
|
if (getParent().getChangeTask() != null) {
|
||||||
|
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||||
|
getParent().getChangeTask().run(previous, this);
|
||||||
|
}
|
||||||
|
// Trim tiles
|
||||||
|
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||||
|
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||||
|
BlockPos pos = tile.getKey();
|
||||||
|
int lx = pos.getX() & 15;
|
||||||
|
int ly = pos.getY();
|
||||||
|
int lz = pos.getZ() & 15;
|
||||||
|
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||||
|
char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||||
|
if (array[k] != 0) {
|
||||||
|
tile.getValue().invalidate();;
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HashSet<UUID> entsToRemove = this.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Efficiently merge sections
|
||||||
|
for (int j = 0; j < sections.length; j++) {
|
||||||
|
int count = this.getCount(j);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char[] newArray = this.getIdArray(j);
|
||||||
|
if (newArray == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ExtendedBlockStorage section = sections[j];
|
||||||
|
|
||||||
|
if ((section == null)) {
|
||||||
|
section = new ExtendedBlockStorage(j << 4, flag);
|
||||||
|
section.setData(newArray);
|
||||||
|
sections[j] = section;
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096){
|
||||||
|
section.setData(newArray);
|
||||||
|
getParent().setCount(0, count - this.getAir(j), section);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char[] currentArray = section.getData();
|
||||||
|
boolean fill = true;
|
||||||
|
int solid = 0;
|
||||||
|
for (int k = 0; k < newArray.length; k++) {
|
||||||
|
char n = newArray[k];
|
||||||
|
switch (n) {
|
||||||
|
case 0:
|
||||||
|
fill = false;
|
||||||
|
continue;
|
||||||
|
case 1:
|
||||||
|
fill = false;
|
||||||
|
if (currentArray[k] > 1) {
|
||||||
|
solid++;
|
||||||
|
}
|
||||||
|
currentArray[k] = 0;
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
solid++;
|
||||||
|
currentArray[k] = n;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getParent().setCount(0, solid, section);
|
||||||
|
if (fill) {
|
||||||
|
this.setCount(j, Short.MAX_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set biomes
|
||||||
|
int[][] biomes = this.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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set tiles
|
||||||
|
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
|
||||||
|
int bx = this.getX() << 4;
|
||||||
|
int bz = this.getZ() << 4;
|
||||||
|
|
||||||
|
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||||
|
CompoundTag nativeTag = entry.getValue();
|
||||||
|
BytePair pair = entry.getKey();
|
||||||
|
BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos
|
||||||
|
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||||
|
if (tileEntity != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||||
|
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
MainUtil.handleError(e);
|
||||||
|
}
|
||||||
|
int[][] biomes = this.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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,21 @@
|
|||||||
package com.boydti.fawe.forge.v0;
|
package com.boydti.fawe.forge.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;
|
||||||
import com.boydti.fawe.object.BytePair;
|
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
|
||||||
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.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
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.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
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 java.util.UUID;
|
||||||
@ -50,11 +44,20 @@ import net.minecraftforge.common.DimensionManager;
|
|||||||
|
|
||||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||||
|
|
||||||
private static Method methodFromNative;
|
protected static Method methodFromNative;
|
||||||
private static Method methodToNative;
|
protected static Method methodToNative;
|
||||||
|
|
||||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||||
super(world);
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForgeQueue_All(String world) {
|
||||||
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
if (methodFromNative == null) {
|
if (methodFromNative == null) {
|
||||||
try {
|
try {
|
||||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||||
@ -69,7 +72,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
getImpWorld();
|
getImpWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||||
@ -241,212 +244,6 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
return previous;
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
|
||||||
CharFaweChunk<Chunk> fs = (CharFaweChunk) fc;
|
|
||||||
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
|
|
||||||
nmsChunk.setModified(true);
|
|
||||||
nmsChunk.setHasEntities(true);
|
|
||||||
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
|
||||||
try {
|
|
||||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
|
||||||
// Sections
|
|
||||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
|
||||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
|
||||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
|
||||||
|
|
||||||
|
|
||||||
// Remove entities
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
int count = fs.getCount(i);
|
|
||||||
if (count == 0) {
|
|
||||||
continue;
|
|
||||||
} else if (count >= 4096) {
|
|
||||||
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
|
||||||
} 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.posX) & 15);
|
|
||||||
int z = ((int) Math.round(entity.posZ) & 15);
|
|
||||||
int y = (int) Math.round(entity.posY);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 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();
|
|
||||||
NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag);
|
|
||||||
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
|
|
||||||
if (entity != null) {
|
|
||||||
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
|
||||||
nmsWorld.spawnEntityInWorld(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Run change task if applicable
|
|
||||||
if (changeTask != null) {
|
|
||||||
CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false);
|
|
||||||
changeTask.run(previous);
|
|
||||||
}
|
|
||||||
// Trim tiles
|
|
||||||
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
|
||||||
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
|
||||||
BlockPos pos = tile.getKey();
|
|
||||||
int lx = pos.getX() & 15;
|
|
||||||
int ly = pos.getY();
|
|
||||||
int lz = pos.getZ() & 15;
|
|
||||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
|
||||||
char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
|
||||||
if (array[k] != 0) {
|
|
||||||
tile.getValue().invalidate();;
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Efficiently merge sections
|
|
||||||
for (int j = 0; j < sections.length; j++) {
|
|
||||||
int count = fs.getCount(j);
|
|
||||||
if (count == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
char[] newArray = fs.getIdArray(j);
|
|
||||||
if (newArray == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ExtendedBlockStorage section = sections[j];
|
|
||||||
|
|
||||||
if ((section == null)) {
|
|
||||||
section = new ExtendedBlockStorage(j << 4, flag);
|
|
||||||
section.setData(newArray);
|
|
||||||
sections[j] = section;
|
|
||||||
continue;
|
|
||||||
} else if (count >= 4096){
|
|
||||||
section.setData(newArray);
|
|
||||||
setCount(0, count - fs.getAir(j), section);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
char[] currentArray = section.getData();
|
|
||||||
boolean fill = true;
|
|
||||||
int solid = 0;
|
|
||||||
for (int k = 0; k < newArray.length; k++) {
|
|
||||||
char n = newArray[k];
|
|
||||||
switch (n) {
|
|
||||||
case 0:
|
|
||||||
fill = false;
|
|
||||||
continue;
|
|
||||||
case 1:
|
|
||||||
fill = false;
|
|
||||||
if (currentArray[k] > 1) {
|
|
||||||
solid++;
|
|
||||||
}
|
|
||||||
currentArray[k] = 0;
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
solid++;
|
|
||||||
currentArray[k] = n;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCount(0, solid, section);
|
|
||||||
if (fill) {
|
|
||||||
fs.setCount(j, Short.MAX_VALUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.getBiomeArray()[((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();
|
|
||||||
BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos
|
|
||||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
|
||||||
if (tileEntity != null) {
|
|
||||||
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag);
|
|
||||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refreshChunk(FaweChunk fc) {
|
public void refreshChunk(FaweChunk fc) {
|
||||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||||
@ -563,7 +360,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
nmsWorld.checkLight(pos);
|
nmsWorld.checkLight(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorldServer nmsWorld;
|
protected WorldServer nmsWorld;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World getImpWorld() {
|
public World getImpWorld() {
|
||||||
|
@ -118,6 +118,11 @@ public class FaweForge implements IFawe {
|
|||||||
return new ForgeQueue_All(world);
|
return new ForgeQueue_All(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||||
|
return new ForgeQueue_All(world);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<FaweMaskManager> getMaskManagers() {
|
public Collection<FaweMaskManager> getMaskManagers() {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
@ -1,19 +1,42 @@
|
|||||||
package com.boydti.fawe.forge.v0;
|
package com.boydti.fawe.forge.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.object.BytePair;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
|
import com.boydti.fawe.util.MathMan;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.ListTag;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.state.IBlockState;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityList;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.BitArray;
|
import net.minecraft.util.BitArray;
|
||||||
|
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.chunk.BlockStateContainer;
|
import net.minecraft.world.chunk.BlockStateContainer;
|
||||||
import net.minecraft.world.chunk.BlockStatePaletteRegistry;
|
import net.minecraft.world.chunk.BlockStatePaletteRegistry;
|
||||||
import net.minecraft.world.chunk.Chunk;
|
import net.minecraft.world.chunk.Chunk;
|
||||||
import net.minecraft.world.chunk.IBlockStatePalette;
|
import net.minecraft.world.chunk.IBlockStatePalette;
|
||||||
|
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||||
|
|
||||||
public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
public class ForgeChunk_All extends CharFaweChunk<Chunk, ForgeQueue_All> {
|
||||||
|
|
||||||
public BlockStateContainer[] sectionPalettes;
|
public BlockStateContainer[] sectionPalettes;
|
||||||
|
|
||||||
@ -35,7 +58,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
public ForgeChunk_All copy(boolean shallow) {
|
||||||
ForgeChunk_All value = (ForgeChunk_All) super.copy(shallow);
|
ForgeChunk_All value = (ForgeChunk_All) super.copy(shallow);
|
||||||
if (sectionPalettes != null) {
|
if (sectionPalettes != null) {
|
||||||
value.sectionPalettes = new BlockStateContainer[16];
|
value.sectionPalettes = new BlockStateContainer[16];
|
||||||
@ -111,4 +134,212 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ForgeChunk_All call() {
|
||||||
|
net.minecraft.world.chunk.Chunk nmsChunk = this.getChunk();
|
||||||
|
nmsChunk.setModified(true);
|
||||||
|
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
||||||
|
try {
|
||||||
|
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||||
|
// Sections
|
||||||
|
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||||
|
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||||
|
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||||
|
|
||||||
|
|
||||||
|
// Remove entities
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
int count = this.getCount(i);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
||||||
|
} else {
|
||||||
|
char[] array = this.getIdArray(i);
|
||||||
|
Collection<Entity> ents = new ArrayList<>(entities[i]);
|
||||||
|
for (Entity entity : ents) {
|
||||||
|
if (entity instanceof EntityPlayer) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int x = ((int) Math.round(entity.posX) & 15);
|
||||||
|
int z = ((int) Math.round(entity.posZ) & 15);
|
||||||
|
int y = (int) Math.round(entity.posY);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 0) {
|
||||||
|
nmsWorld.removeEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set entities
|
||||||
|
Set<UUID> createdEntities = new HashSet<>();
|
||||||
|
Set<CompoundTag> entitiesToSpawn = this.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();
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||||
|
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
|
||||||
|
if (entity != null) {
|
||||||
|
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
||||||
|
nmsWorld.spawnEntityInWorld(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Run change task if applicable
|
||||||
|
if (getParent().getChangeTask() != null) {
|
||||||
|
CharFaweChunk previous = getParent().getPrevious(this, sections, tiles, entities, createdEntities, false);
|
||||||
|
getParent().getChangeTask().run(previous, this);
|
||||||
|
}
|
||||||
|
// Trim tiles
|
||||||
|
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||||
|
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||||
|
BlockPos pos = tile.getKey();
|
||||||
|
int lx = pos.getX() & 15;
|
||||||
|
int ly = pos.getY();
|
||||||
|
int lz = pos.getZ() & 15;
|
||||||
|
int j = FaweCache.CACHE_I[ly][lz][lx];
|
||||||
|
char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int k = FaweCache.CACHE_J[ly][lz][lx];
|
||||||
|
if (array[k] != 0) {
|
||||||
|
tile.getValue().invalidate();;
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HashSet<UUID> entsToRemove = this.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Efficiently merge sections
|
||||||
|
for (int j = 0; j < sections.length; j++) {
|
||||||
|
int count = this.getCount(j);
|
||||||
|
if (count == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final char[] array = this.getIdArray(j);
|
||||||
|
if (array == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ExtendedBlockStorage section = sections[j];
|
||||||
|
if (section == null) {
|
||||||
|
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||||
|
section = sections[j] = new ExtendedBlockStorage(j << 4, flag);
|
||||||
|
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||||
|
getParent().setCount(0, count - this.getAir(j), section);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
||||||
|
}
|
||||||
|
} else if (count >= 4096) {
|
||||||
|
if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
|
||||||
|
getParent().setPalette(section, this.sectionPalettes[j]);
|
||||||
|
getParent().setCount(0, count - this.getAir(j), section);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlockStateContainer nibble = section.getData();
|
||||||
|
int nonEmptyBlockCount = 0;
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
|
||||||
|
switch (combinedId) {
|
||||||
|
case 0:
|
||||||
|
IBlockState existing = nibble.get(x, y, z);
|
||||||
|
if (existing != ForgeQueue_All.air) {
|
||||||
|
nonEmptyBlockCount++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case 1:
|
||||||
|
nibble.set(x, y, z, ForgeQueue_All.air);
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
nonEmptyBlockCount++;
|
||||||
|
nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getParent().setCount(0, nonEmptyBlockCount, section);
|
||||||
|
}
|
||||||
|
// Set biomes
|
||||||
|
int[][] biomes = this.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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set tiles
|
||||||
|
Map<BytePair, CompoundTag> tilesToSpawn = this.getTiles();
|
||||||
|
int bx = this.getX() << 4;
|
||||||
|
int bz = this.getZ() << 4;
|
||||||
|
|
||||||
|
for (Map.Entry<BytePair, CompoundTag> entry : tilesToSpawn.entrySet()) {
|
||||||
|
CompoundTag nativeTag = entry.getValue();
|
||||||
|
BytePair pair = entry.getKey();
|
||||||
|
BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos
|
||||||
|
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
||||||
|
if (tileEntity != null) {
|
||||||
|
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
|
||||||
|
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
MainUtil.handleError(e);
|
||||||
|
}
|
||||||
|
int[][] biomes = this.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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,21 @@
|
|||||||
package com.boydti.fawe.forge.v0;
|
package com.boydti.fawe.forge.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;
|
||||||
import com.boydti.fawe.object.BytePair;
|
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
|
||||||
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.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -57,11 +50,20 @@ import net.minecraftforge.common.DimensionManager;
|
|||||||
|
|
||||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||||
|
|
||||||
private static Method methodFromNative;
|
protected static Method methodFromNative;
|
||||||
private static Method methodToNative;
|
protected static Method methodToNative;
|
||||||
|
|
||||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||||
super(world);
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForgeQueue_All(String world) {
|
||||||
|
super(world);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
if (methodFromNative == null) {
|
if (methodFromNative == null) {
|
||||||
try {
|
try {
|
||||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||||
@ -76,7 +78,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
getImpWorld();
|
getImpWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
public CompoundTag getTileEntity(Chunk chunk, int x, int y, int z) {
|
||||||
@ -291,216 +293,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
return previous;
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final IBlockState air = Blocks.AIR.getDefaultState();
|
protected final static IBlockState air = Blocks.AIR.getDefaultState();
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
|
||||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
|
||||||
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
|
|
||||||
nmsChunk.setModified(true);
|
|
||||||
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
|
||||||
try {
|
|
||||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
|
||||||
// Sections
|
|
||||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
|
||||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
|
||||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
|
||||||
|
|
||||||
|
|
||||||
// Remove entities
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
int count = fs.getCount(i);
|
|
||||||
if (count == 0) {
|
|
||||||
continue;
|
|
||||||
} else if (count >= 4096) {
|
|
||||||
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
|
||||||
} 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.posX) & 15);
|
|
||||||
int z = ((int) Math.round(entity.posZ) & 15);
|
|
||||||
int y = (int) Math.round(entity.posY);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (y < 0 || y > 255 || array[FaweCache.CACHE_J[y][z][x]] != 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();
|
|
||||||
NBTTagCompound tag = (NBTTagCompound)methodFromNative.invoke(null, nativeTag);
|
|
||||||
Entity entity = EntityList.createEntityFromNBT(tag, nmsWorld);
|
|
||||||
if (entity != null) {
|
|
||||||
entity.setPositionAndRotation(x, y, z, yaw, pitch);
|
|
||||||
nmsWorld.spawnEntityInWorld(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Run change task if applicable
|
|
||||||
if (changeTask != null) {
|
|
||||||
CharFaweChunk previous = getPrevious(fs, sections, tiles, entities, createdEntities, false);
|
|
||||||
changeTask.run(previous);
|
|
||||||
}
|
|
||||||
// Trim tiles
|
|
||||||
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
|
||||||
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
|
||||||
BlockPos pos = tile.getKey();
|
|
||||||
int lx = pos.getX() & 15;
|
|
||||||
int ly = pos.getY();
|
|
||||||
int lz = pos.getZ() & 15;
|
|
||||||
int j = FaweCache.CACHE_I[ly][lz][lx];
|
|
||||||
char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int k = FaweCache.CACHE_J[ly][lz][lx];
|
|
||||||
if (array[k] != 0) {
|
|
||||||
tile.getValue().invalidate();;
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Efficiently merge sections
|
|
||||||
for (int j = 0; j < sections.length; j++) {
|
|
||||||
int count = fs.getCount(j);
|
|
||||||
if (count == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final char[] array = fs.getIdArray(j);
|
|
||||||
if (array == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ExtendedBlockStorage section = sections[j];
|
|
||||||
if (section == null) {
|
|
||||||
if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) {
|
|
||||||
section = sections[j] = new ExtendedBlockStorage(j << 4, flag);
|
|
||||||
setPalette(section, fs.sectionPalettes[j]);
|
|
||||||
setCount(0, count - fs.getAir(j), section);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
|
||||||
}
|
|
||||||
} else if (count >= 4096) {
|
|
||||||
if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) {
|
|
||||||
setPalette(section, fs.sectionPalettes[j]);
|
|
||||||
setCount(0, count - fs.getAir(j), section);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
sections[j] = section = new ExtendedBlockStorage(j << 4, flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BlockStateContainer nibble = section.getData();
|
|
||||||
int nonEmptyBlockCount = 0;
|
|
||||||
for (int y = 0; y < 16; y++) {
|
|
||||||
for (int z = 0; z < 16; z++) {
|
|
||||||
for (int x = 0; x < 16; x++) {
|
|
||||||
char combinedId = array[FaweCache.CACHE_J[y][z][x]];
|
|
||||||
switch (combinedId) {
|
|
||||||
case 0:
|
|
||||||
IBlockState existing = nibble.get(x, y, z);
|
|
||||||
if (existing != air) {
|
|
||||||
nonEmptyBlockCount++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
case 1:
|
|
||||||
nibble.set(x, y, z, air);
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
nonEmptyBlockCount++;
|
|
||||||
nibble.set(x, y, z, Block.getBlockById(combinedId >> 4).getStateFromMeta(combinedId & 0xF));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCount(0, nonEmptyBlockCount, section);
|
|
||||||
}
|
|
||||||
// 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.getBiomeArray()[((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();
|
|
||||||
BlockPos pos = new BlockPos(MathMan.unpair16x((byte) pair.get0()) + bx, pair.get1() & 0xFF, MathMan.unpair16y((byte) pair.get0()) + bz); // Set pos
|
|
||||||
TileEntity tileEntity = nmsWorld.getTileEntity(pos);
|
|
||||||
if (tileEntity != null) {
|
|
||||||
NBTTagCompound tag = (NBTTagCompound) methodFromNative.invoke(null, nativeTag);
|
|
||||||
tileEntity.readFromNBT(tag); // ReadTagIntoTile
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
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.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException {
|
public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException {
|
||||||
Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data");
|
Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data");
|
||||||
@ -602,7 +395,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
nmsWorld.checkLight(pos);
|
nmsWorld.checkLight(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorldServer nmsWorld;
|
protected WorldServer nmsWorld;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World getImpWorld() {
|
public World getImpWorld() {
|
||||||
|
@ -193,6 +193,13 @@ public class NukkitPlayerBlockBag extends BlockBag {
|
|||||||
player.getInventory().setContents(items);
|
player.getInventory().setContents(items);
|
||||||
items = null;
|
items = null;
|
||||||
player.getInventory().sendContents(player);
|
player.getInventory().sendContents(player);
|
||||||
|
player.getInventory().sendContents(player);
|
||||||
|
player.getInventory().sendContents(player);
|
||||||
|
player.getInventory().sendContents(player);
|
||||||
|
player.getInventory().sendContents(player);
|
||||||
|
player.getInventory().sendContents(player);
|
||||||
|
player.getInventory().sendContents(player);
|
||||||
|
player.getInventory().sendContents(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,9 +4,6 @@ import cn.nukkit.Player;
|
|||||||
import cn.nukkit.event.EventHandler;
|
import cn.nukkit.event.EventHandler;
|
||||||
import cn.nukkit.event.Listener;
|
import cn.nukkit.event.Listener;
|
||||||
import cn.nukkit.event.player.PlayerQuitEvent;
|
import cn.nukkit.event.player.PlayerQuitEvent;
|
||||||
import cn.nukkit.event.server.DataPacketSendEvent;
|
|
||||||
import cn.nukkit.network.protocol.DataPacket;
|
|
||||||
import cn.nukkit.network.protocol.TextPacket;
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.IFawe;
|
import com.boydti.fawe.IFawe;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
@ -39,24 +36,6 @@ public class FaweNukkit implements IFawe, Listener {
|
|||||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onDataPacketSend(DataPacketSendEvent event) {
|
|
||||||
DataPacket packet = event.getPacket();
|
|
||||||
if (packet instanceof TextPacket) {
|
|
||||||
TextPacket textPacket = (TextPacket) packet;
|
|
||||||
int len = textPacket.message.length();
|
|
||||||
int lineWidth = 52;
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
for (int i = 0; i < textPacket.message.length(); i++) {
|
|
||||||
if (i % 52 == 0) {
|
|
||||||
builder.append((char) 1566);
|
|
||||||
}
|
|
||||||
builder.append(textPacket.message.charAt(i));
|
|
||||||
}
|
|
||||||
textPacket.message = builder.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
@ -121,6 +100,11 @@ public class FaweNukkit implements IFawe, Listener {
|
|||||||
return new NukkitQueue(this, world);
|
return new NukkitQueue(this, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaweQueue getNewQueue(String world, boolean fast) {
|
||||||
|
return new NukkitQueue(this, world);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getWorldName(World world) {
|
public String getWorldName(World world) {
|
||||||
return world.getName();
|
return world.getName();
|
||||||
|
@ -16,7 +16,7 @@ import com.sk89q.worldedit.Vector2D;
|
|||||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class NukkitChunk extends CharFaweChunk<BaseFullChunk> {
|
public class NukkitChunk extends CharFaweChunk<BaseFullChunk, NukkitQueue> {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,7 +39,8 @@ public class NukkitChunk extends CharFaweChunk<BaseFullChunk> {
|
|||||||
private int index;
|
private int index;
|
||||||
private boolean place = true;
|
private boolean place = true;
|
||||||
|
|
||||||
public void execute() {
|
@Override
|
||||||
|
public NukkitChunk call() {
|
||||||
NukkitQueue parent = (NukkitQueue) getParent();
|
NukkitQueue parent = (NukkitQueue) getParent();
|
||||||
Level world = ((NukkitQueue) getParent()).getWorld();
|
Level world = ((NukkitQueue) getParent()).getWorld();
|
||||||
world.clearCache(true);
|
world.clearCache(true);
|
||||||
@ -113,5 +114,6 @@ public class NukkitChunk extends CharFaweChunk<BaseFullChunk> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,7 +14,6 @@ import com.boydti.fawe.example.NMSMappedFaweQueue;
|
|||||||
import com.boydti.fawe.nukkit.core.NBTConverter;
|
import com.boydti.fawe.nukkit.core.NBTConverter;
|
||||||
import com.boydti.fawe.nukkit.optimization.FaweNukkit;
|
import com.boydti.fawe.nukkit.optimization.FaweNukkit;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
@ -25,8 +24,8 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFullChunk, BaseFullChunk> {
|
public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFullChunk, BaseFullChunk> {
|
||||||
private final FaweNukkit faweNukkit;
|
private FaweNukkit faweNukkit;
|
||||||
private final Level world;
|
private Level world;
|
||||||
|
|
||||||
public static int ALLOCATE;
|
public static int ALLOCATE;
|
||||||
public static double TPS_TARGET = 18.5;
|
public static double TPS_TARGET = 18.5;
|
||||||
@ -34,6 +33,15 @@ public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFu
|
|||||||
|
|
||||||
public NukkitQueue(FaweNukkit fn, World world) {
|
public NukkitQueue(FaweNukkit fn, World world) {
|
||||||
super(world);
|
super(world);
|
||||||
|
init(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NukkitQueue(FaweNukkit fn, String world) {
|
||||||
|
super(world);
|
||||||
|
init(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(FaweNukkit fn) {
|
||||||
this.faweNukkit = fn;
|
this.faweNukkit = fn;
|
||||||
this.world = faweNukkit.getPlugin().getServer().getLevelByName(getWorldName());
|
this.world = faweNukkit.getPlugin().getServer().getLevelByName(getWorldName());
|
||||||
if (Settings.QUEUE.EXTRA_TIME_MS != Integer.MIN_VALUE) {
|
if (Settings.QUEUE.EXTRA_TIME_MS != Integer.MIN_VALUE) {
|
||||||
@ -90,12 +98,6 @@ public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFu
|
|||||||
|
|
||||||
private int skip;
|
private int skip;
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
|
||||||
((NukkitChunk) fc).execute();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getSaveFolder() {
|
public File getSaveFolder() {
|
||||||
return new File("worlds" + File.separator + world.getFolderName() + File.separator + "region");
|
return new File("worlds" + File.separator + world.getFolderName() + File.separator + "region");
|
||||||
|
Loading…
Reference in New Issue
Block a user