From 3eae592b59e387d53f53031d43e86ee29333fbb7 Mon Sep 17 00:00:00 2001 From: asiekierka Date: Sun, 26 Oct 2014 11:43:54 +0100 Subject: [PATCH] refactor SchematicRegistry to use BlockMetaPairs, add fluid and block heuristics --- api/buildcraft/api/blueprints/Schematic.java | 1 - .../api/blueprints/SchematicRegistry.java | 44 +++++++++++----- api/buildcraft/api/core/BlockMetaPair.java | 43 ++++++++++++++++ common/buildcraft/BuildCraftBuilders.java | 8 ++- .../builders/HeuristicBlockDetection.java | 51 +++++++++++++++++++ .../schematics/SchematicFactoryBlock.java | 2 +- .../buildcraft/core/blueprints/Blueprint.java | 11 ++-- .../core/blueprints/BptBuilderBlueprint.java | 4 +- .../core/builders/patterns/FillerPattern.java | 4 +- common/buildcraft/factory/TileQuarry.java | 2 +- 10 files changed, 143 insertions(+), 27 deletions(-) create mode 100644 api/buildcraft/api/core/BlockMetaPair.java create mode 100644 common/buildcraft/builders/HeuristicBlockDetection.java diff --git a/api/buildcraft/api/blueprints/Schematic.java b/api/buildcraft/api/blueprints/Schematic.java index 41e26a7f..2a6946fe 100755 --- a/api/buildcraft/api/blueprints/Schematic.java +++ b/api/buildcraft/api/blueprints/Schematic.java @@ -34,7 +34,6 @@ import buildcraft.api.core.IInvSlot; * buildcraft.core.schematics. */ public abstract class Schematic { - /** * Blocks are build in various stages, in order to make sure that a block * can indeed be placed, and that it's unlikely to disturb other blocks. diff --git a/api/buildcraft/api/blueprints/SchematicRegistry.java b/api/buildcraft/api/blueprints/SchematicRegistry.java index 8e7754a9..40e4fd66 100644 --- a/api/buildcraft/api/blueprints/SchematicRegistry.java +++ b/api/buildcraft/api/blueprints/SchematicRegistry.java @@ -23,7 +23,8 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidContainerRegistry; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; - +import net.minecraftforge.oredict.OreDictionary; +import buildcraft.api.core.BlockMetaPair; import buildcraft.api.core.JavaTools; public final class SchematicRegistry { @@ -31,8 +32,8 @@ public final class SchematicRegistry { public static int BREAK_ENERGY = 100; public static final int BUILD_ENERGY = 200; - private static final HashMap schematicBlocks = - new HashMap(); + private static final HashMap schematicBlocks = + new HashMap(); private static final HashMap, SchematicConstructor> schematicEntities = new HashMap, SchematicConstructor>(); @@ -92,12 +93,16 @@ public final class SchematicRegistry { throw new IllegalArgumentException("Could not find matching constructor for class " + clazz); } } - + public static void registerSchematicBlock(Block block, Class clazz, Object... params) { - if (schematicBlocks.containsKey(block)) { + registerSchematicBlock(block, OreDictionary.WILDCARD_VALUE, clazz, params); + } + + public static void registerSchematicBlock(Block block, int meta, Class clazz, Object... params) { + if (schematicBlocks.containsKey(new BlockMetaPair(block, meta))) { throw new RuntimeException("Block " + Block.blockRegistry.getNameForObject(block) + " is already associated with a schematic."); } - schematicBlocks.put(block, new SchematicConstructor(clazz, params)); + schematicBlocks.put(new BlockMetaPair(block, meta), new SchematicConstructor(clazz, params)); } public static void registerSchematicEntity( @@ -109,17 +114,27 @@ public final class SchematicRegistry { schematicEntities.put(entityClass, new SchematicConstructor(schematicClass, params)); } - public static SchematicBlock newSchematicBlock(Block block) { + public static SchematicBlock newSchematicBlock(Block block, int metadata) { if (block == Blocks.air) { return null; } - if (!schematicBlocks.containsKey(block)) { - return null; + BlockMetaPair pairWildcard = new BlockMetaPair(block, OreDictionary.WILDCARD_VALUE); + BlockMetaPair pair = new BlockMetaPair(block, metadata); + + SchematicConstructor c = null; + + if (schematicBlocks.containsKey(pair)) { + c = schematicBlocks.get(pair); + } else if (schematicBlocks.containsKey(pairWildcard)) { + c = schematicBlocks.get(pairWildcard); } + if (c == null) { + return null; + } + try { - SchematicConstructor c = schematicBlocks.get(block); SchematicBlock s = (SchematicBlock) c.newInstance(); s.block = block; return s; @@ -159,13 +174,14 @@ public final class SchematicRegistry { return null; } - public static boolean isSupported(Block block) { - return schematicBlocks.containsKey(block); + public static boolean isSupported(Block block, int metadata) { + return schematicBlocks.containsKey(new BlockMetaPair(block, OreDictionary.WILDCARD_VALUE)) + || schematicBlocks.containsKey(new BlockMetaPair(block, metadata)); } - public static boolean isAllowedForBuilding(Block block) { + public static boolean isAllowedForBuilding(Block block, int metadata) { String name = Block.blockRegistry.getNameForObject(block); - return isSupported(block) && !blocksForbidden.contains(name) && !modsForbidden.contains(name.split(":", 2)[0]); + return isSupported(block, metadata) && !blocksForbidden.contains(name) && !modsForbidden.contains(name.split(":", 2)[0]); } public static void readConfiguration(Configuration conf) { diff --git a/api/buildcraft/api/core/BlockMetaPair.java b/api/buildcraft/api/core/BlockMetaPair.java new file mode 100644 index 00000000..d23c2163 --- /dev/null +++ b/api/buildcraft/api/core/BlockMetaPair.java @@ -0,0 +1,43 @@ +package buildcraft.api.core; + +import net.minecraft.block.Block; + +public class BlockMetaPair implements Comparable { + private int id, meta; + + public BlockMetaPair(Block block, int meta) { + this.id = Block.getIdFromBlock(block); + this.meta = meta; + } + + public Block getBlock() { + return Block.getBlockById(id); + } + + public int meta() { + return meta; + } + + @Override + public int hashCode() { + return 17 * meta + id; + } + + @Override + public boolean equals(Object other) { + if (other == null || !(other instanceof BlockMetaPair)) { + return false; + } + + return ((BlockMetaPair) other).id == id && ((BlockMetaPair) other).meta == meta; + } + + @Override + public int compareTo(BlockMetaPair arg) { + if (arg.id != id) { + return (id - arg.id) * 16; + } else { + return (meta - arg.meta); + } + } +} diff --git a/common/buildcraft/BuildCraftBuilders.java b/common/buildcraft/BuildCraftBuilders.java index e0f27e6e..a1429982 100644 --- a/common/buildcraft/BuildCraftBuilders.java +++ b/common/buildcraft/BuildCraftBuilders.java @@ -28,6 +28,7 @@ import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLInterModComms; import cpw.mods.fml.common.event.FMLMissingMappingsEvent; +import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.event.FMLServerStoppingEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent; @@ -60,6 +61,7 @@ import buildcraft.builders.BlockPathMarker; import buildcraft.builders.BuilderProxy; import buildcraft.builders.EventHandlerBuilders; import buildcraft.builders.GuiHandler; +import buildcraft.builders.HeuristicBlockDetection; import buildcraft.builders.ItemBlueprintStandard; import buildcraft.builders.ItemBlueprintTemplate; import buildcraft.builders.ItemConstructionMarker; @@ -233,6 +235,11 @@ public class BuildCraftBuilders extends BuildCraftMod { return result; } + + @Mod.EventHandler + public void postInit(FMLPostInitializationEvent evt) { + HeuristicBlockDetection.start(); + } @Mod.EventHandler public void init(FMLInitializationEvent evt) { @@ -243,7 +250,6 @@ public class BuildCraftBuilders extends BuildCraftMod { MinecraftForge.EVENT_BUS.register(new EventHandlerBuilders()); // Standard blocks - SchematicRegistry.registerSchematicBlock(Blocks.snow, SchematicIgnore.class); SchematicRegistry.registerSchematicBlock(Blocks.tallgrass, SchematicIgnore.class); SchematicRegistry.registerSchematicBlock(Blocks.double_plant, SchematicIgnore.class); diff --git a/common/buildcraft/builders/HeuristicBlockDetection.java b/common/buildcraft/builders/HeuristicBlockDetection.java new file mode 100644 index 00000000..1834f904 --- /dev/null +++ b/common/buildcraft/builders/HeuristicBlockDetection.java @@ -0,0 +1,51 @@ +package buildcraft.builders; + +import buildcraft.api.blueprints.SchematicBlock; +import buildcraft.api.blueprints.SchematicFluid; +import buildcraft.api.blueprints.SchematicRegistry; +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; + +public final class HeuristicBlockDetection { + private HeuristicBlockDetection() { + + } + + public static void start() { + // Register fluids + for (Fluid f : FluidRegistry.getRegisteredFluids().values()) { + SchematicRegistry.registerSchematicBlock(f.getBlock(), SchematicFluid.class, new FluidStack(f, 1000)); + } + + // Register blocks + for (Object o : Block.blockRegistry.getKeys()) { + Block block = (Block) Block.blockRegistry.getObject(o); + if (block == null) { + continue; + } + + for (int meta = 0; meta < 16; meta++) { + if (!SchematicRegistry.isSupported(block, meta)) { + // Stops dupes with (for instance) ore blocks + try { + if (block.getItemDropped(meta, null, 0) != Item.getItemFromBlock(block)) { + continue; + } + } catch(NullPointerException e) { + // The "null" for Random in getItemDropped stops blocks + // depending on an RNG for deciding the dropped item + // from being autodetected. + } + if (block.hasTileEntity(meta)) { + continue; + } + + SchematicRegistry.registerSchematicBlock(block, meta, SchematicBlock.class); + } + } + } + } +} diff --git a/common/buildcraft/builders/schematics/SchematicFactoryBlock.java b/common/buildcraft/builders/schematics/SchematicFactoryBlock.java index e67e1669..dcd255c9 100755 --- a/common/buildcraft/builders/schematics/SchematicFactoryBlock.java +++ b/common/buildcraft/builders/schematics/SchematicFactoryBlock.java @@ -33,7 +33,7 @@ public class SchematicFactoryBlock extends SchematicFactory { return s; } else { - SchematicBlock s = SchematicRegistry.newSchematicBlock(b); + SchematicBlock s = SchematicRegistry.newSchematicBlock(b, nbt.getInteger("blockMeta")); if (s != null) { s.readFromNBT(nbt, registry); diff --git a/common/buildcraft/core/blueprints/Blueprint.java b/common/buildcraft/core/blueprints/Blueprint.java index c185f413..b132de9c 100644 --- a/common/buildcraft/core/blueprints/Blueprint.java +++ b/common/buildcraft/core/blueprints/Blueprint.java @@ -77,7 +77,8 @@ public class Blueprint extends BlueprintBase { public void readFromWorld(IBuilderContext context, TileEntity anchorTile, int x, int y, int z) { BptContext bptContext = (BptContext) context; Block block = anchorTile.getWorldObj().getBlock(x, y, z); - + int meta = anchorTile.getWorldObj().getBlockMetadata(x, y, z); + if (context.world().isAirBlock(x, y, z)) { // Although no schematic will be returned for the block "air" by // the registry, there can be other blocks considered as air. This @@ -85,7 +86,7 @@ public class Blueprint extends BlueprintBase { return; } - SchematicBlock slot = SchematicRegistry.newSchematicBlock(block); + SchematicBlock slot = SchematicRegistry.newSchematicBlock(block, meta); if (slot == null) { return; @@ -96,9 +97,9 @@ public class Blueprint extends BlueprintBase { int posZ = (int) (z - context.surroundingBox().pMin().z); slot.block = block; - slot.meta = anchorTile.getWorldObj().getBlockMetadata(x, y, z); + slot.meta = meta; - if (!SchematicRegistry.isSupported(block)) { + if (!SchematicRegistry.isSupported(block, meta)) { return; } @@ -212,7 +213,7 @@ public class Blueprint extends BlueprintBase { } if (block != null) { - contents[x][y][z] = SchematicRegistry.newSchematicBlock(block); + contents[x][y][z] = SchematicRegistry.newSchematicBlock(block, cpt.getInteger("blockMeta")); contents[x][y][z].readFromNBT(cpt, mapping); if (!contents[x][y][z].doNotUse()) { diff --git a/common/buildcraft/core/blueprints/BptBuilderBlueprint.java b/common/buildcraft/core/blueprints/BptBuilderBlueprint.java index ca181dda..a7ad2262 100644 --- a/common/buildcraft/core/blueprints/BptBuilderBlueprint.java +++ b/common/buildcraft/core/blueprints/BptBuilderBlueprint.java @@ -95,7 +95,7 @@ public class BptBuilderBlueprint extends BptBuilderBase { slot.block = Blocks.air; } - if (!SchematicRegistry.isAllowedForBuilding(slot.block)) { + if (!SchematicRegistry.isAllowedForBuilding(slot.block, slot.meta)) { continue; } @@ -131,7 +131,7 @@ public class BptBuilderBlueprint extends BptBuilderBase { continue; } - if (!SchematicRegistry.isAllowedForBuilding(slot.block)) { + if (!SchematicRegistry.isAllowedForBuilding(slot.block, slot.meta)) { continue; } diff --git a/common/buildcraft/core/builders/patterns/FillerPattern.java b/common/buildcraft/core/builders/patterns/FillerPattern.java index 62a2d5f9..d6ae7bd7 100644 --- a/common/buildcraft/core/builders/patterns/FillerPattern.java +++ b/common/buildcraft/core/builders/patterns/FillerPattern.java @@ -113,7 +113,7 @@ public abstract class FillerPattern implements IFillerPattern { public abstract Template getTemplate (Box box, World world); - public Blueprint getBlueprint (Box box, World world, Block block) { + public Blueprint getBlueprint (Box box, World world, Block block, int meta) { Blueprint result = new Blueprint (box.sizeX(), box.sizeY(), box.sizeZ()); Template tmpl = getTemplate(box, world); @@ -123,7 +123,7 @@ public abstract class FillerPattern implements IFillerPattern { for (int z = 0; z < box.sizeZ(); ++z) { if (tmpl.contents[x][y][z] != null) { result.contents[x][y][z] = SchematicRegistry - .newSchematicBlock(block); + .newSchematicBlock(block, meta); } } diff --git a/common/buildcraft/factory/TileQuarry.java b/common/buildcraft/factory/TileQuarry.java index 39586e58..7f3def4f 100644 --- a/common/buildcraft/factory/TileQuarry.java +++ b/common/buildcraft/factory/TileQuarry.java @@ -620,7 +620,7 @@ public class TileQuarry extends TileAbstractBuilder implements IMachine, ISidedI private void initializeBlueprintBuilder() { Blueprint bpt = ((FillerPattern) FillerManager.registry.getPattern("buildcraft:frame")) - .getBlueprint(box, worldObj, BuildCraftFactory.frameBlock); + .getBlueprint(box, worldObj, BuildCraftFactory.frameBlock, 0); builder = new BptBuilderBlueprint(bpt, worldObj, box.xMin, yCoord, box.zMin); stage = Stage.BUILDING;