Various fixe + Restructuring + Possible breakage

This commit is contained in:
Jesse Boyd 2016-09-13 15:43:23 +10:00
parent 3a8d54bb78
commit 36fdbe55fe
56 changed files with 2491 additions and 2109 deletions

View File

@ -55,4 +55,6 @@ public abstract class ABukkitMain extends JavaPlugin {
}
public abstract FaweQueue getQueue(World world);
public abstract FaweQueue getQueue(String world);
}

View File

@ -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>

View File

@ -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) {

View File

@ -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());
}
};
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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() {

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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");

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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 {

View File

@ -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);
}
/**

View File

@ -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();

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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);
}
}

View File

@ -92,4 +92,9 @@ public class NullFaweChunk extends FaweChunk<Void> {
public FaweChunk<Void> copy(boolean shallow) {
return this;
}
@Override
public FaweChunk call() {
return null;
}
}

View File

@ -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");
}
}

View File

@ -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");

View File

@ -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();

View File

@ -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();
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -0,0 +1,4 @@
package com.boydti.fawe.object.player;
public class DefaultFawePlayer {
}

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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));
}
});

View File

@ -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

View File

@ -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) {

View File

@ -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<>();

View File

@ -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;
}
}

View File

@ -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() {

View File

@ -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<>();

View File

@ -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;
}
}

View File

@ -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() {

View File

@ -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<>();

View File

@ -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;
}
}

View File

@ -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() {

View File

@ -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<>();

View File

@ -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;
}
}

View File

@ -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() {

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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");