From 27c7d488a255084d9a9d0004c6172f8b898bba8b Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 23 May 2019 23:19:23 -0700 Subject: [PATCH] Add perf. improvments for Forge --- .../worldedit/bukkit/BukkitBlockRegistry.java | 6 ----- .../internal/block/BlockStateIdAccess.java | 27 ++++++++++++++++++- .../worldedit/world/block/BlockState.java | 1 + .../world/registry/BlockRegistry.java | 8 ------ .../world/registry/BundledBlockRegistry.java | 5 ---- .../worldedit/forge/ForgeBlockRegistry.java | 17 +----------- .../com/sk89q/worldedit/forge/ForgeWorld.java | 13 ++++++--- 7 files changed, 37 insertions(+), 40 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java index 79690df26..3100fde4e 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockRegistry.java @@ -81,12 +81,6 @@ public class BukkitBlockRegistry extends BundledBlockRegistry { return id; } - @Nullable - @Override - public BlockState getBlockStateByInternalId(int id) { - return id >= statesById.length ? null : statesById[id]; - } - public static class BukkitBlockMaterial extends PassthroughBlockMaterial { private final Material material; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/BlockStateIdAccess.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/BlockStateIdAccess.java index f7f9d66f0..88ed3d93b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/BlockStateIdAccess.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/BlockStateIdAccess.java @@ -21,8 +21,12 @@ package com.sk89q.worldedit.internal.block; import com.sk89q.worldedit.world.block.BlockState; +import javax.annotation.Nullable; +import java.util.Arrays; import java.util.OptionalInt; +import static com.google.common.base.Preconditions.checkState; + public class BlockStateIdAccess { private BlockStateIdAccess() { @@ -40,7 +44,28 @@ public class BlockStateIdAccess { } public static OptionalInt getBlockStateId(BlockState holder) { - return blockStateStateId.getBlockStateId((BlockState) holder); + return blockStateStateId.getBlockStateId(holder); + } + + public static @Nullable BlockState getBlockStateById(int id) { + return id < blockStates.length ? blockStates[id] : null; + } + + private static BlockState[] blockStates = new BlockState[2 << 14]; + + public static void register(BlockState blockState) { + OptionalInt id = getBlockStateId(blockState); + if (id.isPresent()) { + int i = id.getAsInt(); + while (i >= blockStates.length) { + blockStates = Arrays.copyOf(blockStates, blockStates.length + blockStates.length >> 1); + } + BlockState existing = blockStates[i]; + checkState(existing == null || existing == blockState, + "BlockState %s is using the same block ID (%s) as BlockState %s", + blockState, i, existing); + blockStates[i] = blockState; + } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java index 1cd83cb3e..aeeae8210 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java @@ -68,6 +68,7 @@ public class BlockState implements BlockStateHolder { BlockState initializeId(BlockRegistry registry) { this.internalId = registry.getInternalBlockStateId(this); + BlockStateIdAccess.register(this); return this; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java index d17662b0e..fb572f019 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockRegistry.java @@ -67,12 +67,4 @@ public interface BlockRegistry { */ OptionalInt getInternalBlockStateId(BlockState state); - /** - * Retrieve a block state by its internal ID, if possible. - * - * @param id The internal ID - * @return the block state, if available - */ - @Nullable - BlockState getBlockStateByInternalId(int id); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java index 0b52ae01a..0e5615475 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BundledBlockRegistry.java @@ -59,9 +59,4 @@ public class BundledBlockRegistry implements BlockRegistry { return OptionalInt.empty(); } - @Override - public BlockState getBlockStateByInternalId(int id) { - return null; - } - } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBlockRegistry.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBlockRegistry.java index 998f8674e..8751fff89 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBlockRegistry.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeBlockRegistry.java @@ -27,23 +27,18 @@ import com.sk89q.worldedit.world.registry.BundledBlockRegistry; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; -import net.minecraft.init.Blocks; import net.minecraft.state.IProperty; -import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.loading.FMLLoader; -import net.minecraftforge.registries.GameData; +import javax.annotation.Nullable; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.OptionalInt; import java.util.TreeMap; -import javax.annotation.Nullable; - public class ForgeBlockRegistry extends BundledBlockRegistry { - private final int airId = Block.getStateId(Blocks.AIR.getDefaultState()); private Map materialMap = new HashMap<>(); @Nullable @@ -85,14 +80,4 @@ public class ForgeBlockRegistry extends BundledBlockRegistry { IBlockState equivalent = ForgeAdapter.adapt(state); return OptionalInt.of(Block.getStateId(equivalent)); } - - @Override - public BlockState getBlockStateByInternalId(int id) { - IBlockState equivalent = Block.getStateById(id); - if (equivalent.equals(Blocks.AIR.getDefaultState()) && id != airId) { - // We didn't find a match. - return null; - } - return ForgeAdapter.adapt(equivalent); - } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index 3b1dabeb2..f0c00dd45 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -19,8 +19,6 @@ package com.sk89q.worldedit.forge; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -92,6 +90,7 @@ import net.minecraft.world.gen.feature.TallTaigaTreeFeature; import net.minecraft.world.gen.feature.TreeFeature; import net.minecraft.world.storage.WorldInfo; +import javax.annotation.Nullable; import java.io.File; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -101,7 +100,7 @@ import java.util.Random; import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; -import javax.annotation.Nullable; +import static com.google.common.base.Preconditions.checkNotNull; /** * An adapter to Minecraft worlds for WorldEdit. @@ -464,13 +463,19 @@ public class ForgeWorld extends AbstractWorld { position.getBlockZ() ); + BlockState matchingBlock = BlockStateIdAccess.getBlockStateById(Block.getStateId(mcState)); + if (matchingBlock != null) { + return matchingBlock; + } + return ForgeAdapter.adapt(mcState); } @Override public BaseBlock getFullBlock(BlockVector3 position) { BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - TileEntity tile = getWorld().getTileEntity(pos); + // Avoid creation by using the CHECK mode -- if it's needed, it'll be re-created anyways + TileEntity tile = getWorld().getChunk(pos).getTileEntity(pos, Chunk.EnumCreateEntityType.CHECK); if (tile != null) { return getBlock(position).toBaseBlock(NBTConverter.fromNative(TileEntityUtils.copyNbtData(tile)));