static blocktype initialization

instead of using hacky reflection
This commit is contained in:
Jesse Boyd 2019-11-02 20:35:51 +01:00
parent 70efdf8c54
commit 32d837414b
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
35 changed files with 1128 additions and 989 deletions

View File

@ -11,6 +11,7 @@ import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.world.block.BlockID;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.jpountz.util.UnsafeUtils;
import net.minecraft.server.v1_14_R1.Block;
import net.minecraft.server.v1_14_R1.Chunk;
@ -273,7 +274,7 @@ public class BukkitAdapter_1_14 {
for (int i = 0; i < num_palette; i++) {
final int ordinal = paletteToBlock[i];
blockToPalette[ordinal] = Integer.MAX_VALUE;
final BlockState state = BlockTypes.states[ordinal];
final BlockState state = BlockTypesCache.states[ordinal];
final IBlockData ibd = ((BlockMaterial_1_14) state.getMaterial()).getState();
palette.a(ibd);
}

View File

@ -64,6 +64,7 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import net.minecraft.server.v1_14_R1.Block;
@ -178,7 +179,7 @@ public final class Spigot_v1_14_R4 extends CachedBukkitAdapter implements Bukkit
if (idbToStateOrdinal != null) return false;
idbToStateOrdinal = new char[Block.REGISTRY_ID.a()]; // size
for (int i = 0; i < idbToStateOrdinal.length; i++) {
BlockState state = BlockTypes.states[i];
BlockState state = BlockTypesCache.states[i];
BlockMaterial_1_14 material = (BlockMaterial_1_14) state.getMaterial();
int id = Block.REGISTRY_ID.getId(material.getState());
idbToStateOrdinal[id] = state.getOrdinalChar();
@ -612,7 +613,7 @@ public final class Spigot_v1_14_R4 extends CachedBukkitAdapter implements Bukkit
}
public BlockState adapt(IBlockData ibd) {
return BlockTypes.states[adaptToInt(ibd)];
return BlockTypesCache.states[adaptToInt(ibd)];
}
public int adaptToInt(IBlockData ibd) {

View File

@ -11,6 +11,7 @@ import com.sk89q.worldedit.world.block.BlockID;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import org.bukkit.FluidCollisionMode;
import org.bukkit.Location;
import org.bukkit.Material;
@ -57,7 +58,7 @@ public class AsyncBlock implements Block {
}
public int getPropertyId() {
return world.getBlock(x, y, z).getInternalId() >> BlockTypes.BIT_OFFSET;
return world.getBlock(x, y, z).getInternalId() >> BlockTypesCache.BIT_OFFSET;
}
public int getCombinedId() {
@ -105,7 +106,7 @@ public class AsyncBlock implements Block {
@Deprecated
public boolean setTypeIdAndPropertyId(int id, int propertyId) {
return setCombinedId(id + (propertyId << BlockTypes.BIT_OFFSET));
return setCombinedId(id + (propertyId << BlockTypesCache.BIT_OFFSET));
}
@Deprecated

View File

@ -9,6 +9,7 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
@ -42,7 +43,7 @@ public class AsyncBlockState implements BlockState {
}
public int getPropertyId() {
return state.getInternalId() >> BlockTypes.BIT_OFFSET;
return state.getInternalId() >> BlockTypesCache.BIT_OFFSET;
}
@Override
@ -158,12 +159,12 @@ public class AsyncBlockState implements BlockState {
@Override
public byte getRawData() {
return (byte) (state.getInternalId() >> BlockTypes.BIT_OFFSET);
return (byte) (state.getInternalId() >> BlockTypesCache.BIT_OFFSET);
}
@Override
public void setRawData(byte data) {
int combinedId = getTypeId() + (data << BlockTypes.BIT_OFFSET);
int combinedId = getTypeId() + (data << BlockTypesCache.BIT_OFFSET);
state = com.sk89q.worldedit.world.block.BlockState.getFromInternalId(combinedId).toBaseBlock(state.getNbtData());
this.blockData = BukkitAdapter.adapt(state);
}

View File

@ -6,6 +6,7 @@ import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import java.util.List;
@ -58,7 +59,7 @@ public abstract class CachedBukkitAdapter implements IBukkitAdapter {
@Override
public BlockType adapt(Material material) {
try {
return BlockTypes.values[blockTypes[material.ordinal()]];
return BlockTypesCache.values[blockTypes[material.ordinal()]];
} catch (NullPointerException e) {
if (init()) return adapt(material);
throw e;

View File

@ -28,6 +28,7 @@ import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.math.MutableVector3;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.lang.reflect.Field;
import java.util.ArrayList;
@ -219,7 +220,7 @@ public enum FaweCache implements Trimable {
public final CleanableThreadLocal<byte[]> BYTE_BUFFER_8192 = new CleanableThreadLocal<>(() -> new byte[8192]);
public final CleanableThreadLocal<int[]> BLOCK_TO_PALETTE = new CleanableThreadLocal<>(() -> {
int[] result = new int[BlockTypes.states.length];
int[] result = new int[BlockTypesCache.states.length];
Arrays.fill(result, Integer.MAX_VALUE);
return result;
});
@ -296,7 +297,7 @@ public enum FaweCache implements Trimable {
int ordinal = blocksChars[i];
int palette = blockToPalette[ordinal];
if (palette == Integer.MAX_VALUE) {
// BlockState state = BlockTypes.states[ordinal];
// BlockState state = BlockTypesCache.states[ordinal];
blockToPalette[ordinal] = palette = num_palette;
paletteToBlock[num_palette] = ordinal;
num_palette++;
@ -308,7 +309,7 @@ public enum FaweCache implements Trimable {
int ordinal = blocksInts[i];
int palette = blockToPalette[ordinal];
if (palette == Integer.MAX_VALUE) {
BlockState state = BlockTypes.states[ordinal];
BlockState state = BlockTypesCache.states[ordinal];
blockToPalette[ordinal] = palette = num_palette;
paletteToBlock[num_palette] = ordinal;
num_palette++;

View File

@ -7,6 +7,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.util.Map;
import java.util.Set;
@ -96,7 +97,7 @@ public abstract class CharBlocks implements IBlocks {
@Override
public BlockState getBlock(int x, int y, int z) {
return BlockTypes.states[get(x, y, z)];
return BlockTypesCache.states[get(x, y, z)];
}
public char get(int x, int y, int z) {

View File

@ -5,17 +5,18 @@ import com.boydti.fawe.beta.IChunkSet;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
public abstract class CharGetBlocks extends CharBlocks implements IChunkGet {
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
return BlockTypes.states[get(x, y, z)].toBaseBlock();
return BlockTypesCache.states[get(x, y, z)].toBaseBlock();
}
@Override
public BlockState getBlock(int x, int y, int z) {
return BlockTypes.states[get(x, y, z)];
return BlockTypesCache.states[get(x, y, z)];
}
@Override

View File

@ -13,6 +13,7 @@ import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.util.Collections;
import java.util.HashSet;
@ -74,7 +75,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
@Override
public BlockState getBlock(int x, int y, int z) {
return BlockTypes.states[get(x, y, z)];
return BlockTypesCache.states[get(x, y, z)];
}
@Override

View File

@ -7,6 +7,8 @@ import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -14,7 +16,7 @@ import java.util.List;
public class DistrFilter extends ForkedFilter<DistrFilter> {
private final int[] counter = new int[BlockTypes.states.length];
private final int[] counter = new int[BlockTypesCache.states.length];
public DistrFilter() {
super(null);
@ -45,7 +47,7 @@ public class DistrFilter extends ForkedFilter<DistrFilter> {
int total = 0;
for (int i = 0; i < counter.length; i++) {
int value = counter[i];
if (value != 0 && mask.test(BlockTypes.states[i])) {
if (value != 0 && mask.test(BlockTypesCache.states[i])) {
total += value;
}
}
@ -61,7 +63,7 @@ public class DistrFilter extends ForkedFilter<DistrFilter> {
for (int i = 0; i < counter.length; i++) {
final int count = counter[i];
if (count != 0) {
distribution.add(new Countable<>(BlockTypes.states[i], count));
distribution.add(new Countable<>(BlockTypesCache.states[i], count));
}
}
Collections.sort(distribution);
@ -70,18 +72,18 @@ public class DistrFilter extends ForkedFilter<DistrFilter> {
public List<Countable<BlockType>> getTypeDistribution() {
final List<Countable<BlockType>> distribution = new ArrayList<>();
int[] typeCounter = new int[BlockTypes.values.length];
int[] typeCounter = new int[BlockTypesCache.values.length];
for (int i = 0; i < counter.length; i++) {
final int count = counter[i];
if (count != 0) {
BlockState state = BlockTypes.states[i];
BlockState state = BlockTypesCache.states[i];
typeCounter[state.getBlockType().getInternalId()] += count;
}
}
for (int i = 0; i < typeCounter.length; i++) {
final int count = typeCounter[i];
if (count != 0) {
distribution.add(new Countable<>(BlockTypes.values[i], count));
distribution.add(new Countable<>(BlockTypesCache.values[i], count));
}
}
Collections.sort(distribution);

View File

@ -9,6 +9,8 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import javax.annotation.Nullable;
public class ArrayFilterBlock extends SimpleFilterBlock {
@ -51,7 +53,7 @@ public class ArrayFilterBlock extends SimpleFilterBlock {
@Override
public BlockState getBlock() {
return BlockTypes.states[ordinal];
return BlockTypesCache.states[ordinal];
}
@Override

View File

@ -1,6 +1,6 @@
package com.boydti.fawe.beta.implementation.filter.block;
import static com.sk89q.worldedit.world.block.BlockTypes.states;
import static com.sk89q.worldedit.world.block.BlockTypesCache.states;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlockMask;
@ -19,6 +19,7 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import javax.annotation.Nullable;
@ -231,7 +232,7 @@ public class CharFilterBlock extends ChunkFilterBlock {
@Override
public final BlockState getBlock() {
final int ordinal = getArr[index];
return BlockTypes.states[ordinal];
return BlockTypesCache.states[ordinal];
}
@Override

View File

@ -23,6 +23,7 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.io.IOException;
import java.util.ArrayList;
@ -251,7 +252,7 @@ public class MCAChunk implements IChunkSet {
int ordinal = blocks[i];
int palette = blockToPalette[ordinal];
if (palette == Integer.MAX_VALUE) {
// BlockState state = BlockTypes.states[ordinal];
// BlockState state = BlockTypesCache.states[ordinal];
blockToPalette[ordinal] = palette = num_palette;
paletteToBlock[num_palette] = ordinal;
num_palette++;
@ -269,7 +270,7 @@ public class MCAChunk implements IChunkSet {
for (int i = 0; i < num_palette; i++) {
int ordinal = paletteToBlock[i];
BlockState state = BlockTypes.states[ordinal];
BlockState state = BlockTypesCache.states[ordinal];
BlockType type = state.getBlockType();
out.writeNamedTag("Name", type.getId());

View File

@ -56,6 +56,8 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
@ -438,7 +440,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = minX; x <= maxX; x++, index++, localIndex++) {
int combined = floor[index];
if (BlockTypes.getFromStateOrdinal(combined) == BlockTypes.SNOW) {
layers[localIndex] = (char) (((heights[index] & 0xFF) << 3) + (floor[index] >> BlockTypes.BIT_OFFSET) - 7);
layers[localIndex] = (char) (((heights[index] & 0xFF) << 3) + (floor[index] >> BlockTypesCache.BIT_OFFSET) - 7);
} else {
layers[localIndex] = (char) ((heights[index] & 0xFF) << 3);
}
@ -526,7 +528,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int i = 0; i < heights.length; i++) {
int combined = floor[i];
if (BlockTypes.getFromStateOrdinal(combined) == BlockTypes.SNOW) {
layers[i] = (char) (((heights[i] & 0xFF) << 3) + (floor[i] >> BlockTypes.BIT_OFFSET) - 7);
layers[i] = (char) (((heights[i] & 0xFF) << 3) + (floor[i] >> BlockTypesCache.BIT_OFFSET) - 7);
} else {
layers[i] = (char) ((heights[i] & 0xFF) << 3);
}

View File

@ -17,6 +17,8 @@ import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@ -457,7 +459,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
public int maxZ;
public DiskStorageSummary(int x, int z) {
blocks = new int[BlockTypes.states.length];
blocks = new int[BlockTypesCache.states.length];
minX = x;
maxX = x;
minZ = z;
@ -482,7 +484,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
HashMap<BlockState, Integer> map = new HashMap<>();
for (int i = 0; i < blocks.length; i++) {
if (blocks[i] != 0) {
BlockState state = BlockTypes.states[i];
BlockState state = BlockTypesCache.states[i];
map.put(state, blocks[i]);
}
}

View File

@ -15,6 +15,8 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.util.ArrayList;
import java.util.List;
@ -28,7 +30,7 @@ public class PropertyPattern extends AbstractExtentPattern {
public PropertyPattern(Extent extent) {
super(extent);
this.transformed = new int[BlockTypes.states.length];
this.transformed = new int[BlockTypesCache.states.length];
for (int i = 0; i < transformed.length; i++) {
transformed[i] = i;
}
@ -107,13 +109,13 @@ public class PropertyPattern extends AbstractExtentPattern {
}
} else {
for (int i = 0; i < values.size(); i++) {
int statesIndex = current.modifyIndex(stateId, i) >> BlockTypes.BIT_OFFSET;
int statesIndex = current.modifyIndex(stateId, i) >> BlockTypesCache.BIT_OFFSET;
BlockState state = type.withPropertyId(statesIndex);
int existingOrdinal = transformed[state.getOrdinal()];
int existing = BlockTypes.states[existingOrdinal].getInternalId();
//states[statesIndex] << BlockTypes.BIT_OFFSET;
BlockState newState = state.withPropertyId(property.modifyIndex(existing, index) >> BlockTypes.BIT_OFFSET);
int existing = BlockTypesCache.states[existingOrdinal].getInternalId();
//states[statesIndex] << BlockTypesCache.BIT_OFFSET;
BlockState newState = state.withPropertyId(property.modifyIndex(existing, index) >> BlockTypesCache.BIT_OFFSET);
transformed[state.getOrdinal()] = newState.getOrdinal();
}
}
@ -135,7 +137,7 @@ public class PropertyPattern extends AbstractExtentPattern {
} else {
String regex = charSequence.toString();
blockTypeList = new ArrayList<>();
for (BlockType myType : BlockTypes.values) {
for (BlockType myType : BlockTypesCache.values) {
if (myType.getId().matches(regex)) {
blockTypeList.add(myType);
}

View File

@ -9,6 +9,8 @@ import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.util.SplittableRandom;
public class SolidRandomOffsetPattern extends AbstractPattern {
@ -21,7 +23,7 @@ public class SolidRandomOffsetPattern extends AbstractPattern {
public static boolean[] getTypes() {
boolean[] types = new boolean[BlockTypes.size()];
for (BlockType type : BlockTypes.values) {
for (BlockType type : BlockTypesCache.values) {
types[type.getInternalId()] = type.getMaterial().isSolid();
}
return types;

View File

@ -0,0 +1,70 @@
package com.boydti.fawe.object.string;
public class JoinedCharSequence implements CharSequence {
private char join;
private int len2;
private int len1;
private int length;
private String a;
private String b;
public JoinedCharSequence init(String a, char join, String b) {
this.len1 = a.length();
this.len2 = b.length();
this.length = len1 + len2 + 1;
this.join = join;
this.a = a;
this.b = b;
return this;
}
@Override
public int length() {
return length;
}
@Override
public char charAt(int index) {
if (index < len1) {
return a.charAt(index);
}
if (index == len1) {
return join;
}
return b.charAt(index - len1 - 1);
}
@Override
public CharSequence subSequence(int start, int end) {
char[] chars = new char[end - start];
for (int i = start, j = 0; i < end; i++, j++) {
chars[j] = charAt(i);
}
return new String(chars);
}
@Override
public int hashCode() {
int h = 0;
for (int i = 0; i < length; i++) {
h = 31 * h + charAt(i);
}
return h;
}
@Override
public String toString() {
return (String) subSequence(0, length);
}
@Override
public boolean equals(Object obj) {
CharSequence anotherString = (CharSequence) obj;
if (length == anotherString.length()) {
for (int i = length - 1; i >= 0; i--) {
if (charAt(i) != anotherString.charAt(i)) return false;
}
return true;
}
return false;
}
}

View File

@ -12,6 +12,7 @@ import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@ -593,7 +594,7 @@ public class TextureUtil implements TextureHolder {
if (folder.exists()) {
// Get all the jar files
File[] files = folder.listFiles((dir, name) -> name.endsWith(".jar"));
for (BlockType blockType : BlockTypes.values) {
for (BlockType blockType : BlockTypesCache.values) {
BlockMaterial material = blockType.getMaterial();
if (!material.isSolid() || !material.isFullCube()) {
continue;
@ -635,7 +636,7 @@ public class TextureUtil implements TextureHolder {
Type typeToken = new TypeToken<Map<String, Object>>() {
}.getType();
for (BlockType blockType : BlockTypes.values) {
for (BlockType blockType : BlockTypesCache.values) {
if (!blockType.getMaterial().isFullCube()) {
continue;
}

View File

@ -53,6 +53,7 @@ import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import net.jpountz.lz4.LZ4BlockInputStream;
@ -198,7 +199,7 @@ public class SpongeSchematicReader extends NBTSchematicReader {
}
private BlockState getBlockState(int id) {
return BlockTypes.states[palette[id]];
return BlockTypesCache.states[palette[id]];
}
private BiomeType getBiomeType(FaweInputStream fis) throws IOException {

View File

@ -42,6 +42,7 @@ import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
@ -138,7 +139,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
NBTOutputStream tilesOut = new NBTOutputStream(new LZ4BlockOutputStream(tilesCompressed));
List<Integer> paletteList = new ArrayList<>();
char[] palette = new char[BlockTypes.states.length];
char[] palette = new char[BlockTypesCache.states.length];
Arrays.fill(palette, Character.MAX_VALUE);
int[] paletteMax = {0};
int numTiles = 0;
@ -175,7 +176,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
out.writeLazyCompoundTag("Palette", out12 -> {
for (int i = 0; i < paletteList.size(); i++) {
int stateOrdinal = paletteList.get(i);
BlockState state = BlockTypes.states[stateOrdinal];
BlockState state = BlockTypesCache.states[stateOrdinal];
out12.writeNamedTag(state.getAsString(), i);
}
});

View File

@ -67,6 +67,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Nullable;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import org.jetbrains.annotations.NotNull;
/**
@ -468,14 +470,14 @@ public class BlockTransformExtent extends ResettableExtent {
int internalId = state.getInternalId();
int maskedId = internalId & mask;
int newMaskedId = arr[maskedId >> BlockTypes.BIT_OFFSET];
int newMaskedId = arr[maskedId >> BlockTypesCache.BIT_OFFSET];
if (newMaskedId != -1) {
return BlockState.getFromInternalId(newMaskedId | (internalId & (~mask)));
}
newMaskedId = transformState(state, transform);
arr[maskedId >> BlockTypes.BIT_OFFSET] = newMaskedId & mask;
arr[maskedId >> BlockTypesCache.BIT_OFFSET] = newMaskedId & mask;
return BlockState.getFromInternalId(newMaskedId);
}

View File

@ -5,6 +5,7 @@ import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.util.ArrayList;
import java.util.List;
@ -19,7 +20,7 @@ public abstract class ABlockMask extends AbstractExtentMask {
@Override
public String toString() {
List<String> strings = new ArrayList<>();
for (BlockType type : BlockTypes.values) {
for (BlockType type : BlockTypesCache.values) {
if (type != null) {
boolean hasAll;
List<BlockState> all = type.getAllStates();
@ -43,7 +44,7 @@ public abstract class ABlockMask extends AbstractExtentMask {
if (mask instanceof ABlockMask) {
ABlockMask other = (ABlockMask) mask;
BlockMask newMask = new BlockMask(getExtent());
for (BlockState state : BlockTypes.states) {
for (BlockState state : BlockTypesCache.states) {
if (state != null) {
if (test(state) && other.test(state)) {
newMask.add(state);
@ -62,7 +63,7 @@ public abstract class ABlockMask extends AbstractExtentMask {
if (mask instanceof ABlockMask) {
ABlockMask other = (ABlockMask) mask;
BlockMask newMask = new BlockMask(getExtent());
for (BlockState state : BlockTypes.states) {
for (BlockState state : BlockTypesCache.states) {
if (state != null) {
if (test(state) || other.test(state)) {
newMask.add(state);

View File

@ -28,6 +28,7 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.util.Arrays;
import java.util.Collection;
@ -51,7 +52,7 @@ public class BlockMask extends ABlockMask {
}
public BlockMask(Extent extent) {
this(extent, new boolean[BlockTypes.states.length]);
this(extent, new boolean[BlockTypesCache.states.length]);
}
public BlockMask(Extent extent, boolean[] ordinals) {
@ -86,7 +87,7 @@ public class BlockMask extends ABlockMask {
public BlockMask add(Predicate<BlockState> predicate) {
for (int i = 0; i < ordinals.length; i++) {
if (!ordinals[i]) {
BlockState state = BlockTypes.states[i];
BlockState state = BlockTypesCache.states[i];
if (state != null) {
ordinals[i] = predicate.test(state);
}
@ -221,7 +222,7 @@ public class BlockMask extends ABlockMask {
BlockType unsetType = null;
int totalTypes = 0;
for (BlockType type : BlockTypes.values) {
for (BlockType type : BlockTypesCache.values) {
if (type != null) {
totalTypes++;
boolean hasAll = true;

View File

@ -14,6 +14,7 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.util.*;
import java.util.function.BiPredicate;
@ -102,7 +103,7 @@ public class BlockMaskBuilder {
} else {
String regex = charSequence.toString();
blockTypeList = new ArrayList<>();
for (BlockType myType : BlockTypes.values) {
for (BlockType myType : BlockTypesCache.values) {
if (myType.getId().matches(regex)) {
blockTypeList.add(myType);
add(myType);
@ -209,7 +210,7 @@ public class BlockMaskBuilder {
if (StringMan.isAlphanumericUnd(input)) {
add(BlockTypes.parse(input));
} else {
for (BlockType myType : BlockTypes.values) {
for (BlockType myType : BlockTypesCache.values) {
if (myType.getId().matches(input)) {
add(myType);
}
@ -223,7 +224,7 @@ public class BlockMaskBuilder {
AbstractProperty prop = (AbstractProperty) property;
long[] states = bitSets[type.getInternalId()];
if (states == null) return false;
int localI = index << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
int localI = index << prop.getBitOffset() >> BlockTypesCache.BIT_OFFSET;
return (states == ALL || FastBitSet.get(states, localI));
}
@ -357,7 +358,7 @@ public class BlockMaskBuilder {
for (AbstractProperty prop : properties) {
List values = prop.getValues();
for (int j = 0; j < values.size(); j++) {
int localI = j << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
int localI = j << prop.getBitOffset() >> BlockTypesCache.BIT_OFFSET;
if (states == ALL || FastBitSet.get(states, localI)) {
if (!allowed.test(type, new AbstractMap.SimpleEntry(prop, values.get(j)))) {
if (states == ALL) {
@ -435,7 +436,7 @@ public class BlockMaskBuilder {
for (AbstractProperty prop : (List<AbstractProperty<?>>) type.getProperties()) {
List values = prop.getValues();
for (int j = 0; j < values.size(); j++) {
int localI = j << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
int localI = j << prop.getBitOffset() >> BlockTypesCache.BIT_OFFSET;
if (states == null || !FastBitSet.get(states, localI)) {
if (propPredicate.test(type, new AbstractMap.SimpleEntry(prop, values.get(j)))) {
if (states == null) {
@ -457,7 +458,7 @@ public class BlockMaskBuilder {
if (states == ALL) return this;
List values = property.getValues();
int localI = index << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
int localI = index << prop.getBitOffset() >> BlockTypesCache.BIT_OFFSET;
if (states == null || !FastBitSet.get(states, localI)) {
if (states == null) {
bitSets[type.getInternalId()] = states = FastBitSet.create(type.getMaxStateId() + 1);
@ -473,7 +474,7 @@ public class BlockMaskBuilder {
long[] states = bitSets[type.getInternalId()];
if (states == null) return this;
List values = property.getValues();
int localI = index << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
int localI = index << prop.getBitOffset() >> BlockTypesCache.BIT_OFFSET;
if (states == ALL || FastBitSet.get(states, localI)) {
if (states == ALL) {
bitSets[type.getInternalId()] = states = FastBitSet.create(type.getMaxStateId() + 1);
@ -495,7 +496,7 @@ public class BlockMaskBuilder {
}
} else {
for (int i = 0; i < values.size(); i++) {
int index = current.modifyIndex(state, i) >> BlockTypes.BIT_OFFSET;
int index = current.modifyIndex(state, i) >> BlockTypesCache.BIT_OFFSET;
if (set) FastBitSet.set(states, index);
else FastBitSet.clear(states, index);
}
@ -543,7 +544,7 @@ public class BlockMaskBuilder {
for (AbstractProperty prop : (List<AbstractProperty<?>>) type.getProperties()) {
List values = prop.getValues();
for (int j = 0; j < values.size(); j++) {
int localI = j << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
int localI = j << prop.getBitOffset() >> BlockTypesCache.BIT_OFFSET;
if (FastBitSet.get(bitSet, localI)) set++;
else clear++;
}
@ -558,11 +559,11 @@ public class BlockMaskBuilder {
private boolean[] getOrdinals() {
if (ordinals == null) {
ordinals = new boolean[BlockTypes.states.length];
for (int i = 0; i < BlockTypes.values.length; i++) {
ordinals = new boolean[BlockTypesCache.states.length];
for (int i = 0; i < BlockTypesCache.values.length; i++) {
long[] bitSet = bitSets[i];
if (bitSet == null) continue;
BlockType type = BlockTypes.values[i];
BlockType type = BlockTypesCache.values[i];
if (bitSet == ALL) {
for (BlockState state : type.getAllStates()) {
ordinals[state.getOrdinal()] = true;

View File

@ -5,6 +5,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
public class InverseSingleBlockTypeMask extends ABlockMask {
private final int internalId;
@ -26,7 +27,7 @@ public class InverseSingleBlockTypeMask extends ABlockMask {
@Override
public Mask inverse() {
return new SingleBlockTypeMask(getExtent(), BlockTypes.values[internalId]);
return new SingleBlockTypeMask(getExtent(), BlockTypesCache.values[internalId]);
}
public BlockType getBlockType() {

View File

@ -5,6 +5,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
public class SingleBlockTypeMask extends ABlockMask {
private final int internalId;
@ -26,7 +27,7 @@ public class SingleBlockTypeMask extends ABlockMask {
@Override
public Mask inverse() {
return new InverseSingleBlockTypeMask(getExtent(), BlockTypes.values[internalId]);
return new InverseSingleBlockTypeMask(getExtent(), BlockTypesCache.values[internalId]);
}
public BlockType getBlockType() {

View File

@ -27,6 +27,8 @@ import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.lang.ref.SoftReference;
/**
@ -39,7 +41,7 @@ public class WaterloggedRemover extends AbstractExtentPattern {
private synchronized BlockState[] getRemap() {
BlockState[] remap = cache.get();
if (remap != null) return remap;
cache = new SoftReference<>(remap = new BlockState[BlockTypes.states.length]);
cache = new SoftReference<>(remap = new BlockState[BlockTypesCache.states.length]);
// init
for (int i = 0; i < remap.length; i++) {

View File

@ -23,6 +23,7 @@ import com.boydti.fawe.util.MathMan;
import static com.google.common.base.Preconditions.checkState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import javax.annotation.Nullable;
import java.util.List;
@ -46,7 +47,7 @@ public abstract class AbstractProperty<T> implements Property<T> {
this.name = name;
this.values = values;
this.numBits = MathMan.log2nlz(values.size());
this.bitOffset = bitOffset + BlockTypes.BIT_OFFSET;
this.bitOffset = bitOffset + BlockTypesCache.BIT_OFFSET;
this.bitMask = (((1 << numBits) - 1)) << this.bitOffset;
this.bitMaskInverse = ~this.bitMask;
this.key = PropertyKey.getOrCreate(name);

View File

@ -4,6 +4,7 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import java.util.ArrayList;
import java.util.Arrays;
@ -57,7 +58,7 @@ public class PropertyGroup<G, A> {
public PropertyGroup build() {
PropertyFunction[] states = new PropertyFunction[BlockTypes.size()];
Property prop;
for (BlockType type : BlockTypes.values) {
for (BlockType type : BlockTypesCache.values) {
for (Object[] func : funcs) {
if ((prop = type.getProperty((PropertyKey) func[0])) != null) {
PropertyFunction pf = new PropertyFunction(prop, (Function) func[1], (Function) func[2]);

View File

@ -77,7 +77,7 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
@Deprecated
public static BlockState getFromOrdinal(int ordinal) {
return BlockTypes.states[ordinal];
return BlockTypesCache.states[ordinal];
}
/**
@ -122,7 +122,7 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
type = BlockTypes.get(key);
if (type == null) {
String input = key.toString();
throw new SuggestInputParseException("Does not match a valid block type: " + input, input, () -> Stream.of(BlockTypes.values)
throw new SuggestInputParseException("Does not match a valid block type: " + input, input, () -> Stream.of(BlockTypesCache.values)
.filter(b -> StringMan.blockStateMatches(input, b.getId()))
.map(BlockType::getId)
.sorted(StringMan.blockStateComparator(input))
@ -203,7 +203,7 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
continue;
}
}
return type.withPropertyId(stateId >> BlockTypes.BIT_OFFSET);
return type.withPropertyId(stateId >> BlockTypesCache.BIT_OFFSET);
}
@Override
@ -237,13 +237,13 @@ public class BlockState implements BlockStateHolder<BlockState>, FawePattern {
@Deprecated
@Override
public final int getInternalPropertiesId() {
return this.getInternalId() >> BlockTypes.BIT_OFFSET;
return this.getInternalId() >> BlockTypesCache.BIT_OFFSET;
}
@Deprecated
@Override
public final int getInternalBlockTypeId() {
return this.getInternalId() & BlockTypes.BIT_MASK;
return this.getInternalId() & BlockTypesCache.BIT_MASK;
}
@Override

View File

@ -51,7 +51,7 @@ public class BlockType implements FawePattern, Keyed {
public static final NamespacedRegistry<BlockType> REGISTRY = new NamespacedRegistry<>("block type");
private final String id;
private final BlockTypes.Settings settings;
private final BlockTypesCache.Settings settings;
private boolean initItemType;
private ItemType itemType;
@ -59,7 +59,7 @@ public class BlockType implements FawePattern, Keyed {
protected BlockType(String id, int internalId, List<BlockState> states) {
int i = id.indexOf("[");
this.id = i == -1 ? id : id.substring(0, i);
this.settings = new BlockTypes.Settings(this, id, internalId, states);
this.settings = new BlockTypesCache.Settings(this, id, internalId, states);
}
@Deprecated
@ -105,12 +105,12 @@ public class BlockType implements FawePattern, Keyed {
@Deprecated
public BlockState withPropertyId(int propertyId) {
if (settings.stateOrdinals == null) return settings.defaultState;
return BlockTypes.states[settings.stateOrdinals[propertyId]];
return BlockTypesCache.states[settings.stateOrdinals[propertyId]];
}
@Deprecated
public BlockState withStateId(int internalStateId) { //
return this.withPropertyId(internalStateId >> BlockTypes.BIT_OFFSET);
return this.withPropertyId(internalStateId >> BlockTypesCache.BIT_OFFSET);
}
/**
@ -180,7 +180,7 @@ public class BlockType implements FawePattern, Keyed {
*/
public List<BlockState> getAllStates() {
if (settings.stateOrdinals == null) return Collections.singletonList(getDefaultState());
return IntStream.of(settings.stateOrdinals).filter(i -> i != -1).mapToObj(i -> BlockTypes.states[i]).collect(Collectors.toList());
return IntStream.of(settings.stateOrdinals).filter(i -> i != -1).mapToObj(i -> BlockTypesCache.states[i]).collect(Collectors.toList());
}
/**

View File

@ -17,7 +17,7 @@ public class BlockTypeSwitchBuilder<T> {
}
public BlockTypeSwitchBuilder<T> add(Predicate<BlockType> predicate, T task) {
for (BlockType type : BlockTypes.values) {
for (BlockType type : BlockTypesCache.values) {
if (predicate.test(type)) {
this.runnables[type.getInternalId()] = task;
}

View File

@ -0,0 +1,243 @@
package com.sk89q.worldedit.world.block;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.registry.state.AbstractProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import com.sk89q.worldedit.world.registry.BlockRegistry;
import com.sk89q.worldedit.world.registry.Registries;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class BlockTypesCache {
/*
-----------------------------------------------------
Settings
-----------------------------------------------------
*/
protected final static class Settings {
protected final int internalId;
protected final BlockState defaultState;
protected final AbstractProperty<?>[] propertiesMapArr;
protected final AbstractProperty<?>[] propertiesArr;
protected final List<AbstractProperty<?>> propertiesList;
protected final Map<String, AbstractProperty<?>> propertiesMap;
protected final Set<AbstractProperty<?>> propertiesSet;
protected final BlockMaterial blockMaterial;
protected final int permutations;
protected int[] stateOrdinals;
Settings(BlockType type, String id, int internalId, List<BlockState> states) {
this.internalId = internalId;
String propertyString = null;
int propI = id.indexOf('[');
if (propI != -1) {
propertyString = id.substring(propI + 1, id.length() - 1);
}
int maxInternalStateId = 0;
Map<String, ? extends Property<?>> properties = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getProperties(type);
if (!properties.isEmpty()) {
// Ensure the properties are registered
int maxOrdinal = 0;
for (String key : properties.keySet()) {
maxOrdinal = Math.max(PropertyKey.getOrCreate(key).ordinal(), maxOrdinal);
}
this.propertiesMapArr = new AbstractProperty[maxOrdinal + 1];
int prop_arr_i = 0;
this.propertiesArr = new AbstractProperty[properties.size()];
HashMap<String, AbstractProperty<?>> propMap = new HashMap<>();
int bitOffset = 0;
for (Map.Entry<String, ? extends Property<?>> entry : properties.entrySet()) {
PropertyKey key = PropertyKey.getOrCreate(entry.getKey());
AbstractProperty<?> property = ((AbstractProperty) entry.getValue()).withOffset(bitOffset);
this.propertiesMapArr[key.ordinal()] = property;
this.propertiesArr[prop_arr_i++] = property;
propMap.put(entry.getKey(), property);
maxInternalStateId += (property.getValues().size() << bitOffset);
bitOffset += property.getNumBits();
}
this.propertiesList = Arrays.asList(this.propertiesArr);
this.propertiesMap = Collections.unmodifiableMap(propMap);
this.propertiesSet = new LinkedHashSet<>(this.propertiesMap.values());
} else {
this.propertiesMapArr = new AbstractProperty[0];
this.propertiesArr = this.propertiesMapArr;
this.propertiesList = Collections.emptyList();
this.propertiesMap = Collections.emptyMap();
this.propertiesSet = Collections.emptySet();
}
this.permutations = maxInternalStateId;
this.blockMaterial = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(type);
if (!propertiesList.isEmpty()) {
this.stateOrdinals = generateStateOrdinals(internalId, states.size(), maxInternalStateId, propertiesList);
for (int propId = 0; propId < this.stateOrdinals.length; propId++) {
int ordinal = this.stateOrdinals[propId];
if (ordinal != -1) {
int stateId = internalId + (propId << BIT_OFFSET);
BlockState state = new BlockState(type, stateId, ordinal);
states.add(state);
}
}
int defaultPropId = parseProperties(propertyString, propertiesMap) >> BIT_OFFSET;
this.defaultState = states.get(this.stateOrdinals[defaultPropId]);
} else {
this.defaultState = new BlockState(type, internalId, states.size());
states.add(this.defaultState);
}
}
private int parseProperties(String properties, Map<String, AbstractProperty<?>> propertyMap) {
int id = internalId;
for (String keyPair : properties.split(",")) {
String[] split = keyPair.split("=");
String name = split[0];
String value = split[1];
AbstractProperty btp = propertyMap.get(name);
id = btp.modify(id, btp.getValueFor(value));
}
return id;
}
}
private static int[] generateStateOrdinals(int internalId, int ordinal, int maxStateId, List<AbstractProperty<?>> props) {
if (props.isEmpty()) return null;
int[] result = new int[maxStateId];
Arrays.fill(result, -1);
int[] state = new int[props.size()];
int[] sizes = new int[props.size()];
for (int i = 0; i < props.size(); i++) {
sizes[i] = props.get(i).getValues().size();
}
int index = 0;
outer:
while (true) {
// Create the state
int stateId = internalId;
for (int i = 0; i < state.length; i++) {
stateId = props.get(i).modifyIndex(stateId, state[i]);
}
// Map it to the ordinal
result[stateId >> BIT_OFFSET] = ordinal++;
// Increment the state
while (++state[index] == sizes[index]) {
state[index] = 0;
index++;
if (index == state.length) break outer;
}
index = 0;
}
return result;
}
/*
-----------------------------------------------------
Static Initializer
-----------------------------------------------------
*/
public static final int BIT_OFFSET; // Used internally
protected static final int BIT_MASK; // Used internally
// private static final Map<String, BlockType> $REGISTRY = new HashMap<>();
// public static final NamespacedRegistry<BlockType> REGISTRY = new NamespacedRegistry<>("block type", $REGISTRY);
public static final BlockType[] values;
public static final BlockState[] states;
protected static final Set<String> $NAMESPACES = new LinkedHashSet<>();
static {
try {
ArrayList<BlockState> stateList = new ArrayList<>();
Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS);
Registries registries = platform.getRegistries();
BlockRegistry blockReg = registries.getBlockRegistry();
Collection<String> blocks = blockReg.registerBlocks();
Map<String, String> blockMap = blocks.stream().collect(Collectors.toMap(item -> item.charAt(item.length() - 1) == ']' ? item.substring(0, item.indexOf('[')) : item, item -> item));
int size = blockMap.size();
Field[] idFields = BlockID.class.getDeclaredFields();
for (Field field : idFields) size = Math.max(field.getInt(null) + 1, size);
BIT_OFFSET = MathMan.log2nlz(size);
BIT_MASK = ((1 << BIT_OFFSET) - 1);
values = new BlockType[size];
// Register the statically declared ones first
for (Field field : idFields) {
if (field.getType() == int.class) {
int internalId = field.getInt(null);
String id = "minecraft:" + field.getName().toLowerCase(Locale.ROOT);
String defaultState = blockMap.remove(id);
if (defaultState == null) {
if (internalId != 0) {
System.out.println("Ignoring invalid block " + id);
continue;
}
defaultState = id;
}
if (values[internalId] != null) {
throw new IllegalStateException("Invalid duplicate id for " + field.getName());
}
BlockType type = register(defaultState, internalId, stateList);
// Note: Throws IndexOutOfBoundsError if nothing is registered and blocksMap is empty
values[internalId] = type;
}
}
{ // Register new blocks
int internalId = 1;
for (Map.Entry<String, String> entry : blockMap.entrySet()) {
String defaultState = entry.getValue();
// Skip already registered ids
for (; values[internalId] != null; internalId++);
BlockType type = register(defaultState, internalId, stateList);
values[internalId] = type;
}
}
states = stateList.toArray(new BlockState[stateList.size()]);
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
private static BlockType register(final String id, int internalId, List<BlockState> states) {
// Get the enum name (remove namespace if minecraft:)
int propStart = id.indexOf('[');
String typeName = id.substring(0, propStart == -1 ? id.length() : propStart);
String enumName = (typeName.startsWith("minecraft:") ? typeName.substring(10) : typeName).toUpperCase(Locale.ROOT);
BlockType existing = new BlockType(id, internalId, states);
// register states
BlockType.REGISTRY.register(typeName, existing);
String nameSpace = typeName.substring(0, typeName.indexOf(':'));
$NAMESPACES.add(nameSpace);
return existing;
}
}