mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 09:47:38 +00:00
Fix setting the same block multiple times sequencially
This commit is contained in:
parent
2a373b1390
commit
274c52163b
@ -20,6 +20,7 @@
|
|||||||
package com.boydti.fawe.bukkit.adapter.v1_13_1;
|
package com.boydti.fawe.bukkit.adapter.v1_13_1;
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.object.collection.ObjObjMap;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
|
@ -65,10 +65,10 @@ public class BukkitChunk_All extends IntFaweChunk<Chunk, BukkitQueue_All> {
|
|||||||
public IntFaweChunk copy(boolean shallow) {
|
public IntFaweChunk copy(boolean shallow) {
|
||||||
BukkitChunk_All copy;
|
BukkitChunk_All copy;
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
copy = new BukkitChunk_All(getParent(), getX(), getZ(), ids, count, air);
|
copy = new BukkitChunk_All(getParent(), getX(), getZ(), setBlocks, count, air);
|
||||||
copy.biomes = biomes;
|
copy.biomes = biomes;
|
||||||
} else {
|
} else {
|
||||||
copy = new BukkitChunk_All(getParent(), getX(), getZ(), (int[][]) MainUtil.copyNd(ids), count.clone(), air.clone());
|
copy = new BukkitChunk_All(getParent(), getX(), getZ(), (int[][]) MainUtil.copyNd(setBlocks), count.clone(), air.clone());
|
||||||
copy.biomes = biomes != null ? biomes.clone() : null;
|
copy.biomes = biomes != null ? biomes.clone() : null;
|
||||||
}
|
}
|
||||||
copy.chunk = chunk;
|
copy.chunk = chunk;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.boydti.fawe.bukkit.v0;
|
package com.boydti.fawe.bukkit.v0;
|
||||||
|
|
||||||
import com.boydti.fawe.FaweCache;
|
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
@ -10,7 +9,6 @@ import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
|
||||||
import org.bukkit.ChunkSnapshot;
|
import org.bukkit.ChunkSnapshot;
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
@ -75,7 +73,7 @@ public class BukkitChunk_All_ReadonlySnapshot extends FaweChunk {
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public int[] getIdArray(int layer) {
|
public int[] getIdArray(int layer) {
|
||||||
int[] nextLayer = next.ids[layer];
|
int[] nextLayer = next.setBlocks[layer];
|
||||||
if (nextLayer == null) return null;
|
if (nextLayer == null) return null;
|
||||||
int[] ids = Arrays.copyOf(nextLayer, nextLayer.length);
|
int[] ids = Arrays.copyOf(nextLayer, nextLayer.length);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
@ -6,6 +6,7 @@ import com.boydti.fawe.bukkit.adapter.v1_13_1.Spigot_v1_13_R2;
|
|||||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.example.IntFaweChunk;
|
import com.boydti.fawe.example.IntFaweChunk;
|
||||||
|
import com.boydti.fawe.jnbt.anvil.BitArray4096;
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
@ -60,6 +61,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static com.boydti.fawe.bukkit.v0.BukkitQueue_0.getAdapter;
|
||||||
import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryb;
|
import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryb;
|
||||||
import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryc;
|
import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryc;
|
||||||
import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryd;
|
import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryd;
|
||||||
@ -69,6 +71,7 @@ import static com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13.fieldRegistryf;
|
|||||||
public class BukkitChunk_1_13 extends IntFaweChunk<Chunk, BukkitQueue_1_13> {
|
public class BukkitChunk_1_13 extends IntFaweChunk<Chunk, BukkitQueue_1_13> {
|
||||||
|
|
||||||
public ChunkSection[] sectionPalettes;
|
public ChunkSection[] sectionPalettes;
|
||||||
|
|
||||||
private static final IBlockData AIR = ((BlockMaterial_1_13) BlockTypes.AIR.getMaterial()).getState();
|
private static final IBlockData AIR = ((BlockMaterial_1_13) BlockTypes.AIR.getMaterial()).getState();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,6 +100,52 @@ public class BukkitChunk_1_13 extends IntFaweChunk<Chunk, BukkitQueue_1_13> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[][] getCombinedIdArrays() {
|
||||||
|
if (this.sectionPalettes != null) {
|
||||||
|
for (int i = 0; i < setBlocks.length; i++) {
|
||||||
|
getIdArray(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.setBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getIdArray(int layer) {
|
||||||
|
if (this.setBlocks[layer] == null && this.sectionPalettes != null) {
|
||||||
|
ChunkSection section = this.sectionPalettes[layer];
|
||||||
|
int[] idsArray = this.setBlocks[layer];
|
||||||
|
if (section != null && idsArray == null) {
|
||||||
|
this.setBlocks[layer] = idsArray = new int[4096];
|
||||||
|
if (!section.a()) {
|
||||||
|
try {
|
||||||
|
DataPaletteBlock<IBlockData> blocks = section.getBlocks();
|
||||||
|
DataBits bits = (DataBits) BukkitQueue_1_13.fieldBits.get(blocks);
|
||||||
|
DataPalette<IBlockData> palette = (DataPalette<IBlockData>) BukkitQueue_1_13.fieldPalette.get(blocks);
|
||||||
|
|
||||||
|
long[] raw = bits.a();
|
||||||
|
int bitsPerEntry = bits.c();
|
||||||
|
|
||||||
|
new BitArray4096(raw, bitsPerEntry).toRaw(idsArray);
|
||||||
|
IBlockData defaultBlock = (IBlockData) BukkitQueue_1_13.fieldDefaultBlock.get(blocks);
|
||||||
|
// TODO optimize away palette.a
|
||||||
|
for (int i = 0; i < 4096; i++) {
|
||||||
|
IBlockData ibd = palette.a(idsArray[i]);
|
||||||
|
if (ibd == null) {
|
||||||
|
ibd = defaultBlock;
|
||||||
|
}
|
||||||
|
int ordinal = ((Spigot_v1_13_R2) getAdapter()).adaptToInt(ibd);
|
||||||
|
idsArray[i] = BlockTypes.states[ordinal].getInternalId();
|
||||||
|
}
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.setBlocks[layer];
|
||||||
|
}
|
||||||
|
|
||||||
public boolean storeTile(TileEntity tile, BlockPosition pos) {
|
public boolean storeTile(TileEntity tile, BlockPosition pos) {
|
||||||
CompoundTag nativeTag = getParent().getTag(tile);
|
CompoundTag nativeTag = getParent().getTag(tile);
|
||||||
setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag);
|
setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag);
|
||||||
@ -216,11 +265,11 @@ public class BukkitChunk_1_13 extends IntFaweChunk<Chunk, BukkitQueue_1_13> {
|
|||||||
public IntFaweChunk<Chunk, BukkitQueue_1_13> copy(boolean shallow) {
|
public IntFaweChunk<Chunk, BukkitQueue_1_13> copy(boolean shallow) {
|
||||||
BukkitChunk_1_13 copy;
|
BukkitChunk_1_13 copy;
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
copy = new BukkitChunk_1_13(getParent(), getX(), getZ(), ids, count, air);
|
copy = new BukkitChunk_1_13(getParent(), getX(), getZ(), setBlocks, count, air);
|
||||||
copy.biomes = biomes;
|
copy.biomes = biomes;
|
||||||
copy.chunk = chunk;
|
copy.chunk = chunk;
|
||||||
} else {
|
} else {
|
||||||
copy = new BukkitChunk_1_13(getParent(), getX(), getZ(), (int[][]) MainUtil.copyNd(ids), count.clone(), air.clone());
|
copy = new BukkitChunk_1_13(getParent(), getX(), getZ(), (int[][]) MainUtil.copyNd(setBlocks), count.clone(), air.clone());
|
||||||
copy.biomes = biomes != null ? biomes.clone() : null;
|
copy.biomes = biomes != null ? biomes.clone() : null;
|
||||||
copy.chunk = chunk;
|
copy.chunk = chunk;
|
||||||
}
|
}
|
||||||
@ -281,7 +330,7 @@ public class BukkitChunk_1_13 extends IntFaweChunk<Chunk, BukkitQueue_1_13> {
|
|||||||
public FaweChunk call() {
|
public FaweChunk call() {
|
||||||
Spigot_v1_13_R2 adapter = (Spigot_v1_13_R2) BukkitQueue_0.getAdapter();
|
Spigot_v1_13_R2 adapter = (Spigot_v1_13_R2) BukkitQueue_0.getAdapter();
|
||||||
try {
|
try {
|
||||||
BukkitChunk_1_13_Copy copy = getParent().getChangeTask() != null ? new BukkitChunk_1_13_Copy(getParent(), getX(), getZ()) : null;
|
BukkitChunk_1_13 copy = getParent().getChangeTask() != null ? new BukkitChunk_1_13(getParent(), getX(), getZ()) : null;
|
||||||
final Chunk chunk = this.getChunk();
|
final Chunk chunk = this.getChunk();
|
||||||
final World world = chunk.getWorld();
|
final World world = chunk.getWorld();
|
||||||
Settings settings = getParent().getSettings();
|
Settings settings = getParent().getSettings();
|
||||||
@ -439,7 +488,7 @@ public class BukkitChunk_1_13 extends IntFaweChunk<Chunk, BukkitQueue_1_13> {
|
|||||||
section = sections[j] = getParent().newChunkSection(j, flag, array);
|
section = sections[j] = getParent().newChunkSection(j, flag, array);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (count >= 4096) {
|
} else if (count >= 4096 && false) {
|
||||||
if (countAir >= 4096) {
|
if (countAir >= 4096) {
|
||||||
sections[j] = null;
|
sections[j] = null;
|
||||||
continue;
|
continue;
|
||||||
@ -452,6 +501,11 @@ public class BukkitChunk_1_13 extends IntFaweChunk<Chunk, BukkitQueue_1_13> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (count >= 4096) {
|
||||||
|
for (int i = 0; i < 4096; i++) {
|
||||||
|
if (array[i] == 0) System.out.println("Invalid ");
|
||||||
|
}
|
||||||
|
}
|
||||||
int by = j << 4;
|
int by = j << 4;
|
||||||
DataPaletteBlock<IBlockData> nibble = section.getBlocks();
|
DataPaletteBlock<IBlockData> nibble = section.getBlocks();
|
||||||
int nonEmptyBlockCount = 0;
|
int nonEmptyBlockCount = 0;
|
||||||
|
@ -1,90 +0,0 @@
|
|||||||
package com.boydti.fawe.bukkit.v1_13;
|
|
||||||
|
|
||||||
import com.boydti.fawe.bukkit.adapter.v1_13_1.Spigot_v1_13_R2;
|
|
||||||
import com.boydti.fawe.jnbt.anvil.BitArray4096;
|
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
|
||||||
import net.minecraft.server.v1_13_R2.ChunkSection;
|
|
||||||
import net.minecraft.server.v1_13_R2.DataBits;
|
|
||||||
import net.minecraft.server.v1_13_R2.DataPalette;
|
|
||||||
import net.minecraft.server.v1_13_R2.DataPaletteBlock;
|
|
||||||
import net.minecraft.server.v1_13_R2.IBlockData;
|
|
||||||
|
|
||||||
import static com.boydti.fawe.bukkit.v0.BukkitQueue_0.getAdapter;
|
|
||||||
|
|
||||||
public class BukkitChunk_1_13_Copy extends BukkitChunk_1_13 {
|
|
||||||
public BukkitChunk_1_13_Copy(FaweQueue parent, int x, int z) {
|
|
||||||
super(parent, x, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[][] getCombinedIdArrays() {
|
|
||||||
if (this.sectionPalettes == null) {
|
|
||||||
return this.ids;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < ids.length; i++) {
|
|
||||||
getIdArray(i);
|
|
||||||
}
|
|
||||||
return super.getCombinedIdArrays();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getIdArray(int layer) {
|
|
||||||
if (this.sectionPalettes != null) {
|
|
||||||
ChunkSection section = this.sectionPalettes[layer];
|
|
||||||
int[] idsArray = this.ids[layer];
|
|
||||||
if (section != null && idsArray == null) {
|
|
||||||
idsArray = new int[4096];
|
|
||||||
if (!section.a()) {
|
|
||||||
try {
|
|
||||||
DataPaletteBlock<IBlockData> blocks = section.getBlocks();
|
|
||||||
DataBits bits = (DataBits) BukkitQueue_1_13.fieldBits.get(blocks);
|
|
||||||
DataPalette<IBlockData> palette = (DataPalette<IBlockData>) BukkitQueue_1_13.fieldPalette.get(blocks);
|
|
||||||
|
|
||||||
long[] raw = bits.a();
|
|
||||||
int bitsPerEntry = bits.c();
|
|
||||||
|
|
||||||
new BitArray4096(raw, bitsPerEntry).toRaw(idsArray);
|
|
||||||
IBlockData defaultBlock = (IBlockData) BukkitQueue_1_13.fieldDefaultBlock.get(blocks);
|
|
||||||
// TODO optimize away palette.a
|
|
||||||
for (int i = 0; i < 4096; i++) {
|
|
||||||
IBlockData ibd = palette.a(idsArray[i]);
|
|
||||||
if (ibd == null) {
|
|
||||||
ibd = defaultBlock;
|
|
||||||
}
|
|
||||||
int ordinal = ((Spigot_v1_13_R2) getAdapter()).adaptToInt(ibd);
|
|
||||||
idsArray[i] = BlockTypes.states[ordinal].getInternalId();
|
|
||||||
}
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return idsArray;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <B extends BlockStateHolder<B>> void setBlock(int x, int y, int z, B block) {
|
|
||||||
throw new UnsupportedOperationException("Read only");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBiome(BiomeType biome) {
|
|
||||||
throw new UnsupportedOperationException("Read only");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBiome(int x, int z, BiomeType biome) {
|
|
||||||
throw new UnsupportedOperationException("Read only");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBlock(int x, int y, int z, int combinedId) {
|
|
||||||
throw new UnsupportedOperationException("Read only");
|
|
||||||
}
|
|
||||||
}
|
|
@ -879,7 +879,11 @@ public class BukkitQueue_1_13 extends BukkitQueue_0<net.minecraft.server.v1_13_R
|
|||||||
|
|
||||||
// BlockStates
|
// BlockStates
|
||||||
int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
|
int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
|
||||||
bitsPerEntry = Math.max(bitsPerEntry, 4);
|
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) {
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
package com.boydti.fawe.example;
|
package com.boydti.fawe.example;
|
||||||
|
|
||||||
import com.boydti.fawe.FaweCache;
|
|
||||||
import com.boydti.fawe.object.FaweChunk;
|
import com.boydti.fawe.object.FaweChunk;
|
||||||
import com.boydti.fawe.object.FaweQueue;
|
import com.boydti.fawe.object.FaweQueue;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BlockID;
|
import com.sk89q.worldedit.world.block.BlockID;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public abstract class IntFaweChunk<T, V extends FaweQueue> extends FaweChunk<T> {
|
public abstract class IntFaweChunk<T, V extends FaweQueue> extends FaweChunk<T> {
|
||||||
|
|
||||||
public final int[][] ids;
|
public final int[][] setBlocks;
|
||||||
public final short[] count;
|
public final short[] count;
|
||||||
public final short[] air;
|
public final short[] air;
|
||||||
|
|
||||||
@ -24,9 +22,9 @@ public abstract class IntFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
|
|||||||
|
|
||||||
public T chunk;
|
public T chunk;
|
||||||
|
|
||||||
public IntFaweChunk(FaweQueue parent, int x, int z, int[][] ids, short[] count, short[] air) {
|
public IntFaweChunk(FaweQueue parent, int x, int z, int[][] setBlocks, short[] count, short[] air) {
|
||||||
super(parent, x, z);
|
super(parent, x, z);
|
||||||
this.ids = ids;
|
this.setBlocks = setBlocks;
|
||||||
this.count = count;
|
this.count = count;
|
||||||
this.air = air;
|
this.air = air;
|
||||||
}
|
}
|
||||||
@ -40,7 +38,7 @@ public abstract class IntFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
|
|||||||
*/
|
*/
|
||||||
public IntFaweChunk(FaweQueue parent, int x, int z) {
|
public IntFaweChunk(FaweQueue parent, int x, int z) {
|
||||||
super(parent, x, z);
|
super(parent, x, z);
|
||||||
this.ids = new int[HEIGHT >> 4][];
|
this.setBlocks = new int[HEIGHT >> 4][];
|
||||||
this.count = new short[HEIGHT >> 4];
|
this.count = new short[HEIGHT >> 4];
|
||||||
this.air = new short[HEIGHT >> 4];
|
this.air = new short[HEIGHT >> 4];
|
||||||
}
|
}
|
||||||
@ -103,8 +101,8 @@ public abstract class IntFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
|
|||||||
@Override
|
@Override
|
||||||
public int getBitMask() {
|
public int getBitMask() {
|
||||||
int bitMask = 0;
|
int bitMask = 0;
|
||||||
for (int section = 0; section < ids.length; section++) {
|
for (int section = 0; section < setBlocks.length; section++) {
|
||||||
if (ids[section] != null) {
|
if (setBlocks[section] != null) {
|
||||||
bitMask += 1 << section;
|
bitMask += 1 << section;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,12 +117,12 @@ public abstract class IntFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int[] getIdArray(final int i) {
|
public int[] getIdArray(final int i) {
|
||||||
return this.ids[i];
|
return this.setBlocks[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[][] getCombinedIdArrays() {
|
public int[][] getCombinedIdArrays() {
|
||||||
return this.ids;
|
return this.setBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -193,11 +191,15 @@ public abstract class IntFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
|
|||||||
@Override
|
@Override
|
||||||
public void setBlock(int x, int y, int z, int combinedId) {
|
public void setBlock(int x, int y, int z, int combinedId) {
|
||||||
final int i = y >> 4;
|
final int i = y >> 4;
|
||||||
int[] vs = this.ids[i];
|
int[] vs = this.setBlocks[i];
|
||||||
if (vs == null) {
|
if (vs == null) {
|
||||||
vs = this.ids[i] = new int[4096];
|
vs = this.setBlocks[i] = new int[4096];
|
||||||
}
|
}
|
||||||
vs[(((y & 15) << 8) | (z << 4) | x)] = combinedId;
|
int index = (((y & 15) << 8) | (z << 4) | x);
|
||||||
|
int existing = vs[index];
|
||||||
|
vs[index] = combinedId;
|
||||||
|
switch (existing) {
|
||||||
|
case 0:
|
||||||
this.count[i]++;
|
this.count[i]++;
|
||||||
switch (combinedId) {
|
switch (combinedId) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -206,6 +208,21 @@ public abstract class IntFaweChunk<T, V extends FaweQueue> extends FaweChunk<T>
|
|||||||
case BlockID.VOID_AIR:
|
case BlockID.VOID_AIR:
|
||||||
this.air[i]++;
|
this.air[i]++;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case BlockID.AIR:
|
||||||
|
case BlockID.CAVE_AIR:
|
||||||
|
case BlockID.VOID_AIR:
|
||||||
|
switch (combinedId) {
|
||||||
|
case 0:
|
||||||
|
case BlockID.AIR:
|
||||||
|
case BlockID.CAVE_AIR:
|
||||||
|
case BlockID.VOID_AIR:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.air[i]--;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ public class NullQueueIntFaweChunk extends IntFaweChunk {
|
|||||||
@Override
|
@Override
|
||||||
public IntFaweChunk copy(boolean shallow) {
|
public IntFaweChunk copy(boolean shallow) {
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
return new NullQueueIntFaweChunk(getX(), getZ(), ids, count, air);
|
return new NullQueueIntFaweChunk(getX(), getZ(), setBlocks, count, air);
|
||||||
} else {
|
} else {
|
||||||
return new NullQueueIntFaweChunk(getX(), getZ(), (int[][]) MainUtil.copyNd(ids), count.clone(), air.clone());
|
return new NullQueueIntFaweChunk(getX(), getZ(), (int[][]) MainUtil.copyNd(setBlocks), count.clone(), air.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,10 +23,10 @@ public class SimpleIntFaweChunk extends IntFaweChunk {
|
|||||||
public IntFaweChunk copy(boolean shallow) {
|
public IntFaweChunk copy(boolean shallow) {
|
||||||
SimpleIntFaweChunk copy;
|
SimpleIntFaweChunk copy;
|
||||||
if (shallow) {
|
if (shallow) {
|
||||||
copy = new SimpleIntFaweChunk(getParent(), getX(), getZ(), ids, count, air);
|
copy = new SimpleIntFaweChunk(getParent(), getX(), getZ(), setBlocks, count, air);
|
||||||
copy.biomes = biomes;
|
copy.biomes = biomes;
|
||||||
} else {
|
} else {
|
||||||
copy = new SimpleIntFaweChunk(getParent(), getX(), getZ(), (int[][]) MainUtil.copyNd(ids), count.clone(), air.clone());
|
copy = new SimpleIntFaweChunk(getParent(), getX(), getZ(), (int[][]) MainUtil.copyNd(setBlocks), count.clone(), air.clone());
|
||||||
copy.biomes = biomes != null ? biomes.clone() : null;
|
copy.biomes = biomes != null ? biomes.clone() : null;
|
||||||
}
|
}
|
||||||
return copy;
|
return copy;
|
||||||
|
@ -302,10 +302,16 @@ public abstract class FaweChangeSet implements ChangeSet {
|
|||||||
switch (combinedIdCurrent) {
|
switch (combinedIdCurrent) {
|
||||||
case 0:
|
case 0:
|
||||||
continue;
|
continue;
|
||||||
case 1:
|
|
||||||
combinedIdCurrent = 0;
|
|
||||||
default:
|
default:
|
||||||
int combinedIdPrevious = previousLayer != null ? previousLayer[index] : BlockID.AIR;
|
int combinedIdPrevious;
|
||||||
|
if (previousLayer != null) {
|
||||||
|
combinedIdPrevious = previousLayer[index];
|
||||||
|
if (combinedIdPrevious == 0) {
|
||||||
|
combinedIdPrevious = BlockID.AIR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
combinedIdPrevious = BlockID.AIR;
|
||||||
|
}
|
||||||
if (combinedIdCurrent != combinedIdPrevious) {
|
if (combinedIdCurrent != combinedIdPrevious) {
|
||||||
add(xx, yy, zz, combinedIdPrevious, combinedIdCurrent);
|
add(xx, yy, zz, combinedIdPrevious, combinedIdCurrent);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,233 @@
|
|||||||
|
package com.boydti.fawe.object.collection;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
||||||
|
|
||||||
|
public class ObjObjMap<K, V>
|
||||||
|
{
|
||||||
|
private static final Object FREE_KEY = new Object();
|
||||||
|
private static final Object REMOVED_KEY = new Object();
|
||||||
|
|
||||||
|
/** Keys and values */
|
||||||
|
private Object[] m_data;
|
||||||
|
|
||||||
|
/** Value for the null key (if inserted into a map) */
|
||||||
|
private Object m_nullValue;
|
||||||
|
private boolean m_hasNull;
|
||||||
|
|
||||||
|
/** Fill factor, must be between (0 and 1) */
|
||||||
|
private final float m_fillFactor;
|
||||||
|
/** We will resize a map once it reaches this size */
|
||||||
|
private int m_threshold;
|
||||||
|
/** Current map size */
|
||||||
|
private int m_size;
|
||||||
|
/** Mask to calculate the original position */
|
||||||
|
private int m_mask;
|
||||||
|
/** Mask to wrap the actual array pointer */
|
||||||
|
private int m_mask2;
|
||||||
|
|
||||||
|
public ObjObjMap( final int size, final float fillFactor )
|
||||||
|
{
|
||||||
|
if ( fillFactor <= 0 || fillFactor >= 1 )
|
||||||
|
throw new IllegalArgumentException( "FillFactor must be in (0, 1)" );
|
||||||
|
if ( size <= 0 )
|
||||||
|
throw new IllegalArgumentException( "Size must be positive!" );
|
||||||
|
final int capacity = arraySize(size, fillFactor);
|
||||||
|
m_mask = capacity - 1;
|
||||||
|
m_mask2 = capacity * 2 - 1;
|
||||||
|
m_fillFactor = fillFactor;
|
||||||
|
|
||||||
|
m_data = new Object[capacity * 2];
|
||||||
|
Arrays.fill( m_data, FREE_KEY );
|
||||||
|
|
||||||
|
m_threshold = (int) (capacity * fillFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public V get( @Nonnull final K key )
|
||||||
|
{
|
||||||
|
// if ( key == null )
|
||||||
|
// return (V) m_nullValue; //we null it on remove, so safe not to check a flag here
|
||||||
|
|
||||||
|
int ptr = (key.hashCode() & m_mask) << 1;
|
||||||
|
Object k = m_data[ ptr ];
|
||||||
|
|
||||||
|
// if ( k == FREE_KEY )
|
||||||
|
// return null; //end of chain already
|
||||||
|
if ( k == ( key ) ) //we check FREE and REMOVED prior to this call
|
||||||
|
return (V) m_data[ ptr + 1 ];
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
ptr = (ptr + 2) & m_mask2; //that's next index
|
||||||
|
k = m_data[ ptr ];
|
||||||
|
// if ( k == FREE_KEY )
|
||||||
|
// return null;
|
||||||
|
if ( k == ( key ) )
|
||||||
|
return (V) m_data[ ptr + 1 ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public V put( final K key, final V value )
|
||||||
|
{
|
||||||
|
if ( key == null )
|
||||||
|
return insertNullKey(value);
|
||||||
|
|
||||||
|
int ptr = getStartIndex(key) << 1;
|
||||||
|
Object k = m_data[ptr];
|
||||||
|
|
||||||
|
if ( k == FREE_KEY ) //end of chain already
|
||||||
|
{
|
||||||
|
m_data[ ptr ] = key;
|
||||||
|
m_data[ ptr + 1 ] = value;
|
||||||
|
if ( m_size >= m_threshold )
|
||||||
|
rehash( m_data.length * 2 ); //size is set inside
|
||||||
|
else
|
||||||
|
++m_size;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if ( k == ( key ) ) //we check FREE and REMOVED prior to this call
|
||||||
|
{
|
||||||
|
final Object ret = m_data[ ptr + 1 ];
|
||||||
|
m_data[ ptr + 1 ] = value;
|
||||||
|
return (V) ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int firstRemoved = -1;
|
||||||
|
if ( k == REMOVED_KEY )
|
||||||
|
firstRemoved = ptr; //we may find a key later
|
||||||
|
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
ptr = ( ptr + 2 ) & m_mask2; //that's next index calculation
|
||||||
|
k = m_data[ ptr ];
|
||||||
|
if ( k == FREE_KEY )
|
||||||
|
{
|
||||||
|
if ( firstRemoved != -1 )
|
||||||
|
ptr = firstRemoved;
|
||||||
|
m_data[ ptr ] = key;
|
||||||
|
m_data[ ptr + 1 ] = value;
|
||||||
|
if ( m_size >= m_threshold )
|
||||||
|
rehash( m_data.length * 2 ); //size is set inside
|
||||||
|
else
|
||||||
|
++m_size;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if ( k == ( key ) )
|
||||||
|
{
|
||||||
|
final Object ret = m_data[ ptr + 1 ];
|
||||||
|
m_data[ ptr + 1 ] = value;
|
||||||
|
return (V) ret;
|
||||||
|
}
|
||||||
|
else if ( k == REMOVED_KEY )
|
||||||
|
{
|
||||||
|
if ( firstRemoved == -1 )
|
||||||
|
firstRemoved = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public V remove( final K key )
|
||||||
|
{
|
||||||
|
if ( key == null )
|
||||||
|
return removeNullKey();
|
||||||
|
|
||||||
|
int ptr = getStartIndex(key) << 1;
|
||||||
|
Object k = m_data[ ptr ];
|
||||||
|
if ( k == FREE_KEY )
|
||||||
|
return null; //end of chain already
|
||||||
|
else if ( k == ( key ) ) //we check FREE and REMOVED prior to this call
|
||||||
|
{
|
||||||
|
--m_size;
|
||||||
|
if ( m_data[ ( ptr + 2 ) & m_mask2 ] == FREE_KEY )
|
||||||
|
m_data[ ptr ] = FREE_KEY;
|
||||||
|
else
|
||||||
|
m_data[ ptr ] = REMOVED_KEY;
|
||||||
|
final V ret = (V) m_data[ ptr + 1 ];
|
||||||
|
m_data[ ptr + 1 ] = null;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
ptr = ( ptr + 2 ) & m_mask2; //that's next index calculation
|
||||||
|
k = m_data[ ptr ];
|
||||||
|
if ( k == FREE_KEY )
|
||||||
|
return null;
|
||||||
|
else if ( k == ( key ) )
|
||||||
|
{
|
||||||
|
--m_size;
|
||||||
|
if ( m_data[ ( ptr + 2 ) & m_mask2 ] == FREE_KEY )
|
||||||
|
m_data[ ptr ] = FREE_KEY;
|
||||||
|
else
|
||||||
|
m_data[ ptr ] = REMOVED_KEY;
|
||||||
|
final V ret = (V) m_data[ ptr + 1 ];
|
||||||
|
m_data[ ptr + 1 ] = null;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private V insertNullKey(final V value)
|
||||||
|
{
|
||||||
|
if ( m_hasNull )
|
||||||
|
{
|
||||||
|
final Object ret = m_nullValue;
|
||||||
|
m_nullValue = value;
|
||||||
|
return (V) ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_nullValue = value;
|
||||||
|
++m_size;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private V removeNullKey()
|
||||||
|
{
|
||||||
|
if ( m_hasNull )
|
||||||
|
{
|
||||||
|
final Object ret = m_nullValue;
|
||||||
|
m_nullValue = null;
|
||||||
|
m_hasNull = false;
|
||||||
|
--m_size;
|
||||||
|
return (V) ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size()
|
||||||
|
{
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rehash( final int newCapacity )
|
||||||
|
{
|
||||||
|
m_threshold = (int) (newCapacity/2 * m_fillFactor);
|
||||||
|
m_mask = newCapacity/2 - 1;
|
||||||
|
m_mask2 = newCapacity - 1;
|
||||||
|
|
||||||
|
final int oldCapacity = m_data.length;
|
||||||
|
final Object[] oldData = m_data;
|
||||||
|
|
||||||
|
m_data = new Object[ newCapacity ];
|
||||||
|
Arrays.fill( m_data, FREE_KEY );
|
||||||
|
|
||||||
|
m_size = m_hasNull ? 1 : 0;
|
||||||
|
|
||||||
|
for ( int i = 0; i < oldCapacity; i += 2 ) {
|
||||||
|
final Object oldKey = oldData[ i ];
|
||||||
|
if( oldKey != FREE_KEY && oldKey != REMOVED_KEY )
|
||||||
|
put( (K)oldKey, (V)oldData[ i + 1 ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStartIndex( final Object key )
|
||||||
|
{
|
||||||
|
//key is not null here
|
||||||
|
return key.hashCode() & m_mask;
|
||||||
|
}
|
||||||
|
}
|
@ -2484,6 +2484,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
|
|||||||
* @throws MaxChangedBlocksException thrown if too many blocks are changed
|
* @throws MaxChangedBlocksException thrown if too many blocks are changed
|
||||||
*/
|
*/
|
||||||
public int makeSphere(final BlockVector3 pos, final Pattern block, double radiusX, double radiusY, double radiusZ, final boolean filled) {
|
public int makeSphere(final BlockVector3 pos, final Pattern block, double radiusX, double radiusY, double radiusZ, final boolean filled) {
|
||||||
|
System.out.println("Make sphere");
|
||||||
radiusX += 0.5;
|
radiusX += 0.5;
|
||||||
radiusY += 0.5;
|
radiusY += 0.5;
|
||||||
radiusZ += 0.5;
|
radiusZ += 0.5;
|
||||||
@ -2500,36 +2501,38 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
|
|||||||
final int ceilRadiusY = (int) Math.ceil(radiusY);
|
final int ceilRadiusY = (int) Math.ceil(radiusY);
|
||||||
final int ceilRadiusZ = (int) Math.ceil(radiusZ);
|
final int ceilRadiusZ = (int) Math.ceil(radiusZ);
|
||||||
|
|
||||||
double nextXn = 0;
|
double nextXn = invRadiusX;
|
||||||
double dx, dy, dz, dxy, dxyz;
|
double dx, dy, dz, dxz, dxyz;
|
||||||
forX:
|
forX:
|
||||||
for (int x = 0; x <= ceilRadiusX; ++x) {
|
for (int x = 0; x <= ceilRadiusX; ++x) {
|
||||||
final double xn = nextXn;
|
final double xn = nextXn;
|
||||||
dx = xn * xn;
|
dx = xn * xn;
|
||||||
nextXn = (x + 1) * invRadiusX;
|
nextXn = (x + 1) * invRadiusX;
|
||||||
double nextYn = 0;
|
double nextZn = invRadiusZ;
|
||||||
forY:
|
|
||||||
for (int y = 0; y <= ceilRadiusY; ++y) {
|
|
||||||
final double yn = nextYn;
|
|
||||||
dy = yn * yn;
|
|
||||||
dxy = dx + dy;
|
|
||||||
nextYn = (y + 1) * invRadiusY;
|
|
||||||
double nextZn = 0;
|
|
||||||
forZ:
|
forZ:
|
||||||
for (int z = 0; z <= ceilRadiusZ; ++z) {
|
for (int z = 0; z <= ceilRadiusZ; ++z) {
|
||||||
final double zn = nextZn;
|
final double zn = nextZn;
|
||||||
dz = zn * zn;
|
dz = zn * zn;
|
||||||
dxyz = dxy + dz;
|
dxz = dx + dz;
|
||||||
nextZn = (z + 1) * invRadiusZ;
|
nextZn = (z + 1) * invRadiusZ;
|
||||||
|
double nextYn = invRadiusY;
|
||||||
|
|
||||||
|
forY:
|
||||||
|
for (int y = 0; y <= ceilRadiusY; ++y) {
|
||||||
|
final double yn = nextYn;
|
||||||
|
dy = yn * yn;
|
||||||
|
dxyz = dxz + dy;
|
||||||
|
nextYn = (y + 1) * invRadiusY;
|
||||||
|
|
||||||
if (dxyz > 1) {
|
if (dxyz > 1) {
|
||||||
if (z == 0) {
|
|
||||||
if (y == 0) {
|
if (y == 0) {
|
||||||
|
if (z == 0) {
|
||||||
break forX;
|
break forX;
|
||||||
}
|
}
|
||||||
break forY;
|
|
||||||
}
|
|
||||||
break forZ;
|
break forZ;
|
||||||
}
|
}
|
||||||
|
break forY;
|
||||||
|
}
|
||||||
|
|
||||||
if (!filled) {
|
if (!filled) {
|
||||||
if (nextXn * nextXn + dy + dz <= 1 && nextYn * nextYn + dx + dz <= 1 && nextZn * nextZn + dx + dy <= 1) {
|
if (nextXn * nextXn + dy + dz <= 1 && nextYn * nextYn + dx + dz <= 1 && nextZn * nextZn + dx + dy <= 1) {
|
||||||
@ -2538,13 +2541,19 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setBlock(px + x, py + y, pz + z, block);
|
this.setBlock(px + x, py + y, pz + z, block);
|
||||||
this.setBlock(px - x, py + y, pz + z, block);
|
if (x != 0) this.setBlock(px - x, py + y, pz + z, block);
|
||||||
this.setBlock(px + x, py - y, pz + z, block);
|
if (z != 0) {
|
||||||
this.setBlock(px + x, py + y, pz - z, block);
|
this.setBlock(px + x, py + y, pz - z, block);
|
||||||
this.setBlock(px - x, py - y, pz + z, block);
|
if (x != 0) this.setBlock(px - x, py + y, pz - z, block);
|
||||||
|
}
|
||||||
|
if (y != 0) {
|
||||||
|
this.setBlock(px + x, py - y, pz + z, block);
|
||||||
|
if (x != 0) this.setBlock(px - x, py - y, pz + z, block);
|
||||||
|
if (z != 0) {
|
||||||
this.setBlock(px + x, py - y, pz - z, block);
|
this.setBlock(px + x, py - y, pz - z, block);
|
||||||
this.setBlock(px - x, py + y, pz - z, block);
|
if (x != 0) this.setBlock(px - x, py - y, pz - z, block);
|
||||||
this.setBlock(px - x, py - y, pz - z, block);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user