Fix palette / region iteration

This commit is contained in:
Jesse Boyd 2019-11-04 07:47:31 +00:00
parent 930dfb7f7c
commit 1e16095cba
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
9 changed files with 138 additions and 56 deletions

View File

@ -249,6 +249,13 @@ public final class BukkitAdapter_1_14 {
case 0:
ordinal = getArr[i];
set[i] = ordinal;
switch (ordinal) {
case BlockID.AIR:
case BlockID.CAVE_AIR:
case BlockID.VOID_AIR:
air++;
}
break;
case BlockID.AIR:
case BlockID.CAVE_AIR:
case BlockID.VOID_AIR:
@ -270,12 +277,11 @@ public final class BukkitAdapter_1_14 {
private static int createPalette(int[] blockToPalette, int[] paletteToBlock, int[] blocksCopy, int[] num_palette_buffer, char[] set) {
int air = 0;
int num_palette = 0;
char airOrdinal = BlockTypes.AIR.getDefaultState().getOrdinalChar();
for (int i = 0; i < 4096; i++) {
char ordinal = set[i];
switch (ordinal) {
case 0:
ordinal = airOrdinal;
ordinal = BlockID.AIR;
case BlockID.AIR:
case BlockID.CAVE_AIR:
case BlockID.VOID_AIR:

View File

@ -26,6 +26,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import net.minecraft.server.v1_14_R1.BiomeBase;
import net.minecraft.server.v1_14_R1.BlockPosition;
import net.minecraft.server.v1_14_R1.Chunk;
import net.minecraft.server.v1_14_R1.ChunkCoordIntPair;
import net.minecraft.server.v1_14_R1.ChunkSection;
import net.minecraft.server.v1_14_R1.DataBits;
import net.minecraft.server.v1_14_R1.DataPalette;
@ -35,8 +36,11 @@ import net.minecraft.server.v1_14_R1.DataPaletteLinear;
import net.minecraft.server.v1_14_R1.Entity;
import net.minecraft.server.v1_14_R1.EntityTypes;
import net.minecraft.server.v1_14_R1.IBlockData;
import net.minecraft.server.v1_14_R1.LightEngineThreaded;
import net.minecraft.server.v1_14_R1.NBTTagCompound;
import net.minecraft.server.v1_14_R1.NBTTagInt;
import net.minecraft.server.v1_14_R1.SectionPosition;
import net.minecraft.server.v1_14_R1.SystemUtils;
import net.minecraft.server.v1_14_R1.TileEntity;
import net.minecraft.server.v1_14_R1.WorldServer;
import org.bukkit.World;
@ -47,6 +51,7 @@ import org.bukkit.event.entity.CreatureSpawnEvent;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
@ -439,6 +444,13 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
};
}
// {//Lighting
// for (int layer = 0; layer < 16; layer++) {
// if (!set.hasSection(layer)) continue;
// //TODO lighting
// }
// }
Runnable callback;
if (bitMask == 0) {
callback = null;

View File

@ -1,16 +1,28 @@
package com.boydti.fawe.bukkit.adapter.mc1_14;
import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.math.BlockVector3;
import net.minecraft.server.v1_14_R1.Chunk;
import net.minecraft.server.v1_14_R1.ChunkSection;
import net.minecraft.server.v1_14_R1.NBTBase;
import net.minecraft.server.v1_14_R1.NBTTagCompound;
import net.minecraft.server.v1_14_R1.PacketPlayOutMapChunk;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Map;
import java.util.function.Supplier;
public class MapChunkUtil_1_14 {
private static final Field fieldX;
@ -42,6 +54,7 @@ public class MapChunkUtil_1_14 {
fieldZ.setAccessible(true);
fieldBitMask.setAccessible(true);
fieldHeightMap.setAccessible(true);
fieldChunkData.setAccessible(true);
fieldBlockEntities.setAccessible(true);
fieldFull.setAccessible(true);
} catch (Throwable e) {
@ -60,7 +73,8 @@ public class MapChunkUtil_1_14 {
fieldBitMask.set(nmsPacket, packet.getChunk().getBitMask());
NBTBase heightMap = adapter.fromNative(packet.getHeightMap());
fieldHeightMap.set(nmsPacket, heightMap);
fieldChunkData.set(nmsPacket, packet.get());
fieldChunkData.set(nmsPacket, packet.getSectionBytes());
Map<BlockVector3, CompoundTag> tiles = packet.getChunk().getTiles();
ArrayList<NBTTagCompound> nmsTiles = new ArrayList<>(tiles.size());
@ -72,6 +86,7 @@ public class MapChunkUtil_1_14 {
fieldFull.set(nmsPacket, packet.isFull());
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
return nmsPacket;

View File

@ -297,7 +297,6 @@ public enum FaweCache implements Trimable {
int ordinal = blocksChars[i];
int palette = blockToPalette[ordinal];
if (palette == Integer.MAX_VALUE) {
// BlockState state = BlockTypesCache.states[ordinal];
blockToPalette[ordinal] = palette = num_palette;
paletteToBlock[num_palette] = ordinal;
num_palette++;
@ -309,7 +308,7 @@ public enum FaweCache implements Trimable {
int ordinal = blocksInts[i];
int palette = blockToPalette[ordinal];
if (palette == Integer.MAX_VALUE) {
BlockState state = BlockTypesCache.states[ordinal];
// BlockState state = BlockTypesCache.states[ordinal];
blockToPalette[ordinal] = palette = num_palette;
paletteToBlock[num_palette] = ordinal;
num_palette++;
@ -326,6 +325,11 @@ public enum FaweCache implements Trimable {
// BlockStates
int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
if (Settings.IMP.PROTOCOL_SUPPORT_FIX || num_palette != 1) {
bitsPerEntry = Math.max(bitsPerEntry, 4); // Protocol support breaks <4 bits per entry
} else {
bitsPerEntry = Math.max(bitsPerEntry, 1); // For some reason minecraft needs 4096 bits to store 0 entries
}
int blockBitArrayEnd = (bitsPerEntry * 4096) >> 6;
if (num_palette == 1) {
// Set a value, because minecraft needs it for some reason
@ -347,8 +351,8 @@ public enum FaweCache implements Trimable {
return palette;
} catch (Throwable e) {
Arrays.fill(blockToPalette, Integer.MAX_VALUE);
e.printStackTrace();
Arrays.fill(blockToPalette, Integer.MAX_VALUE);
throw e;
}
}

View File

@ -14,6 +14,7 @@ import com.sk89q.worldedit.world.block.BlockID;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.registry.BlockRegistry;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
@ -66,28 +67,36 @@ public interface IBlocks extends Trimable {
char[] ids = this.getArray(layer);
int nonEmpty = 0; // TODO optimize into same loop as toPalette
for (char id : ids) {
if (id != 0) nonEmpty++;
for (int i = 0; i < ids.length; i++) {
char ordinal = ids[i];
switch (ordinal) {
case BlockID.__RESERVED__:
case BlockID.CAVE_AIR:
case BlockID.VOID_AIR:
ids[i] = BlockID.AIR;
case BlockID.AIR:
continue;
default:
nonEmpty++;
}
}
sectionWriter.writeShort(nonEmpty); // non empty
sectionWriter.writeByte(14); // globalPaletteBitsPerBlock
if (true) {
BitArray4096 bits = new BitArray4096(14); // globalPaletteBitsPerBlock
bits.setAt(0, 0);
for (int i = 0; i < 4096; i++) {
int ordinal = ids[i];
BlockState state = BlockState.getFromOrdinal(ordinal);
if (!state.getMaterial().isAir()) {
int mcId = registry.getInternalBlockStateId(state).getAsInt();
bits.setAt(i, mcId);
}
}
sectionWriter.write(bits.getData());
} else {
// if (false) {
// sectionWriter.writeByte(14); // globalPaletteBitsPerBlock
// BitArray4096 bits = new BitArray4096(14); // globalPaletteBitsPerBlock
// bits.setAt(0, 0);
// for (int i = 0; i < 4096; i++) {
// int ordinal = ids[i];
// BlockState state = BlockState.getFromOrdinal(ordinal);
// if (!state.getMaterial().isAir()) {
// int mcId = registry.getInternalBlockStateId(state).getAsInt();
// bits.setAt(i, mcId);
// }
// }
// sectionWriter.write(bits.getData());
// } else {
FaweCache.Palette palette = FaweCache.IMP.toPalette(0, ids);
sectionWriter.writeByte(palette.bitsPerEntry); // bits per block
@ -95,11 +104,11 @@ public interface IBlocks extends Trimable {
for (int i = 0; i < palette.paletteToBlockLength; i++) {
int ordinal = palette.paletteToBlock[i];
switch (ordinal) {
case BlockID.__RESERVED__:
case BlockID.CAVE_AIR:
case BlockID.VOID_AIR:
case BlockID.AIR:
case BlockID.__RESERVED__:
sectionWriter.writeVarInt(0);
sectionWriter.write(0);
break;
default:
BlockState state = BlockState.getFromOrdinal(ordinal);
@ -112,7 +121,7 @@ public interface IBlocks extends Trimable {
for (int i = 0; i < palette.blockStatesLength; i++) {
sectionWriter.writeLong(palette.blockStates[i]);
}
}
// }
}
// if (writeBiomes) {

View File

@ -115,7 +115,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
@Override
public void filter(Filter filter, int yStart, int yEnd) {
for (y = yStart, index = yStart << 8; y < yEnd; y++) {
for (y = yStart, index = yStart << 8; y <= yEnd; y++) {
for (z = 0; z < 16; z++) {
for (x = 0; x < 16; x++, index++) {
filter.applyBlock(this);

View File

@ -57,7 +57,7 @@ public class ChunkPacket implements Function<byte[], byte[]>, Supplier<byte[]> {
return chunk;
}
private byte[] getSectionBytes() {
public byte[] getSectionBytes() {
byte[] tmp = this.sectionBytes;
if (tmp == null) {
synchronized (this) {
@ -107,7 +107,6 @@ public class ChunkPacket implements Function<byte[], byte[]>, Supplier<byte[]> {
fos.writeVarInt(getChunk().getBitMask());
fos.writeNBT("", getHeightMap());
fos.writeVarInt(sectionBytes.length);

View File

@ -8,6 +8,7 @@ import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import java.util.function.Supplier;
import java.util.stream.Stream;
@ -25,7 +26,7 @@ public class ChunkSendProcessor implements IBatchProcessor {
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
int chunkX = chunk.getX();
int chunkZ = chunk.getZ();
boolean replaceAll = true;
boolean replaceAll = set.getBiomeType(0, 0) != null;
ChunkPacket packet = new ChunkPacket(chunkX, chunkZ, () -> set, replaceAll);
Stream<Player> stream = this.players.get();
if (stream == null) {
@ -41,4 +42,4 @@ public class ChunkSendProcessor implements IBatchProcessor {
public Extent construct(Extent child) {
return null;
}
}
}

View File

@ -328,31 +328,67 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
@NotNull @Override
public Iterator<BlockVector2> iterator() {
return new Iterator<BlockVector2>() {
private MutableBlockVector2 pos = new MutableBlockVector2().setComponents(maxX + 1, maxZ);
final MutableBlockVector2 mutable = new MutableBlockVector2(0, 0);
int bx = minX;
int bz = minZ;
int tx = maxX;
int tz = maxZ;
private int x = minX;
private int z = minZ;
int regionX = x >> 5;
int regionZ = z >> 5;
int rbx = Math.max(bx, regionX << 5);
int rbz = Math.max(bz, regionZ << 5);
int rtx = Math.min(tx, 31 + (regionX << 5));
int rtz = Math.min(tz, 31 + (regionZ << 5));
boolean hasNext = true;
@Override
public boolean hasNext() {
return pos != null;
return hasNext;
}
@Override
public BlockVector2 next() {
MutableBlockVector2 result = pos;
// calc next
pos.setComponents(pos.getX() - 1, pos.getZ());
if (pos.getX() <= minX) {
if (pos.getZ() == minZ) {
pos = null;
} else if (pos.getX() < minX) {
pos.setComponents(maxX, pos.getZ() - 1);
mutable.mutX(x);
mutable.mutZ(z);
if (++x > rtx) {
if (++z > rtz) {
if (x > tx) {
x = bx;
if (z > tz) {
if (!hasNext) {
throw new NoSuchElementException("End of iterator") {
@Override
public Throwable fillInStackTrace() {
return this;
}
};
}
x = tx;
hasNext = false;
return mutable;
}
} else {
z = rbz;
}
regionX = x >> 5;
regionZ = z >> 5;
rbx = Math.max(bx, regionX << 5);
rbz = Math.max(bz, regionZ << 5);
rtx = Math.min(tx, 31 + (regionX << 5));
rtz = Math.min(tz, 31 + (regionZ << 5));
} else {
x = rbx;
}
}
return result;
}
@Override
public void remove() {
throw new UnsupportedOperationException("This set is immutable.");
return mutable;
}
};
}
@ -628,19 +664,19 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
@Override
public void filter(final IChunk chunk, final Filter filter, ChunkFilterBlock block, final IChunkGet get, final IChunkSet set) {
int x = chunk.getX();
int z = chunk.getZ();
block = block.init(x, z, get);
int chunkX = chunk.getX();
int chunkZ = chunk.getZ();
block = block.init(chunkX, chunkZ, get);
if ((minX + 15) >> 4 <= x && (maxX - 15) >> 4 >= x && (minZ + 15) >> 4 <= z && (maxZ - 15) >> 4 >= z) {
if ((minX + 15) >> 4 <= chunkX && (maxX - 15) >> 4 >= chunkX && (minZ + 15) >> 4 <= chunkZ && (maxZ - 15) >> 4 >= chunkZ) {
filter(chunk, filter, block, get, set, minY, maxY);
return;
}
int localMinX = Math.max(minX, x << 4) & 15;
int localMaxX = Math.min(maxX, 15 + (x << 4)) & 15;
int localMinZ = Math.max(minZ, z << 4) & 15;
int localMaxZ = Math.min(maxZ, 15 + (z << 4)) & 15;
int localMinX = Math.max(minX, chunkX << 4) & 15;
int localMaxX = Math.min(maxX, 15 + (chunkX << 4)) & 15;
int localMinZ = Math.max(minZ, chunkZ << 4) & 15;
int localMaxZ = Math.min(maxZ, 15 + (chunkZ << 4)) & 15;
int yStart = (minY & 15);
int yEnd = (maxY & 15);