FastAsyncWorldedit/forge1710/src/main/java/com/boydti/fawe/forge/v1710/ForgeChunk_All.java

421 lines
17 KiB
Java

package com.boydti.fawe.forge.v1710;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
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.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;
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, ForgeQueue_All> {
public final byte[][] byteIds;
public final NibbleArray[] extended;
public final NibbleArray[] datas;
public ForgeChunk_All(FaweQueue parent, int x, int z) {
super(parent, x, z);
this.byteIds = new byte[16][];
this.extended = new NibbleArray[16];
this.datas = new NibbleArray[16];
}
public ForgeChunk_All(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap, byte[][] byteIds, NibbleArray[] datas, NibbleArray[] extended) {
super(parent, x, z, ids, count, air, heightMap);
this.byteIds = byteIds;
this.datas = datas;
this.extended = extended;
}
@Override
public CharFaweChunk copy(boolean shallow) {
ForgeChunk_All copy;
if (shallow) {
copy = new ForgeChunk_All(getParent(), getX(), getZ(), ids, count, air, heightMap, byteIds, datas, extended);
copy.biomes = biomes;
copy.chunk = chunk;
} else {
copy = new ForgeChunk_All(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone(), (byte[][]) MainUtil.copyNd(byteIds), datas.clone(), extended.clone());
copy.biomes = biomes;
copy.chunk = chunk;
copy.biomes = biomes.clone();
copy.chunk = chunk;
}
return copy;
}
@Override
public Chunk getNewChunk() {
World world = ((ForgeQueue_All) getParent()).getWorld();
return world.getChunkProvider().provideChunk(getX(), getZ());
}
public byte[] getByteIdArray(int i) {
return this.byteIds[i];
}
public NibbleArray getDataArray(int i) {
return datas[i];
}
public NibbleArray getExtendedIdArray(int i) {
return extended[i];
}
@Override
public void setBlock(int x, int y, int z, int id) {
setBlock(x, y, z, id, 0);
}
@Override
public void setBlock(int x, int y, int z, int id, int data) {
int i = FaweCache.CACHE_I[y][z][x];
int j = FaweCache.CACHE_J[y][z][x];
byte[] vs = this.byteIds[i];
char[] vs2 = this.ids[i];
if (vs2 == null) {
vs2 = this.ids[i] = new char[4096];
}
if (vs == null) {
vs = this.byteIds[i] = new byte[4096];
}
this.count[i]++;
switch (id) {
case 0:
this.air[i]++;
vs[j] = 0;
vs2[j] = (char) 1;
return;
case 11:
case 39:
case 40:
case 51:
case 74:
case 89:
case 122:
case 124:
case 138:
case 169:
case 213:
case 130:
case 76:
case 62:
case 50:
case 10:
// this.relight[i]++;
default:
vs2[j] = (char) ((id << 4) + data);
vs[j] = (byte) id;
if (data != 0) {
NibbleArray dataArray = datas[i];
if (dataArray == null) {
datas[i] = dataArray = new NibbleArray(4096, 4);
}
dataArray.set(x, y & 15, z, data);
}
if (id > 255) {
NibbleArray nibble = extended[i];
if (nibble == null) {
extended[i] = nibble = new NibbleArray(4096, 4);
}
nibble.set(x, y & 15, z, id >> 8);
}
}
}
@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;
// Set heightmap
getParent().setHeightMap(this, heightMap);
// 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 if (!getParent().getSettings().EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) {
char[] array = this.getIdArray(i);
if (array == null || entities[i] == null || entities[i].isEmpty()) continue;
Collection<Entity> ents = new ArrayList<>(entities[i]);
for (Entity entity : ents) {
if (entity instanceof EntityPlayer) {
continue;
}
int x = (MathMan.roundInt(entity.posX) & 15);
int z = (MathMan.roundInt(entity.posZ) & 15);
int y = MathMan.roundInt(entity.posY);
if (y < 0 || y > 255) continue;
if (array[FaweCache.CACHE_J[y][z][x]] != 0) {
synchronized (ForgeQueue_All.class) {
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())) {
synchronized (ForgeQueue_All.class) {
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 = EntityList.createEntityByName(id, nmsWorld);
if (entity != null) {
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
tag.removeTag("UUIDMost");
tag.removeTag("UUIDLeast");
entity.readFromNBT(tag);
entity.setPositionAndRotation(x, y, z, yaw, pitch);
synchronized (ForgeQueue_All.class) {
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) {
synchronized (ForgeQueue_All.class) {
tile.getValue().invalidate();
iterator.remove();
}
}
}
// Efficiently merge sections
for (int j = 0; j < sections.length; j++) {
int count = this.getCount(j);
if (count == 0) {
continue;
}
byte[] newIdArray = this.getByteIdArray(j);
if (newIdArray == null) {
continue;
}
int countAir = this.getAir(j);
NibbleArray newDataArray = this.getDataArray(j);
NibbleArray extendedArray = this.getExtendedIdArray(j);
ExtendedBlockStorage section = sections[j];
if ((section == null)) {
if (count == countAir) {
continue;
}
sections[j] = section = new ExtendedBlockStorage(j << 4, !getParent().getWorld().provider.hasNoSky);
section.setBlockLSBArray(newIdArray);
if (newDataArray != null) {
section.setBlockMetadataArray(newDataArray);
}
if (extendedArray != null) {
section.setBlockMSBArray(extendedArray);
}
continue;
} else if (count >= 4096) {
if (count == countAir) {
sections[j] = null;
continue;
}
section.setBlockLSBArray(newIdArray);
if (newDataArray != null) {
section.setBlockMetadataArray(newDataArray);
} else if (section.getMetadataArray() != null) {
Arrays.fill(section.getMetadataArray().data, (byte) 0);
}
if (extendedArray != null) {
section.setBlockMSBArray(extendedArray);
} else if (section.getBlockMSBArray() != null) {
Arrays.fill(section.getBlockMSBArray().data, (byte) 0);
}
continue;
}
byte[] currentIdArray = section.getBlockLSBArray();
NibbleArray currentDataArray = section.getMetadataArray();
NibbleArray currentExtraArray = section.getBlockMSBArray();
boolean data = currentDataArray != null && newDataArray != null;
if (currentDataArray == null && newDataArray != null) {
section.setBlockMetadataArray(newDataArray);
}
boolean extra = currentExtraArray != null && extendedArray != null;
if (currentExtraArray == null && extendedArray != null) {
section.setBlockMSBArray(extendedArray);
}
int solid = 0;
char[] charArray = this.getIdArray(j);
for (int k = 0; k < newIdArray.length; k++) {
char combined = charArray[k];
switch (combined) {
case 0:
if (currentIdArray[k] != 0) {
solid++;
}
continue;
case 1:
currentIdArray[k] = 0;
if (extra) {
int x = FaweCache.CACHE_X[0][k];
int y = FaweCache.CACHE_Y[0][k];
int z = FaweCache.CACHE_Z[0][k];
currentExtraArray.set(x, y, z, 0);
}
continue;
default:
solid++;
currentIdArray[k] = newIdArray[k];
if (data) {
if (FaweCache.hasData(combined >> 4)) {
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);
}
} else if (currentDataArray != null) {
int x = FaweCache.CACHE_X[0][k];
int y = FaweCache.CACHE_Y[0][k];
int z = FaweCache.CACHE_Z[0][k];
currentDataArray.set(x, y, z, 0);
}
int extraId = FaweCache.getId(combined) >> 8;
if (extra && extraId != 0) {
int x = FaweCache.CACHE_X[0][k];
int y = FaweCache.CACHE_Y[0][k];
int z = FaweCache.CACHE_Z[0][k];
int newExtra = extendedArray.get(x, y, z);
currentExtraArray.set(x, y, z, newExtra);
} else if (currentExtraArray != null) {
int x = FaweCache.CACHE_X[0][k];
int y = FaweCache.CACHE_Y[0][k];
int z = FaweCache.CACHE_Z[0][k];
currentExtraArray.set(x, y, z, 0);
}
continue;
}
}
getParent().setCount(0, solid, section);
}
// Set biomes
if (this.biomes != null) {
byte[] currentBiomes = nmsChunk.getBiomeArray();
for (int i = 0 ; i < this.biomes.length; i++) {
byte biome = this.biomes[i];
if (biome != 0) {
if (biome == -1) biome = 0;
currentBiomes[i] = biome;
}
}
}
// Set tiles
Map<Short, CompoundTag> tilesToSpawn = this.getTiles();
int bx = this.getX() << 4;
int bz = this.getZ() << 4;
for (Map.Entry<Short, CompoundTag> entry : tilesToSpawn.entrySet()) {
CompoundTag nativeTag = entry.getValue();
short blockHash = entry.getKey();
int x = (blockHash >> 12 & 0xF) + bx;
int y = (blockHash & 0xFF);
int z = (blockHash >> 8 & 0xF) + bz;
TileEntity tileEntity = nmsWorld.getTileEntity(x, y, z);
if (tileEntity != null) {
NBTTagCompound tag = (NBTTagCompound) ForgeQueue_All.methodFromNative.invoke(null, nativeTag);
tag.setInteger("x", x);
tag.setInteger("y", y);
tag.setInteger("z", z);
tileEntity.readFromNBT(tag); // ReadTagIntoTile
}
}
} catch (Throwable e) {
MainUtil.handleError(e);
}
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;
}
}