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(String world);
|
||||
}
|
@ -150,6 +150,47 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
private boolean hasNMS = true;
|
||||
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 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.config.Settings;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -17,7 +18,7 @@ import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
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.
|
||||
@ -39,17 +40,23 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk> {
|
||||
private int index;
|
||||
private boolean place = true;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
getChunk().load(true);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public void execute(long start) {
|
||||
@Override
|
||||
public FaweChunk call() {
|
||||
long start = System.currentTimeMillis();
|
||||
int recommended = 25 + BukkitQueue_All.ALLOCATE;
|
||||
boolean more = true;
|
||||
BukkitQueue_All parent = (BukkitQueue_All) getParent();
|
||||
final Chunk chunk = getChunk();
|
||||
Object[] disableResult = parent.disableLighting(chunk);
|
||||
chunk.load(true);
|
||||
final World world = chunk.getWorld();
|
||||
char[][] sections = getCombinedIdArrays();
|
||||
if (layer == -1) {
|
||||
@ -220,6 +227,7 @@ public class BukkitChunk_All extends CharFaweChunk<Chunk> {
|
||||
this.addToQueue();
|
||||
}
|
||||
parent.resetLighting(disableResult);
|
||||
return this;
|
||||
}
|
||||
|
||||
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
|
||||
public File getSaveFolder() {
|
||||
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) {}
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
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) {
|
||||
ALLOCATE = Settings.QUEUE.EXTRA_TIME_MS;
|
||||
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;
|
||||
|
||||
@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
|
||||
public void startSet(boolean parallel) {
|
||||
super.startSet(true);
|
||||
|
@ -129,7 +129,7 @@ public class AsyncWorld implements World {
|
||||
* @return
|
||||
*/
|
||||
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);
|
||||
return wrap(world);
|
||||
}
|
||||
|
@ -1,20 +1,49 @@
|
||||
package com.boydti.fawe.bukkit.v1_10;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
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.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.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.BlockPosition;
|
||||
import net.minecraft.server.v1_10_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_10_R1.DataBits;
|
||||
import net.minecraft.server.v1_10_R1.DataPalette;
|
||||
import net.minecraft.server.v1_10_R1.DataPaletteBlock;
|
||||
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.NBTTagCompound;
|
||||
import net.minecraft.server.v1_10_R1.TileEntity;
|
||||
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;
|
||||
|
||||
@ -35,7 +64,7 @@ public class BukkitChunk_1_10 extends CharFaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@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);
|
||||
if (sectionPalettes != null) {
|
||||
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.v0.BukkitQueue_0;
|
||||
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.FastByteArrayInputStream;
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
@ -31,6 +32,11 @@ public class BukkitMain_110 extends ABukkitMain {
|
||||
return new BukkitQueue_1_10(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getQueue(String world) {
|
||||
return new BukkitQueue_1_10(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
super.onEnable();
|
||||
|
@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
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.TaskManager;
|
||||
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.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
import net.minecraft.server.v1_10_R1.Block;
|
||||
import net.minecraft.server.v1_10_R1.BlockPosition;
|
||||
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.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.craftbukkit.v1_10_R1.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
|
||||
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.WorldLoadEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
|
||||
|
||||
private static IBlockData air;
|
||||
private static Field fieldBits;
|
||||
private static Method getEntitySlices;
|
||||
protected static IBlockData air;
|
||||
protected static Field fieldBits;
|
||||
protected static Method getEntitySlices;
|
||||
|
||||
public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE];
|
||||
|
||||
public BukkitQueue_1_10(final com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
public BukkitQueue_1_10(final String world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
checkVersion("v1_10_R1");
|
||||
if (air == null) {
|
||||
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
|
||||
public void setSkyLight(ChunkSection section, int x, int y, int z, int 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);
|
||||
}
|
||||
|
||||
private DataBits lastBits;
|
||||
private DataPaletteBlock lastBlocks;
|
||||
protected DataBits lastBits;
|
||||
protected DataPaletteBlock lastBlocks;
|
||||
|
||||
@Override
|
||||
public World createWorld(final WorldCreator creator) {
|
||||
@ -354,7 +358,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
||||
nmsWorld.w(pos);
|
||||
}
|
||||
|
||||
private WorldServer nmsWorld;
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
@ -402,10 +406,10 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
||||
}
|
||||
|
||||
@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;
|
||||
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
|
||||
char[][] idPrevious = new char[16][];
|
||||
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;
|
||||
}
|
||||
|
||||
private BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
||||
protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@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
|
||||
public boolean unloadChunk(final String world, final Chunk chunk) {
|
||||
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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,41 @@
|
||||
package com.boydti.fawe.bukkit.v1_7;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
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.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.TileEntity;
|
||||
import org.bukkit.Bukkit;
|
||||
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
|
||||
public Chunk getNewChunk() {
|
||||
@ -87,7 +114,7 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@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());
|
||||
if (shallow) {
|
||||
copy.byteIds = byteIds;
|
||||
@ -108,4 +135,232 @@ public class BukkitChunk_1_7 extends CharFaweChunk<Chunk> {
|
||||
}
|
||||
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.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
public class BukkitMain_17 extends ABukkitMain {
|
||||
@ -10,4 +11,9 @@ public class BukkitMain_17 extends ABukkitMain {
|
||||
public BukkitQueue_0 getQueue(World 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;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
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.TaskManager;
|
||||
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.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
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.CraftServer;
|
||||
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.WorldLoadEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
|
||||
|
||||
private static Field fieldData;
|
||||
private static Field fieldIds;
|
||||
protected static Field fieldData;
|
||||
protected static Field fieldIds;
|
||||
|
||||
public BukkitQueue17(final com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
public BukkitQueue17(final String world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
checkVersion("v1_7_R4");
|
||||
if (fieldData == null) {
|
||||
try {
|
||||
@ -236,230 +237,6 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
|
||||
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 {
|
||||
Class<? extends ChunkSection> clazz = section.getClass();
|
||||
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
|
||||
@ -625,7 +402,7 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
|
||||
nmsWorld.t(x, y, z);
|
||||
}
|
||||
|
||||
private WorldServer nmsWorld;
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
|
@ -1,11 +1,39 @@
|
||||
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.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
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.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.
|
||||
*
|
||||
@ -21,4 +49,208 @@ public class BukkitChunk_1_8 extends CharFaweChunk<Chunk> {
|
||||
public Chunk getNewChunk() {
|
||||
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.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
public class BukkitMain_18 extends ABukkitMain {
|
||||
@ -10,4 +11,9 @@ public class BukkitMain_18 extends ABukkitMain {
|
||||
public BukkitQueue_0 getQueue(World 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.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
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.TaskManager;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||
import com.sk89q.worldedit.internal.Constants;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
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.CraftServer;
|
||||
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.WorldLoadEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
@ -74,6 +66,11 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
|
||||
checkVersion("v1_8_R3");
|
||||
}
|
||||
|
||||
public BukkitQueue18R3(final String world) {
|
||||
super(world);
|
||||
checkVersion("v1_8_R3");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupAdapter(BukkitImplAdapter adapter) {
|
||||
if (this.adapter == null) {
|
||||
@ -235,206 +232,6 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
|
||||
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 {
|
||||
Class<? extends ChunkSection> clazz = section.getClass();
|
||||
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
|
||||
|
@ -1,20 +1,51 @@
|
||||
package com.boydti.fawe.bukkit.v1_9;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
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.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.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.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.DataPalette;
|
||||
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
|
||||
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.NBTTagCompound;
|
||||
import net.minecraft.server.v1_9_R2.TileEntity;
|
||||
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;
|
||||
|
||||
@ -35,7 +66,7 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
||||
public BukkitChunk_1_9 copy(boolean shallow) {
|
||||
BukkitChunk_1_9 value = (BukkitChunk_1_9) super.copy(shallow);
|
||||
if (sectionPalettes != null) {
|
||||
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.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
public class BukkitMain_19 extends ABukkitMain {
|
||||
@ -9,4 +10,9 @@ public class BukkitMain_19 extends ABukkitMain {
|
||||
public BukkitQueue_0 getQueue(World 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.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
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.TaskManager;
|
||||
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.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
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.DataPalette;
|
||||
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
|
||||
import net.minecraft.server.v1_9_R2.Entity;
|
||||
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.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.craftbukkit.v1_9_R2.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_9_R2.CraftServer;
|
||||
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.WorldLoadEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSection> {
|
||||
|
||||
private static IBlockData air;
|
||||
private static Field fieldBits;
|
||||
protected static IBlockData air;
|
||||
protected static Field fieldBits;
|
||||
|
||||
public BukkitQueue_1_9_R1(final com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
public BukkitQueue_1_9_R1(final String world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
checkVersion("v1_9_R2");
|
||||
if (air == null) {
|
||||
try {
|
||||
@ -287,7 +282,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
|
||||
nmsWorld.w(pos);
|
||||
}
|
||||
|
||||
private WorldServer nmsWorld;
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
@ -442,7 +437,7 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
|
||||
return previous;
|
||||
}
|
||||
|
||||
private BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
||||
protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@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
|
||||
public boolean unloadChunk(final String world, final Chunk chunk) {
|
||||
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());
|
||||
}
|
||||
|
||||
private DataBits lastBits;
|
||||
private DataPaletteBlock lastBlocks;
|
||||
protected DataBits lastBits;
|
||||
protected DataPaletteBlock lastBlocks;
|
||||
|
||||
@Override
|
||||
public void relightBlock(int x, int y, int z) {
|
||||
|
@ -435,7 +435,7 @@ public class Fawe {
|
||||
}
|
||||
|
||||
private void setupMemoryListener() {
|
||||
if (Settings.MAX_MEMORY_PERCENT < 1) {
|
||||
if (Settings.MAX_MEMORY_PERCENT < 1 || Settings.MAX_MEMORY_PERCENT > 99) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
@ -98,9 +98,8 @@ public class FaweAPI {
|
||||
return FawePlayer.wrap(obj);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
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(String world, boolean fast);
|
||||
|
||||
public String getWorldName(World world);
|
||||
|
||||
public Collection<FaweMaskManager> getMaskManagers();
|
||||
|
@ -15,7 +15,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
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 short[] count;
|
||||
@ -47,6 +47,11 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
||||
this.relight = new short[HEIGHT >> 4];
|
||||
}
|
||||
|
||||
@Override
|
||||
public V getParent() {
|
||||
return (V) super.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getChunk() {
|
||||
if (this.chunk == null) {
|
||||
@ -358,8 +363,8 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk<T> copy(boolean shallow) {
|
||||
CharFaweChunk<T> copy = (CharFaweChunk<T>) getParent().getFaweChunk(getX(), getZ());
|
||||
public CharFaweChunk<T, V> copy(boolean shallow) {
|
||||
CharFaweChunk<T, V> copy = (CharFaweChunk<T, V>) getParent().getFaweChunk(getX(), getZ());
|
||||
if (shallow) {
|
||||
copy.ids = ids;
|
||||
copy.air = air;
|
||||
|
@ -3,12 +3,13 @@ package com.boydti.fawe.example;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
|
||||
public class DefaultFaweQueueMap implements IFaweQueueMap {
|
||||
|
||||
@ -21,26 +22,25 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
|
||||
/**
|
||||
* Map of chunks in the queue
|
||||
*/
|
||||
public ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<>(8, 0.9f, 1);
|
||||
public ConcurrentLinkedDeque<FaweChunk> chunks = new ConcurrentLinkedDeque<FaweChunk>() {
|
||||
public ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<Long, FaweChunk>(8, 0.9f, 1) {
|
||||
@Override
|
||||
public boolean add(FaweChunk o) {
|
||||
public FaweChunk put(Long key, FaweChunk value) {
|
||||
if (parent.getProgressTask() != null) {
|
||||
parent.getProgressTask().run(FaweQueue.ProgressType.QUEUE, size() + 1);
|
||||
}
|
||||
return super.add(o);
|
||||
return super.put(key, value);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Collection<FaweChunk> getFaweCunks() {
|
||||
return new HashSet<>(chunks);
|
||||
return new HashSet<>(blocks.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachChunk(RunnableVal<FaweChunk> onEach) {
|
||||
for (FaweChunk chunk : chunks) {
|
||||
onEach.run(chunk);
|
||||
for (Map.Entry<Long, FaweChunk> entry : blocks.entrySet()) {
|
||||
onEach.run(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,6 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
|
||||
return previous;
|
||||
}
|
||||
this.blocks.put(pair, chunk);
|
||||
chunks.add(chunk);
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
@ -77,9 +76,7 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
|
||||
public void add(FaweChunk chunk) {
|
||||
long pair = MathMan.pairInt(chunk.getX(), chunk.getZ());
|
||||
FaweChunk previous = this.blocks.put(pair, chunk);
|
||||
if (previous == null) {
|
||||
chunks.add(chunk);
|
||||
} else {
|
||||
if (previous != null) {
|
||||
blocks.put(pair, previous);
|
||||
}
|
||||
}
|
||||
@ -88,12 +85,11 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
|
||||
@Override
|
||||
public void clear() {
|
||||
blocks.clear();
|
||||
chunks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return chunks.size();
|
||||
return blocks.size();
|
||||
}
|
||||
|
||||
private FaweChunk getNewFaweChunk(int cx, int cz) {
|
||||
@ -105,24 +101,59 @@ public class DefaultFaweQueueMap implements IFaweQueueMap {
|
||||
private int lastZ = Integer.MIN_VALUE;
|
||||
|
||||
@Override
|
||||
public boolean next() {
|
||||
public boolean next(int amount, ExecutorCompletionService pool, long time) {
|
||||
lastWrappedChunk = null;
|
||||
lastX = Integer.MIN_VALUE;
|
||||
lastZ = Integer.MIN_VALUE;
|
||||
try {
|
||||
if (this.blocks.isEmpty()) {
|
||||
return false;
|
||||
int added = 0;
|
||||
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) {
|
||||
FaweChunk chunk = chunks.poll();
|
||||
if (chunk != null) {
|
||||
blocks.remove(chunk.longHash());
|
||||
parent.execute(chunk);
|
||||
return true;
|
||||
boolean result = true;
|
||||
for (int i = 0; i < amount && (result = iter.hasNext()); i++, added++) {
|
||||
Map.Entry<Long, FaweChunk> item = iter.next();
|
||||
FaweChunk chunk = item.getValue();
|
||||
parent.start(chunk);
|
||||
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) {
|
||||
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.RunnableVal;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
|
||||
public interface IFaweQueueMap {
|
||||
|
||||
@ -20,5 +21,5 @@ public interface IFaweQueueMap {
|
||||
|
||||
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.UUID;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -36,6 +37,11 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
this(world, null);
|
||||
}
|
||||
|
||||
public MappedFaweQueue(final String world) {
|
||||
super(world);
|
||||
map = new DefaultFaweQueueMap(this);
|
||||
}
|
||||
|
||||
public MappedFaweQueue(final World world, IFaweQueueMap map) {
|
||||
super(world);
|
||||
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 setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask);
|
||||
|
||||
@Override
|
||||
public abstract FaweChunk getFaweChunk(int x, int z);
|
||||
|
||||
@ -192,10 +196,19 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean next() {
|
||||
return map.next();
|
||||
public boolean next(int amount, ExecutorCompletionService pool, long time) {
|
||||
return map.next(amount, pool, time);
|
||||
}
|
||||
|
||||
public void start(FaweChunk chunk) {
|
||||
chunk.start();
|
||||
}
|
||||
|
||||
public void end(FaweChunk chunk) {
|
||||
chunk.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runTasks() {
|
||||
if (getProgressTask() != null) {
|
||||
getProgressTask().run(ProgressType.DONE, 1);
|
||||
@ -224,31 +237,6 @@ public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
|
||||
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
|
||||
public void clear() {
|
||||
map.clear();
|
||||
|
@ -22,6 +22,12 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
||||
addRelightTask();
|
||||
}
|
||||
|
||||
public NMSMappedFaweQueue(String world) {
|
||||
super(world);
|
||||
this.maxY = 256;
|
||||
addRelightTask();
|
||||
}
|
||||
|
||||
public NMSMappedFaweQueue(World world, IFaweQueueMap map) {
|
||||
super(world, map);
|
||||
this.maxY = world.getMaxY();
|
||||
@ -47,35 +53,32 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
||||
private NMSRelighter relighter;
|
||||
|
||||
@Override
|
||||
public boolean execute(FaweChunk fc) {
|
||||
if (super.execute(fc)) {
|
||||
sendChunk(fc);
|
||||
if (Settings.LIGHTING.MODE == 0) {
|
||||
return true;
|
||||
public void end(FaweChunk chunk) {
|
||||
super.end(chunk);
|
||||
if (Settings.LIGHTING.MODE == 0) {
|
||||
return;
|
||||
}
|
||||
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 (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;
|
||||
}
|
||||
if (relight) {
|
||||
relighter.addChunk(chunk.getX(), chunk.getZ(), fix);
|
||||
} else {
|
||||
return false;
|
||||
refreshChunk(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,4 +92,9 @@ public class NullFaweChunk extends FaweChunk<Void> {
|
||||
public FaweChunk<Void> copy(boolean shallow) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk call() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -402,4 +402,9 @@ public class MCAChunk extends FaweChunk<Void> {
|
||||
public Void getChunk() {
|
||||
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.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.RunnableVal4;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -141,11 +140,6 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk getPrevious(CharFaweChunk fs, FaweChunk sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
|
@ -14,6 +14,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
|
||||
public class MCAQueueMap implements IFaweQueueMap {
|
||||
|
||||
@ -150,20 +151,26 @@ public class MCAQueueMap implements IFaweQueueMap {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean next() {
|
||||
public boolean next(int size, ExecutorCompletionService dispatcher, long time) {
|
||||
lastX = Integer.MIN_VALUE;
|
||||
lastZ = Integer.MIN_VALUE;
|
||||
lastFileX = Integer.MIN_VALUE;
|
||||
lastFileZ = Integer.MIN_VALUE;
|
||||
if (!mcaFileMap.isEmpty()) {
|
||||
Iterator<Map.Entry<Long, MCAFile>> iter = mcaFileMap.entrySet().iterator();
|
||||
if (iter.hasNext()) {
|
||||
MCAFile file = iter.next().getValue();
|
||||
iter.remove();
|
||||
file.flush();
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
boolean result;
|
||||
long start = System.currentTimeMillis();
|
||||
do {
|
||||
if (result = iter.hasNext()) {
|
||||
MCAFile file = iter.next().getValue();
|
||||
iter.remove();
|
||||
file.flush();
|
||||
file.close();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (System.currentTimeMillis() - start < time);
|
||||
return result;
|
||||
}
|
||||
if (isHybridQueue) {
|
||||
boolean value = queue.next();
|
||||
|
@ -9,8 +9,9 @@ import java.util.ArrayDeque;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
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 int x,z;
|
||||
@ -267,4 +268,11 @@ public abstract class FaweChunk<T> {
|
||||
}
|
||||
|
||||
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");
|
||||
fieldPlayer.setAccessible(true);
|
||||
return wrap(fieldPlayer.get(actor));
|
||||
} catch (Throwable e) {
|
||||
MainUtil.handleError(e);
|
||||
return Fawe.imp().wrap(actor.getName());
|
||||
}
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
}
|
||||
if (obj instanceof Actor) {
|
||||
|
@ -1,8 +1,10 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweAPI;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
@ -23,6 +25,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public abstract class FaweQueue {
|
||||
@ -34,6 +37,10 @@ public abstract class FaweQueue {
|
||||
private RunnableVal2<FaweChunk, FaweChunk> changeTask;
|
||||
private RunnableVal2<ProgressType, Integer> progressTask;
|
||||
|
||||
public FaweQueue(String world) {
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public FaweQueue(World world) {
|
||||
this.weWorld = world;
|
||||
this.world = Fawe.imp().getWorldName(world);
|
||||
@ -62,7 +69,7 @@ public abstract class FaweQueue {
|
||||
}
|
||||
|
||||
public World getWEWorld() {
|
||||
return weWorld;
|
||||
return weWorld != null ? weWorld : (weWorld = FaweAPI.getWorld(world));
|
||||
}
|
||||
|
||||
public String getWorldName() {
|
||||
@ -226,11 +233,19 @@ public abstract class FaweQueue {
|
||||
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
|
||||
* @return
|
||||
*/
|
||||
public abstract boolean next();
|
||||
public abstract boolean next(int amount, ExecutorCompletionService pool, long time);
|
||||
|
||||
public void saveMemory() {
|
||||
MainUtil.sendAdmin(BBC.OOM.s());
|
||||
@ -369,6 +384,8 @@ public abstract class FaweQueue {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void runTasks();
|
||||
|
||||
public boolean enqueue() {
|
||||
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 {
|
||||
// If it's going to fail, throw an error now rather than later
|
||||
QueueProvider provider = QueueProvider.of(FaweLocalBlockQueue.class, null);
|
||||
GlobalBlockQueue.IMP.setProvider(provider);
|
||||
GlobalBlockQueue.IMP = new GlobalBlockQueue(provider, 1);
|
||||
HybridPlotManager.REGENERATIVE_CLEAR = false;
|
||||
Fawe.debug(" - QueueProvider: " + FaweLocalBlockQueue.class);
|
||||
Fawe.debug(" - HybridPlotManager.REGENERATIVE_CLEAR: " + HybridPlotManager.REGENERATIVE_CLEAR);
|
||||
|
@ -12,6 +12,7 @@ import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
|
||||
public class DelegateFaweQueue extends FaweQueue {
|
||||
private FaweQueue parent;
|
||||
@ -169,6 +170,11 @@ public class DelegateFaweQueue extends FaweQueue {
|
||||
return parent.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean next(int amount, ExecutorCompletionService pool, long time) {
|
||||
return parent.next(amount, pool, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveMemory() {
|
||||
parent.saveMemory();
|
||||
@ -234,6 +240,11 @@ public class DelegateFaweQueue extends FaweQueue {
|
||||
return parent.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runTasks() {
|
||||
parent.runTasks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enqueue() {
|
||||
return parent.enqueue();
|
||||
|
@ -3,13 +3,13 @@ package com.boydti.fawe.util;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweQueue;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -40,23 +40,17 @@ public class SetQueue {
|
||||
*/
|
||||
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 ExecutorCompletionService completer = new ExecutorCompletionService(pool);
|
||||
|
||||
/**
|
||||
* @see TaskManager#getPublicForkJoinPool()
|
||||
* @return ForkJoinPool
|
||||
*/
|
||||
@Deprecated
|
||||
public ExecutorCompletionService getCompleterService() {
|
||||
return completer;
|
||||
}
|
||||
|
||||
public SetQueue() {
|
||||
tasks = new ConcurrentLinkedDeque<>();
|
||||
@ -65,56 +59,55 @@ public class SetQueue {
|
||||
TaskManager.IMP.repeat(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!tasks.isEmpty() && Fawe.get().getTimer().isAbove(18.5)) {
|
||||
tasks.poll().run();
|
||||
}
|
||||
if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) {
|
||||
lastSuccess = System.currentTimeMillis();
|
||||
runEmptyTasks();
|
||||
return;
|
||||
}
|
||||
if (!MemUtil.isMemoryFree()) {
|
||||
final int mem = MemUtil.calculateMemory();
|
||||
if (mem != Integer.MAX_VALUE) {
|
||||
if ((mem <= 1) && Settings.CRASH_MITIGATION) {
|
||||
for (FaweQueue queue : getAllQueues()) {
|
||||
queue.saveMemory();
|
||||
try {
|
||||
while (!tasks.isEmpty() && Fawe.get().getTimer().isAbove(18.5)) {
|
||||
tasks.poll().run();
|
||||
}
|
||||
if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) {
|
||||
lastSuccess = System.currentTimeMillis();
|
||||
runEmptyTasks();
|
||||
return;
|
||||
}
|
||||
if (!MemUtil.isMemoryFree()) {
|
||||
final int mem = MemUtil.calculateMemory();
|
||||
if (mem != Integer.MAX_VALUE) {
|
||||
if ((mem <= 1) && Settings.CRASH_MITIGATION) {
|
||||
for (FaweQueue queue : getAllQueues()) {
|
||||
queue.saveMemory();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (SetQueue.this.forceChunkSet()) {
|
||||
System.gc();
|
||||
} else {
|
||||
SetQueue.this.runEmptyTasks();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (SetQueue.this.forceChunkSet()) {
|
||||
System.gc();
|
||||
} else {
|
||||
SetQueue.this.runEmptyTasks();
|
||||
}
|
||||
}
|
||||
FaweQueue queue = getNextQueue();
|
||||
if (queue == null || !Fawe.get().getTimer().isAbove(18.5)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
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());
|
||||
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);
|
||||
if (Thread.currentThread() != Fawe.get().getMainThread()) {
|
||||
throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread");
|
||||
}
|
||||
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) {
|
||||
MainUtil.handleError(e);
|
||||
} finally {
|
||||
// Enable it again (note that we are still on the main thread)
|
||||
SET_TASK.value2.endSet(parallel);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, 1);
|
||||
@ -156,6 +149,7 @@ public class SetQueue {
|
||||
public void dequeue(FaweQueue queue) {
|
||||
inactiveQueues.remove(queue);
|
||||
activeQueues.remove(queue);
|
||||
queue.runTasks();
|
||||
}
|
||||
|
||||
public Collection<FaweQueue> getAllQueues() {
|
||||
@ -181,44 +175,34 @@ public class SetQueue {
|
||||
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) {
|
||||
SET_TASK.value1 = Long.MAX_VALUE;
|
||||
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);
|
||||
queue.startSet(Settings.QUEUE.PARALLEL_THREADS > 1);
|
||||
try {
|
||||
if (!parallel || !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);
|
||||
}
|
||||
queue.next(Settings.QUEUE.PARALLEL_THREADS, getCompleterService(), Long.MAX_VALUE);
|
||||
} catch (Throwable e) {
|
||||
pool.awaitQuiescence(Settings.QUEUE.DISCARD_AFTER_MS, TimeUnit.MILLISECONDS);
|
||||
completer = new ExecutorCompletionService(pool);
|
||||
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() {
|
||||
long now = System.currentTimeMillis();
|
||||
while (activeQueues.size() > 0) {
|
||||
while (!activeQueues.isEmpty()) {
|
||||
FaweQueue queue = activeQueues.peek();
|
||||
if (queue != null && queue.size() > 0) {
|
||||
queue.setModified(now);
|
||||
return queue;
|
||||
} else {
|
||||
queue.runTasks();
|
||||
activeQueues.poll();
|
||||
}
|
||||
}
|
||||
@ -234,6 +218,7 @@ public class SetQueue {
|
||||
total += queue.size();
|
||||
if (queue.size() == 0) {
|
||||
if (age > Settings.QUEUE.DISCARD_AFTER_MS) {
|
||||
queue.runTasks();
|
||||
iter.remove();
|
||||
}
|
||||
continue;
|
||||
@ -265,6 +250,8 @@ public class SetQueue {
|
||||
if (set) {
|
||||
activeQueues.add(queue);
|
||||
return set;
|
||||
} else {
|
||||
queue.runTasks();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -285,6 +272,9 @@ public class SetQueue {
|
||||
}
|
||||
if (diff > Settings.QUEUE.DISCARD_AFTER_MS) {
|
||||
// These edits never finished
|
||||
for (FaweQueue queue : tmp) {
|
||||
queue.runTasks();
|
||||
}
|
||||
inactiveQueues.clear();
|
||||
}
|
||||
return false;
|
||||
|
@ -214,7 +214,7 @@ public class PlayerWrapper implements Player {
|
||||
TaskManager.IMP.sync(new RunnableVal<Object>() {
|
||||
@Override
|
||||
public void run(Object value) {
|
||||
edit.getQueue().next();
|
||||
edit.getQueue().flush();
|
||||
setPosition(new Vector(x + 0.5, y, z + 0.5));
|
||||
}
|
||||
});
|
||||
|
@ -162,7 +162,7 @@ public class NavigationCommands {
|
||||
|
||||
@Command(
|
||||
aliases = { "jumpto", "j" },
|
||||
usage = "jumpto [world,x,y,z]",
|
||||
usage = "[world,x,y,z]",
|
||||
desc = "Teleport to a location",
|
||||
min = 0,
|
||||
max = 1
|
||||
|
@ -151,7 +151,7 @@ public class SelectionCommand extends SimpleCommand<Operation> {
|
||||
long start = System.currentTimeMillis();
|
||||
BBC.OPERATION.send(actor, BBC.VISITOR_BLOCK.format(cuboid.getArea()));
|
||||
queue.flush();
|
||||
BBC.ACTION_COMPLETE.send(actor, start);
|
||||
BBC.ACTION_COMPLETE.send(actor, (System.currentTimeMillis() - start) / 1000);
|
||||
return null;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
|
@ -118,6 +118,11 @@ public class FaweForge implements IFawe {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
|
@ -1,19 +1,42 @@
|
||||
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.object.BytePair;
|
||||
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.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.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.ClassInheritanceMultiMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.BlockStatePaletteRegistry;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
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;
|
||||
|
||||
@ -35,7 +58,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
||||
public ForgeChunk_All copy(boolean shallow) {
|
||||
ForgeChunk_All value = (ForgeChunk_All) super.copy(shallow);
|
||||
if (sectionPalettes != null) {
|
||||
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;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
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.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -57,11 +50,20 @@ import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||
|
||||
private static Method methodFromNative;
|
||||
private static Method methodToNative;
|
||||
protected static Method methodFromNative;
|
||||
protected static Method methodToNative;
|
||||
|
||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
public ForgeQueue_All(String world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
if (methodFromNative == null) {
|
||||
try {
|
||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||
@ -76,7 +78,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
private BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
private final 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;
|
||||
}
|
||||
protected final static IBlockState air = Blocks.AIR.getDefaultState();
|
||||
|
||||
public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data");
|
||||
@ -604,7 +397,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
|
||||
private WorldServer nmsWorld;
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
|
@ -115,6 +115,11 @@ public class FaweForge implements IFawe {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
|
@ -1,14 +1,36 @@
|
||||
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.object.BytePair;
|
||||
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.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.chunk.Chunk;
|
||||
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 NibbleArray[] datas;
|
||||
@ -83,7 +105,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
||||
public ForgeChunk_All copy(boolean shallow) {
|
||||
ForgeChunk_All copy = new ForgeChunk_All(getParent(), getX(), getZ());
|
||||
if (shallow) {
|
||||
copy.byteIds = byteIds;
|
||||
@ -104,4 +126,229 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
||||
}
|
||||
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;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
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.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -52,11 +47,20 @@ import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||
|
||||
private static Method methodFromNative;
|
||||
private static Method methodToNative;
|
||||
protected static Method methodFromNative;
|
||||
protected static Method methodToNative;
|
||||
|
||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
public ForgeQueue_All(String world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
if (methodFromNative == null) {
|
||||
try {
|
||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||
@ -199,7 +203,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
||||
return true;
|
||||
}
|
||||
|
||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
protected final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
@Override
|
||||
public void run(IntegerPair loc) {
|
||||
Chunk chunk = getWorld().getChunkProvider().provideChunk(loc.x, loc.z);
|
||||
@ -264,223 +268,6 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
||||
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 {
|
||||
Class<? extends ExtendedBlockStorage> clazz = section.getClass();
|
||||
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);
|
||||
}
|
||||
|
||||
private WorldServer nmsWorld;
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
|
@ -118,6 +118,11 @@ public class FaweForge implements IFawe {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
|
@ -1,11 +1,35 @@
|
||||
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.object.BytePair;
|
||||
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.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.
|
||||
*
|
||||
@ -22,4 +46,209 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||
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;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
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.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
@ -50,11 +44,20 @@ import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||
|
||||
private static Method methodFromNative;
|
||||
private static Method methodToNative;
|
||||
protected static Method methodFromNative;
|
||||
protected static Method methodToNative;
|
||||
|
||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
public ForgeQueue_All(String world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
if (methodFromNative == null) {
|
||||
try {
|
||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||
@ -69,7 +72,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
private BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@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
|
||||
public void refreshChunk(FaweChunk fc) {
|
||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||
@ -563,7 +360,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
|
||||
private WorldServer nmsWorld;
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
|
@ -118,6 +118,11 @@ public class FaweForge implements IFawe {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return new ArrayList<>();
|
||||
|
@ -1,19 +1,42 @@
|
||||
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.object.BytePair;
|
||||
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.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.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.ClassInheritanceMultiMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.BlockStatePaletteRegistry;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
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;
|
||||
|
||||
@ -35,7 +58,7 @@ public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
||||
public ForgeChunk_All copy(boolean shallow) {
|
||||
ForgeChunk_All value = (ForgeChunk_All) super.copy(shallow);
|
||||
if (sectionPalettes != null) {
|
||||
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;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.object.BytePair;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
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.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -57,11 +50,20 @@ import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlockStorage[], ExtendedBlockStorage> {
|
||||
|
||||
private static Method methodFromNative;
|
||||
private static Method methodToNative;
|
||||
protected static Method methodFromNative;
|
||||
protected static Method methodToNative;
|
||||
|
||||
public ForgeQueue_All(com.sk89q.worldedit.world.World world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
public ForgeQueue_All(String world) {
|
||||
super(world);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
if (methodFromNative == null) {
|
||||
try {
|
||||
Class<?> converter = Class.forName("com.sk89q.worldedit.forge.NBTConverter");
|
||||
@ -76,7 +78,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
||||
getImpWorld();
|
||||
}
|
||||
|
||||
private BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
protected BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
private final 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;
|
||||
}
|
||||
protected final static IBlockState air = Blocks.AIR.getDefaultState();
|
||||
|
||||
public void setPalette(ExtendedBlockStorage section, BlockStateContainer palette) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field fieldSection = ExtendedBlockStorage.class.getDeclaredField("data");
|
||||
@ -602,7 +395,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
|
||||
private WorldServer nmsWorld;
|
||||
protected WorldServer nmsWorld;
|
||||
|
||||
@Override
|
||||
public World getImpWorld() {
|
||||
|
@ -193,6 +193,13 @@ public class NukkitPlayerBlockBag extends BlockBag {
|
||||
player.getInventory().setContents(items);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,6 @@ import cn.nukkit.Player;
|
||||
import cn.nukkit.event.EventHandler;
|
||||
import cn.nukkit.event.Listener;
|
||||
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.IFawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
@ -39,24 +36,6 @@ public class FaweNukkit implements IFawe, Listener {
|
||||
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
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
@ -121,6 +100,11 @@ public class FaweNukkit implements IFawe, Listener {
|
||||
return new NukkitQueue(this, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world, boolean fast) {
|
||||
return new NukkitQueue(this, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
return world.getName();
|
||||
|
@ -16,7 +16,7 @@ import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
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 boolean place = true;
|
||||
|
||||
public void execute() {
|
||||
@Override
|
||||
public NukkitChunk call() {
|
||||
NukkitQueue parent = (NukkitQueue) getParent();
|
||||
Level world = ((NukkitQueue) getParent()).getWorld();
|
||||
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.optimization.FaweNukkit;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
@ -25,8 +24,8 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFullChunk, BaseFullChunk> {
|
||||
private final FaweNukkit faweNukkit;
|
||||
private final Level world;
|
||||
private FaweNukkit faweNukkit;
|
||||
private Level world;
|
||||
|
||||
public static int ALLOCATE;
|
||||
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) {
|
||||
super(world);
|
||||
init(fn);
|
||||
}
|
||||
|
||||
public NukkitQueue(FaweNukkit fn, String world) {
|
||||
super(world);
|
||||
init(fn);
|
||||
}
|
||||
|
||||
private void init(FaweNukkit fn) {
|
||||
this.faweNukkit = fn;
|
||||
this.world = faweNukkit.getPlugin().getServer().getLevelByName(getWorldName());
|
||||
if (Settings.QUEUE.EXTRA_TIME_MS != Integer.MIN_VALUE) {
|
||||
@ -90,12 +98,6 @@ public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFu
|
||||
|
||||
private int skip;
|
||||
|
||||
@Override
|
||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
||||
((NukkitChunk) fc).execute();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSaveFolder() {
|
||||
return new File("worlds" + File.separator + world.getFolderName() + File.separator + "region");
|
||||
|
Loading…
Reference in New Issue
Block a user