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: case 0:
ordinal = getArr[i]; ordinal = getArr[i];
set[i] = ordinal; set[i] = ordinal;
switch (ordinal) {
case BlockID.AIR:
case BlockID.CAVE_AIR:
case BlockID.VOID_AIR:
air++;
}
break;
case BlockID.AIR: case BlockID.AIR:
case BlockID.CAVE_AIR: case BlockID.CAVE_AIR:
case BlockID.VOID_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) { private static int createPalette(int[] blockToPalette, int[] paletteToBlock, int[] blocksCopy, int[] num_palette_buffer, char[] set) {
int air = 0; int air = 0;
int num_palette = 0; int num_palette = 0;
char airOrdinal = BlockTypes.AIR.getDefaultState().getOrdinalChar();
for (int i = 0; i < 4096; i++) { for (int i = 0; i < 4096; i++) {
char ordinal = set[i]; char ordinal = set[i];
switch (ordinal) { switch (ordinal) {
case 0: case 0:
ordinal = airOrdinal; ordinal = BlockID.AIR;
case BlockID.AIR: case BlockID.AIR:
case BlockID.CAVE_AIR: case BlockID.CAVE_AIR:
case BlockID.VOID_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.BiomeBase;
import net.minecraft.server.v1_14_R1.BlockPosition; import net.minecraft.server.v1_14_R1.BlockPosition;
import net.minecraft.server.v1_14_R1.Chunk; 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.ChunkSection;
import net.minecraft.server.v1_14_R1.DataBits; import net.minecraft.server.v1_14_R1.DataBits;
import net.minecraft.server.v1_14_R1.DataPalette; 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.Entity;
import net.minecraft.server.v1_14_R1.EntityTypes; import net.minecraft.server.v1_14_R1.EntityTypes;
import net.minecraft.server.v1_14_R1.IBlockData; 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.NBTTagCompound;
import net.minecraft.server.v1_14_R1.NBTTagInt; 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.TileEntity;
import net.minecraft.server.v1_14_R1.WorldServer; import net.minecraft.server.v1_14_R1.WorldServer;
import org.bukkit.World; import org.bukkit.World;
@ -47,6 +51,7 @@ import org.bukkit.event.entity.CreatureSpawnEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.Future; 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; Runnable callback;
if (bitMask == 0) { if (bitMask == 0) {
callback = null; callback = null;

View File

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

View File

@ -297,7 +297,6 @@ public enum FaweCache implements Trimable {
int ordinal = blocksChars[i]; int ordinal = blocksChars[i];
int palette = blockToPalette[ordinal]; int palette = blockToPalette[ordinal];
if (palette == Integer.MAX_VALUE) { if (palette == Integer.MAX_VALUE) {
// BlockState state = BlockTypesCache.states[ordinal];
blockToPalette[ordinal] = palette = num_palette; blockToPalette[ordinal] = palette = num_palette;
paletteToBlock[num_palette] = ordinal; paletteToBlock[num_palette] = ordinal;
num_palette++; num_palette++;
@ -309,7 +308,7 @@ public enum FaweCache implements Trimable {
int ordinal = blocksInts[i]; int ordinal = blocksInts[i];
int palette = blockToPalette[ordinal]; int palette = blockToPalette[ordinal];
if (palette == Integer.MAX_VALUE) { if (palette == Integer.MAX_VALUE) {
BlockState state = BlockTypesCache.states[ordinal]; // BlockState state = BlockTypesCache.states[ordinal];
blockToPalette[ordinal] = palette = num_palette; blockToPalette[ordinal] = palette = num_palette;
paletteToBlock[num_palette] = ordinal; paletteToBlock[num_palette] = ordinal;
num_palette++; num_palette++;
@ -326,6 +325,11 @@ public enum FaweCache implements Trimable {
// BlockStates // BlockStates
int bitsPerEntry = MathMan.log2nlz(num_palette - 1); 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; int blockBitArrayEnd = (bitsPerEntry * 4096) >> 6;
if (num_palette == 1) { if (num_palette == 1) {
// Set a value, because minecraft needs it for some reason // Set a value, because minecraft needs it for some reason
@ -347,8 +351,8 @@ public enum FaweCache implements Trimable {
return palette; return palette;
} catch (Throwable e) { } catch (Throwable e) {
Arrays.fill(blockToPalette, Integer.MAX_VALUE);
e.printStackTrace(); e.printStackTrace();
Arrays.fill(blockToPalette, Integer.MAX_VALUE);
throw e; 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.block.BlockState;
import com.sk89q.worldedit.world.registry.BlockRegistry; import com.sk89q.worldedit.world.registry.BlockRegistry;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -66,28 +67,36 @@ public interface IBlocks extends Trimable {
char[] ids = this.getArray(layer); char[] ids = this.getArray(layer);
int nonEmpty = 0; // TODO optimize into same loop as toPalette int nonEmpty = 0; // TODO optimize into same loop as toPalette
for (char id : ids) { for (int i = 0; i < ids.length; i++) {
if (id != 0) nonEmpty++; 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.writeShort(nonEmpty); // non empty
sectionWriter.writeByte(14); // globalPaletteBitsPerBlock // if (false) {
// sectionWriter.writeByte(14); // globalPaletteBitsPerBlock
if (true) { // BitArray4096 bits = new BitArray4096(14); // globalPaletteBitsPerBlock
BitArray4096 bits = new BitArray4096(14); // globalPaletteBitsPerBlock // bits.setAt(0, 0);
bits.setAt(0, 0); // for (int i = 0; i < 4096; i++) {
for (int i = 0; i < 4096; i++) { // int ordinal = ids[i];
int ordinal = ids[i]; // BlockState state = BlockState.getFromOrdinal(ordinal);
BlockState state = BlockState.getFromOrdinal(ordinal); // if (!state.getMaterial().isAir()) {
if (!state.getMaterial().isAir()) { // int mcId = registry.getInternalBlockStateId(state).getAsInt();
int mcId = registry.getInternalBlockStateId(state).getAsInt(); // bits.setAt(i, mcId);
bits.setAt(i, mcId); // }
} // }
} // sectionWriter.write(bits.getData());
sectionWriter.write(bits.getData()); // } else {
} else {
FaweCache.Palette palette = FaweCache.IMP.toPalette(0, ids); FaweCache.Palette palette = FaweCache.IMP.toPalette(0, ids);
sectionWriter.writeByte(palette.bitsPerEntry); // bits per block sectionWriter.writeByte(palette.bitsPerEntry); // bits per block
@ -95,11 +104,11 @@ public interface IBlocks extends Trimable {
for (int i = 0; i < palette.paletteToBlockLength; i++) { for (int i = 0; i < palette.paletteToBlockLength; i++) {
int ordinal = palette.paletteToBlock[i]; int ordinal = palette.paletteToBlock[i];
switch (ordinal) { switch (ordinal) {
case BlockID.__RESERVED__:
case BlockID.CAVE_AIR: case BlockID.CAVE_AIR:
case BlockID.VOID_AIR: case BlockID.VOID_AIR:
case BlockID.AIR: case BlockID.AIR:
case BlockID.__RESERVED__: sectionWriter.write(0);
sectionWriter.writeVarInt(0);
break; break;
default: default:
BlockState state = BlockState.getFromOrdinal(ordinal); BlockState state = BlockState.getFromOrdinal(ordinal);
@ -112,7 +121,7 @@ public interface IBlocks extends Trimable {
for (int i = 0; i < palette.blockStatesLength; i++) { for (int i = 0; i < palette.blockStatesLength; i++) {
sectionWriter.writeLong(palette.blockStates[i]); sectionWriter.writeLong(palette.blockStates[i]);
} }
} // }
} }
// if (writeBiomes) { // if (writeBiomes) {

View File

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

View File

@ -57,7 +57,7 @@ public class ChunkPacket implements Function<byte[], byte[]>, Supplier<byte[]> {
return chunk; return chunk;
} }
private byte[] getSectionBytes() { public byte[] getSectionBytes() {
byte[] tmp = this.sectionBytes; byte[] tmp = this.sectionBytes;
if (tmp == null) { if (tmp == null) {
synchronized (this) { synchronized (this) {
@ -107,7 +107,6 @@ public class ChunkPacket implements Function<byte[], byte[]>, Supplier<byte[]> {
fos.writeVarInt(getChunk().getBitMask()); fos.writeVarInt(getChunk().getBitMask());
fos.writeNBT("", getHeightMap()); fos.writeNBT("", getHeightMap());
fos.writeVarInt(sectionBytes.length); 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.entity.Player;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -25,7 +26,7 @@ public class ChunkSendProcessor implements IBatchProcessor {
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
int chunkX = chunk.getX(); int chunkX = chunk.getX();
int chunkZ = chunk.getZ(); int chunkZ = chunk.getZ();
boolean replaceAll = true; boolean replaceAll = set.getBiomeType(0, 0) != null;
ChunkPacket packet = new ChunkPacket(chunkX, chunkZ, () -> set, replaceAll); ChunkPacket packet = new ChunkPacket(chunkX, chunkZ, () -> set, replaceAll);
Stream<Player> stream = this.players.get(); Stream<Player> stream = this.players.get();
if (stream == null) { if (stream == null) {
@ -41,4 +42,4 @@ public class ChunkSendProcessor implements IBatchProcessor {
public Extent construct(Extent child) { public Extent construct(Extent child) {
return null; return null;
} }
} }

View File

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