421 lines
17 KiB
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;
|
|
}
|
|
}
|