From 84601f685fea0a92d11f1a28e0b1e0a1742a27c2 Mon Sep 17 00:00:00 2001 From: George Paton Date: Fri, 8 Aug 2025 14:51:45 +1000 Subject: [PATCH] NBTStructureLib features brought back to NTM, including: * `/locate` command * custom spawning rules (eg. make something always spawn at 0,0) * code structure reorg * extra logging for misconfigured structures --- .../java/com/hbm/blocks/BlockDummyable.java | 6 +- .../com/hbm/blocks/generic/BlockBobble.java | 6 +- .../com/hbm/blocks/generic/BlockDecoCRT.java | 6 +- .../hbm/blocks/generic/BlockDecoModel.java | 4 +- .../hbm/blocks/generic/BlockDecoToaster.java | 6 +- .../com/hbm/blocks/generic/BlockModDoor.java | 6 +- .../com/hbm/blocks/generic/BlockPipe.java | 6 +- .../com/hbm/blocks/generic/BlockPlushie.java | 6 +- .../hbm/blocks/generic/BlockWandJigsaw.java | 6 +- .../hbm/blocks/generic/BlockWandLogic.java | 2 +- .../com/hbm/blocks/generic/BlockWandLoot.java | 2 +- .../com/hbm/blocks/generic/DecoBlock.java | 6 +- .../generic/DecoPoleSatelliteReceiver.java | 6 +- .../hbm/blocks/generic/DecoTapeRecorder.java | 6 +- .../hbm/blocks/machine/BlockMachineBase.java | 6 +- .../com/hbm/blocks/machine/Floodlight.java | 4 +- .../com/hbm/blocks/machine/Spotlight.java | 6 +- .../com/hbm/blocks/network/FluidPump.java | 6 +- .../java/com/hbm/commands/CommandLocate.java | 118 ++++++++ .../java/com/hbm/items/tool/ItemWandS.java | 2 +- src/main/java/com/hbm/lib/HbmWorld.java | 3 +- src/main/java/com/hbm/main/MainRegistry.java | 1 + .../java/com/hbm/main/StructureManager.java | 2 +- .../com/hbm/world/gen/NTMWorldGenerator.java | 44 +-- .../INBTBlockTransformable.java} | 28 +- .../INBTTileEntityTransformable.java | 2 +- .../com/hbm/world/gen/nbt/JigsawPiece.java | 35 +++ .../com/hbm/world/gen/nbt/JigsawPool.java | 58 ++++ .../hbm/world/gen/{ => nbt}/NBTStructure.java | 274 +++++++----------- .../com/hbm/world/gen/nbt/SpawnCondition.java | 115 ++++++++ src/main/resources/assets/hbm/lang/en_US.lang | 4 + 31 files changed, 537 insertions(+), 245 deletions(-) create mode 100644 src/main/java/com/hbm/commands/CommandLocate.java rename src/main/java/com/hbm/world/gen/{INBTTransformable.java => nbt/INBTBlockTransformable.java} (89%) rename src/main/java/com/hbm/world/gen/{ => nbt}/INBTTileEntityTransformable.java (90%) create mode 100644 src/main/java/com/hbm/world/gen/nbt/JigsawPiece.java create mode 100644 src/main/java/com/hbm/world/gen/nbt/JigsawPool.java rename src/main/java/com/hbm/world/gen/{ => nbt}/NBTStructure.java (84%) create mode 100644 src/main/java/com/hbm/world/gen/nbt/SpawnCondition.java diff --git a/src/main/java/com/hbm/blocks/BlockDummyable.java b/src/main/java/com/hbm/blocks/BlockDummyable.java index 19c33db65..fe9a001ca 100644 --- a/src/main/java/com/hbm/blocks/BlockDummyable.java +++ b/src/main/java/com/hbm/blocks/BlockDummyable.java @@ -5,7 +5,7 @@ import com.hbm.handler.ThreeInts; import com.hbm.interfaces.ICopiable; import com.hbm.main.MainRegistry; import com.hbm.tileentity.IPersistentNBT; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.common.network.internal.FMLNetworkHandler; import cpw.mods.fml.relauncher.Side; @@ -37,7 +37,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -public abstract class BlockDummyable extends BlockContainer implements ICustomBlockHighlight, ICopiable, INBTTransformable { +public abstract class BlockDummyable extends BlockContainer implements ICustomBlockHighlight, ICopiable, INBTBlockTransformable { public BlockDummyable(Material mat) { super(mat); @@ -590,7 +590,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl meta -= extra; } - meta = INBTTransformable.transformMetaDeco(meta, coordBaseMode); + meta = INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode); if(isOffset) { meta += offset; diff --git a/src/main/java/com/hbm/blocks/generic/BlockBobble.java b/src/main/java/com/hbm/blocks/generic/BlockBobble.java index ea53feb69..3ba895977 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockBobble.java +++ b/src/main/java/com/hbm/blocks/generic/BlockBobble.java @@ -4,8 +4,8 @@ import com.hbm.inventory.gui.GUIScreenBobble; import com.hbm.items.special.ItemPlasticScrap.ScrapType; import com.hbm.main.MainRegistry; import com.hbm.tileentity.IGUIProvider; -import com.hbm.world.gen.INBTTileEntityTransformable; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTTileEntityTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.common.network.internal.FMLNetworkHandler; import cpw.mods.fml.relauncher.Side; @@ -34,7 +34,7 @@ import net.minecraft.world.World; import java.util.List; import java.util.Random; -public class BlockBobble extends BlockContainer implements IGUIProvider, INBTTransformable { +public class BlockBobble extends BlockContainer implements IGUIProvider, INBTBlockTransformable { public BlockBobble() { super(Material.iron); diff --git a/src/main/java/com/hbm/blocks/generic/BlockDecoCRT.java b/src/main/java/com/hbm/blocks/generic/BlockDecoCRT.java index b1ede562a..bee8f863e 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockDecoCRT.java +++ b/src/main/java/com/hbm/blocks/generic/BlockDecoCRT.java @@ -2,7 +2,7 @@ package com.hbm.blocks.generic; import com.hbm.blocks.BlockMulti; import com.hbm.lib.RefStrings; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.relauncher.Side; @@ -15,7 +15,7 @@ import net.minecraft.util.IIcon; import net.minecraft.util.MathHelper; import net.minecraft.world.World; -public class BlockDecoCRT extends BlockMulti implements INBTTransformable { +public class BlockDecoCRT extends BlockMulti implements INBTBlockTransformable { protected String[] variants = new String[] {"crt_clean", "crt_broken", "crt_blinking", "crt_bsod"}; @SideOnly(Side.CLIENT) protected IIcon[] icons; @@ -77,7 +77,7 @@ public class BlockDecoCRT extends BlockMulti implements INBTTransformable { @Override public int transformMeta(int meta, int coordBaseMode) { - return INBTTransformable.transformMetaDecoModel(meta, coordBaseMode); + return INBTBlockTransformable.transformMetaDecoModel(meta, coordBaseMode); } } \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/generic/BlockDecoModel.java b/src/main/java/com/hbm/blocks/generic/BlockDecoModel.java index 2e2febe67..fcf9fbc7e 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockDecoModel.java +++ b/src/main/java/com/hbm/blocks/generic/BlockDecoModel.java @@ -1,7 +1,7 @@ package com.hbm.blocks.generic; import com.hbm.blocks.BlockEnumMulti; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.client.registry.RenderingRegistry; import net.minecraft.block.material.Material; @@ -12,7 +12,7 @@ import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -public class BlockDecoModel extends BlockEnumMulti implements INBTTransformable { +public class BlockDecoModel extends BlockEnumMulti implements INBTBlockTransformable { public BlockDecoModel(Material mat, Class theEnum, boolean multiName, boolean multiTexture) { super(mat, theEnum, multiName, multiTexture); diff --git a/src/main/java/com/hbm/blocks/generic/BlockDecoToaster.java b/src/main/java/com/hbm/blocks/generic/BlockDecoToaster.java index c35dd1d3b..149cdf7f4 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockDecoToaster.java +++ b/src/main/java/com/hbm/blocks/generic/BlockDecoToaster.java @@ -2,7 +2,7 @@ package com.hbm.blocks.generic; import com.hbm.blocks.BlockMulti; import com.hbm.lib.RefStrings; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.relauncher.Side; @@ -17,7 +17,7 @@ import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -public class BlockDecoToaster extends BlockMulti implements INBTTransformable { +public class BlockDecoToaster extends BlockMulti implements INBTBlockTransformable { protected String[] variants = new String[] {"toaster_iron", "toaster_steel", "toaster_wood"}; @SideOnly(Side.CLIENT) protected IIcon[] icons; @@ -94,7 +94,7 @@ public class BlockDecoToaster extends BlockMulti implements INBTTransformable { @Override public int transformMeta(int meta, int coordBaseMode) { - return INBTTransformable.transformMetaDecoModel(meta, coordBaseMode); + return INBTBlockTransformable.transformMetaDecoModel(meta, coordBaseMode); } } \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/generic/BlockModDoor.java b/src/main/java/com/hbm/blocks/generic/BlockModDoor.java index 233f8da71..0093135d5 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockModDoor.java +++ b/src/main/java/com/hbm/blocks/generic/BlockModDoor.java @@ -4,7 +4,7 @@ import java.util.Random; import com.hbm.blocks.ModBlocks; import com.hbm.items.ModItems; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -21,7 +21,7 @@ import net.minecraft.util.Vec3; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -public class BlockModDoor extends Block implements INBTTransformable { +public class BlockModDoor extends Block implements INBTBlockTransformable { @SideOnly(Side.CLIENT) private IIcon[] field_150017_a; @SideOnly(Side.CLIENT) @@ -400,6 +400,6 @@ public class BlockModDoor extends Block implements INBTTransformable { @Override public int transformMeta(int meta, int coordBaseMode) { - return INBTTransformable.transformMetaDoor(meta, coordBaseMode); + return INBTBlockTransformable.transformMetaDoor(meta, coordBaseMode); } } \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/generic/BlockPipe.java b/src/main/java/com/hbm/blocks/generic/BlockPipe.java index 27eaf3b27..824fc5aae 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockPipe.java +++ b/src/main/java/com/hbm/blocks/generic/BlockPipe.java @@ -4,7 +4,7 @@ import java.util.List; import com.hbm.blocks.ITooltipProvider; import com.hbm.lib.RefStrings; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.relauncher.Side; @@ -17,7 +17,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.IIcon; import net.minecraft.world.World; -public class BlockPipe extends Block implements ITooltipProvider, INBTTransformable { +public class BlockPipe extends Block implements ITooltipProvider, INBTBlockTransformable { @SideOnly(Side.CLIENT) private IIcon sideIcon; @@ -96,7 +96,7 @@ public class BlockPipe extends Block implements ITooltipProvider, INBTTransforma @Override public int transformMeta(int meta, int coordBaseMode) { - return INBTTransformable.transformMetaPillar(meta, coordBaseMode); + return INBTBlockTransformable.transformMetaPillar(meta, coordBaseMode); } } \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/generic/BlockPlushie.java b/src/main/java/com/hbm/blocks/generic/BlockPlushie.java index 848065a84..877d784e7 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockPlushie.java +++ b/src/main/java/com/hbm/blocks/generic/BlockPlushie.java @@ -5,8 +5,8 @@ import java.util.Random; import com.hbm.blocks.IBlockMulti; import com.hbm.blocks.ITooltipProvider; -import com.hbm.world.gen.INBTTileEntityTransformable; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTTileEntityTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -29,7 +29,7 @@ import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.StatCollector; import net.minecraft.world.World; -public class BlockPlushie extends BlockContainer implements IBlockMulti, ITooltipProvider, INBTTransformable { +public class BlockPlushie extends BlockContainer implements IBlockMulti, ITooltipProvider, INBTBlockTransformable { public BlockPlushie() { super(Material.cloth); diff --git a/src/main/java/com/hbm/blocks/generic/BlockWandJigsaw.java b/src/main/java/com/hbm/blocks/generic/BlockWandJigsaw.java index 63076df31..d64470934 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockWandJigsaw.java +++ b/src/main/java/com/hbm/blocks/generic/BlockWandJigsaw.java @@ -18,7 +18,7 @@ import com.hbm.tileentity.IGUIProvider; import com.hbm.tileentity.TileEntityLoadedBase; import com.hbm.util.BufferUtil; import com.hbm.util.i18n.I18nUtil; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.common.network.internal.FMLNetworkHandler; import cpw.mods.fml.common.registry.GameRegistry; @@ -47,7 +47,7 @@ import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.client.event.RenderGameOverlayEvent.Pre; -public class BlockWandJigsaw extends BlockContainer implements IBlockSideRotation, INBTTransformable, IGUIProvider, ILookOverlay { +public class BlockWandJigsaw extends BlockContainer implements IBlockSideRotation, INBTBlockTransformable, IGUIProvider, ILookOverlay { private IIcon iconTop; private IIcon iconSide; @@ -123,7 +123,7 @@ public class BlockWandJigsaw extends BlockContainer implements IBlockSideRotatio @Override public int transformMeta(int meta, int coordBaseMode) { - return INBTTransformable.transformMetaDeco(meta, coordBaseMode); + return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode); } @Override diff --git a/src/main/java/com/hbm/blocks/generic/BlockWandLogic.java b/src/main/java/com/hbm/blocks/generic/BlockWandLogic.java index 01d8df298..f7c3b2aa2 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockWandLogic.java +++ b/src/main/java/com/hbm/blocks/generic/BlockWandLogic.java @@ -13,8 +13,8 @@ import com.hbm.main.MainRegistry; import com.hbm.tileentity.TileEntityLoadedBase; import com.hbm.util.BufferUtil; import com.hbm.util.i18n.I18nUtil; +import com.hbm.world.gen.nbt.INBTTileEntityTransformable; import com.hbm.world.gen.util.LogicBlockActions; -import com.hbm.world.gen.INBTTileEntityTransformable; import com.hbm.world.gen.util.LogicBlockConditions; import com.hbm.world.gen.util.LogicBlockInteractions; import cpw.mods.fml.common.registry.GameRegistry; diff --git a/src/main/java/com/hbm/blocks/generic/BlockWandLoot.java b/src/main/java/com/hbm/blocks/generic/BlockWandLoot.java index bf457843d..cf5cebce0 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockWandLoot.java +++ b/src/main/java/com/hbm/blocks/generic/BlockWandLoot.java @@ -17,7 +17,7 @@ import com.hbm.tileentity.TileEntityLoadedBase; import com.hbm.util.BufferUtil; import com.hbm.util.LootGenerator; import com.hbm.util.i18n.I18nUtil; -import com.hbm.world.gen.INBTTileEntityTransformable; +import com.hbm.world.gen.nbt.INBTTileEntityTransformable; import com.mojang.authlib.GameProfile; import api.hbm.block.IToolable; diff --git a/src/main/java/com/hbm/blocks/generic/DecoBlock.java b/src/main/java/com/hbm/blocks/generic/DecoBlock.java index bf25850eb..05642281a 100644 --- a/src/main/java/com/hbm/blocks/generic/DecoBlock.java +++ b/src/main/java/com/hbm/blocks/generic/DecoBlock.java @@ -6,7 +6,7 @@ import java.util.Random; import com.hbm.blocks.ModBlocks; import com.hbm.tileentity.deco.TileEntityDecoBlock; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import api.hbm.block.IToolable; import cpw.mods.fml.client.registry.RenderingRegistry; @@ -25,7 +25,7 @@ import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -public class DecoBlock extends BlockContainer implements IToolable, INBTTransformable { +public class DecoBlock extends BlockContainer implements IToolable, INBTBlockTransformable { Random rand = new Random(); @@ -185,6 +185,6 @@ public class DecoBlock extends BlockContainer implements IToolable, INBTTransfor @Override public int transformMeta(int meta, int coordBaseMode) { - return INBTTransformable.transformMetaDeco(meta, coordBaseMode); + return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode); } } \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/generic/DecoPoleSatelliteReceiver.java b/src/main/java/com/hbm/blocks/generic/DecoPoleSatelliteReceiver.java index 109cabbc5..a55592ae9 100644 --- a/src/main/java/com/hbm/blocks/generic/DecoPoleSatelliteReceiver.java +++ b/src/main/java/com/hbm/blocks/generic/DecoPoleSatelliteReceiver.java @@ -1,7 +1,7 @@ package com.hbm.blocks.generic; import com.hbm.tileentity.deco.TileEntityDecoPoleSatelliteReceiver; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; @@ -11,7 +11,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; import net.minecraft.world.World; -public class DecoPoleSatelliteReceiver extends BlockContainer implements INBTTransformable { +public class DecoPoleSatelliteReceiver extends BlockContainer implements INBTBlockTransformable { public DecoPoleSatelliteReceiver(Material p_i45386_1_) { super(p_i45386_1_); @@ -61,7 +61,7 @@ public class DecoPoleSatelliteReceiver extends BlockContainer implements INBTTra @Override public int transformMeta(int meta, int coordBaseMode) { - return INBTTransformable.transformMetaDeco(meta, coordBaseMode); + return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode); } } \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/generic/DecoTapeRecorder.java b/src/main/java/com/hbm/blocks/generic/DecoTapeRecorder.java index e7143aae6..ca8e32474 100644 --- a/src/main/java/com/hbm/blocks/generic/DecoTapeRecorder.java +++ b/src/main/java/com/hbm/blocks/generic/DecoTapeRecorder.java @@ -1,6 +1,6 @@ package com.hbm.blocks.generic; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.client.registry.RenderingRegistry; import net.minecraft.block.BlockContainer; @@ -11,7 +11,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; import net.minecraft.world.World; -public class DecoTapeRecorder extends BlockContainer implements INBTTransformable { +public class DecoTapeRecorder extends BlockContainer implements INBTBlockTransformable { public DecoTapeRecorder(Material p_i45386_1_) { super(p_i45386_1_); @@ -63,7 +63,7 @@ public class DecoTapeRecorder extends BlockContainer implements INBTTransformabl @Override public int transformMeta(int meta, int coordBaseMode) { - return INBTTransformable.transformMetaDeco(meta, coordBaseMode); + return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode); } } \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/machine/BlockMachineBase.java b/src/main/java/com/hbm/blocks/machine/BlockMachineBase.java index b5d111c13..41e0c6a03 100644 --- a/src/main/java/com/hbm/blocks/machine/BlockMachineBase.java +++ b/src/main/java/com/hbm/blocks/machine/BlockMachineBase.java @@ -1,7 +1,7 @@ package com.hbm.blocks.machine; import com.hbm.main.MainRegistry; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.common.network.internal.FMLNetworkHandler; import net.minecraft.block.Block; @@ -17,7 +17,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; import net.minecraft.world.World; -public abstract class BlockMachineBase extends BlockContainer implements INBTTransformable { +public abstract class BlockMachineBase extends BlockContainer implements INBTBlockTransformable { int guiID = -1; protected boolean rotatable = false; @@ -115,6 +115,6 @@ public abstract class BlockMachineBase extends BlockContainer implements INBTTra @Override public int transformMeta(int meta, int coordBaseMode) { if(!rotatable) return meta; - return INBTTransformable.transformMetaDeco(meta, coordBaseMode); + return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode); } } \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/machine/Floodlight.java b/src/main/java/com/hbm/blocks/machine/Floodlight.java index 25e70cac2..4dcdf6fa0 100644 --- a/src/main/java/com/hbm/blocks/machine/Floodlight.java +++ b/src/main/java/com/hbm/blocks/machine/Floodlight.java @@ -4,10 +4,10 @@ import com.hbm.blocks.ModBlocks; import com.hbm.blocks.machine.FloodlightBeam.TileEntityFloodlightBeam; import com.hbm.util.Compat; import com.hbm.util.fauxpointtwelve.BlockPos; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import api.hbm.block.IToolable; import api.hbm.energymk2.IEnergyReceiverMK2; -import com.hbm.world.gen.INBTTransformable; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.block.Block; @@ -28,7 +28,7 @@ import net.minecraft.util.Vec3; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; -public class Floodlight extends BlockContainer implements IToolable, INBTTransformable { +public class Floodlight extends BlockContainer implements IToolable, INBTBlockTransformable { public Floodlight(Material mat) { super(mat); diff --git a/src/main/java/com/hbm/blocks/machine/Spotlight.java b/src/main/java/com/hbm/blocks/machine/Spotlight.java index 4868d3dd0..a72f81db2 100644 --- a/src/main/java/com/hbm/blocks/machine/Spotlight.java +++ b/src/main/java/com/hbm/blocks/machine/Spotlight.java @@ -7,7 +7,7 @@ import java.util.Random; import com.hbm.blocks.BlockEnums.LightType; import com.hbm.blocks.ISpotlight; import com.hbm.main.ResourceManager; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.relauncher.Side; @@ -26,7 +26,7 @@ import net.minecraft.world.World; import net.minecraftforge.client.model.obj.WavefrontObject; import net.minecraftforge.common.util.ForgeDirection; -public class Spotlight extends Block implements ISpotlight, INBTTransformable { +public class Spotlight extends Block implements ISpotlight, INBTBlockTransformable { public static boolean disableOnGeneration = true; @@ -367,7 +367,7 @@ public class Spotlight extends Block implements ISpotlight, INBTTransformable { public int transformMeta(int meta, int coordBaseMode) { // +1 to set as broken, won't turn on until broken and replaced int disabled = disableOnGeneration ? 1 : 0; - return (INBTTransformable.transformMetaDeco(meta >> 1, coordBaseMode) << 1) + disabled; + return (INBTBlockTransformable.transformMetaDeco(meta >> 1, coordBaseMode) << 1) + disabled; } @Override diff --git a/src/main/java/com/hbm/blocks/network/FluidPump.java b/src/main/java/com/hbm/blocks/network/FluidPump.java index a3fcd1baa..9ce059fb4 100644 --- a/src/main/java/com/hbm/blocks/network/FluidPump.java +++ b/src/main/java/com/hbm/blocks/network/FluidPump.java @@ -25,7 +25,7 @@ import com.hbm.tileentity.TileEntityLoadedBase; import com.hbm.util.BobMathUtil; import com.hbm.util.EnumUtil; import com.hbm.util.i18n.I18nUtil; -import com.hbm.world.gen.INBTTransformable; +import com.hbm.world.gen.nbt.INBTBlockTransformable; import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority; import api.hbm.fluidmk2.IFluidStandardTransceiverMK2; @@ -55,7 +55,7 @@ import net.minecraft.world.World; import net.minecraftforge.client.event.RenderGameOverlayEvent.Pre; import net.minecraftforge.common.util.ForgeDirection; -public class FluidPump extends BlockContainer implements INBTTransformable, ILookOverlay, IGUIProvider { +public class FluidPump extends BlockContainer implements INBTBlockTransformable, ILookOverlay, IGUIProvider { public FluidPump(Material mat) { super(mat); @@ -127,7 +127,7 @@ public class FluidPump extends BlockContainer implements INBTTransformable, ILoo @Override public int transformMeta(int meta, int coordBaseMode) { - return INBTTransformable.transformMetaDeco(meta, coordBaseMode); + return INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode); } @Optional.InterfaceList({@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "OpenComputers")}) diff --git a/src/main/java/com/hbm/commands/CommandLocate.java b/src/main/java/com/hbm/commands/CommandLocate.java new file mode 100644 index 000000000..b0a7f8948 --- /dev/null +++ b/src/main/java/com/hbm/commands/CommandLocate.java @@ -0,0 +1,118 @@ +package com.hbm.commands; + +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +import com.hbm.lib.HbmWorld; +import com.hbm.world.gen.nbt.NBTStructure; +import com.hbm.world.gen.nbt.SpawnCondition; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.PlayerNotFoundException; +import net.minecraft.command.WrongUsageException; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MathHelper; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; + +public class CommandLocate extends CommandBase { + + private static final int MAX_DISTANCE = 256; + + @Override + public String getCommandName() { + return "ntmlocate"; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return String.format(Locale.US, + "%s/%s structure %s- Locates the nearest structure with a given name.", + EnumChatFormatting.GREEN, getCommandName(), EnumChatFormatting.LIGHT_PURPLE + ); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + if(!(sender instanceof EntityPlayer)) + throw new PlayerNotFoundException(); + + if(args.length == 0) + throw new WrongUsageException(getCommandUsage(sender), new Object[0]); + + if(args[0].equals("structure")) { + EntityPlayer player = (EntityPlayer) sender; + + SpawnCondition structure = NBTStructure.getStructure(args[1]); + + if(structure == null) { + ChatComponentTranslation message = new ChatComponentTranslation("commands.locate.no_match"); + message.getChatStyle().setColor(EnumChatFormatting.RED); + sender.addChatMessage(message); + return; + } + + int chunkX = MathHelper.floor_double(player.posX) / 16; + int chunkZ = MathHelper.floor_double(player.posZ) / 16; + + ChunkCoordIntPair pos = getNearestLocationTo(structure, player.worldObj, chunkX, chunkZ); + + if(pos == null) { + ChatComponentTranslation message = new ChatComponentTranslation("commands.locate.none_found"); + message.getChatStyle().setColor(EnumChatFormatting.RED); + sender.addChatMessage(message); + return; + } + + ChatComponentTranslation message = new ChatComponentTranslation("commands.locate.success.coordinates", structure.name, pos.chunkXPos * 16, pos.chunkZPos * 16); + message.getChatStyle().setColor(EnumChatFormatting.GREEN); + sender.addChatMessage(message); + } else { + throw new WrongUsageException(getCommandUsage(sender), new Object[0]); + } + } + + private ChunkCoordIntPair getNearestLocationTo(SpawnCondition spawn, World world, int chunkX, int chunkZ) { + if(HbmWorld.worldGenerator.getStructureAt(world, chunkX, chunkZ) == spawn) + return new ChunkCoordIntPair(chunkX, chunkZ); + + for(int radius = 1; radius < MAX_DISTANCE; radius++) { + for(int x = chunkX - radius; x <= chunkX + radius; x++) { + if(HbmWorld.worldGenerator.getStructureAt(world, x, chunkZ - radius) == spawn) + return new ChunkCoordIntPair(x, chunkZ - radius); + if(HbmWorld.worldGenerator.getStructureAt(world, x, chunkZ + radius) == spawn) + return new ChunkCoordIntPair(x, chunkZ + radius); + } + for(int z = chunkZ - radius; z <= chunkZ + radius; z++) { + if(HbmWorld.worldGenerator.getStructureAt(world, chunkX - radius, z) == spawn) + return new ChunkCoordIntPair(chunkX - radius, z); + if(HbmWorld.worldGenerator.getStructureAt(world, chunkX + radius, z) == spawn) + return new ChunkCoordIntPair(chunkX + radius, z); + } + } + + return null; + } + + @SuppressWarnings("unchecked") + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args) { + if(args.length < 1) + return Collections.emptyList(); + + if(args.length == 1) + return getListOfStringsMatchingLastWord(args, "structure"); + + if(args.length == 2) { + List structures = NBTStructure.listStructures(); + return getListOfStringsMatchingLastWord(args, structures.toArray(new String[structures.size()])); + } + + return Collections.emptyList(); + } + +} diff --git a/src/main/java/com/hbm/items/tool/ItemWandS.java b/src/main/java/com/hbm/items/tool/ItemWandS.java index 2de5998fb..55de41e9a 100644 --- a/src/main/java/com/hbm/items/tool/ItemWandS.java +++ b/src/main/java/com/hbm/items/tool/ItemWandS.java @@ -10,7 +10,7 @@ import java.text.SimpleDateFormat; import com.hbm.blocks.ModBlocks; import com.hbm.util.BobMathUtil; import com.hbm.util.Tuple.Pair; -import com.hbm.world.gen.NBTStructure; +import com.hbm.world.gen.nbt.NBTStructure; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/com/hbm/lib/HbmWorld.java b/src/main/java/com/hbm/lib/HbmWorld.java index ed4ca9208..5242feb9b 100644 --- a/src/main/java/com/hbm/lib/HbmWorld.java +++ b/src/main/java/com/hbm/lib/HbmWorld.java @@ -1,10 +1,11 @@ package com.hbm.lib; import com.hbm.world.gen.MapGenNTMFeatures; -import com.hbm.world.gen.NBTStructure; import com.hbm.world.gen.NTMWorldGenerator; import com.hbm.world.gen.component.*; import com.hbm.world.gen.component.BunkerComponents.BunkerStart; +import com.hbm.world.gen.nbt.NBTStructure; + import cpw.mods.fml.common.IWorldGenerator; import cpw.mods.fml.common.registry.GameRegistry; import net.minecraft.world.gen.structure.MapGenStructureIO; diff --git a/src/main/java/com/hbm/main/MainRegistry.java b/src/main/java/com/hbm/main/MainRegistry.java index f797b0de3..d6aebacd8 100644 --- a/src/main/java/com/hbm/main/MainRegistry.java +++ b/src/main/java/com/hbm/main/MainRegistry.java @@ -967,6 +967,7 @@ public class MainRegistry { event.registerServerCommand(new CommandRadiation()); event.registerServerCommand(new CommandPacketInfo()); event.registerServerCommand(new CommandReloadServer()); + event.registerServerCommand(new CommandLocate()); } @EventHandler diff --git a/src/main/java/com/hbm/main/StructureManager.java b/src/main/java/com/hbm/main/StructureManager.java index 5c3f93090..077a3665f 100644 --- a/src/main/java/com/hbm/main/StructureManager.java +++ b/src/main/java/com/hbm/main/StructureManager.java @@ -1,7 +1,7 @@ package com.hbm.main; import com.hbm.lib.RefStrings; -import com.hbm.world.gen.NBTStructure; +import com.hbm.world.gen.nbt.NBTStructure; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/com/hbm/world/gen/NTMWorldGenerator.java b/src/main/java/com/hbm/world/gen/NTMWorldGenerator.java index bb1c7b3d3..049428707 100644 --- a/src/main/java/com/hbm/world/gen/NTMWorldGenerator.java +++ b/src/main/java/com/hbm/world/gen/NTMWorldGenerator.java @@ -9,14 +9,15 @@ import java.util.Random; import com.hbm.blocks.ModBlocks; import com.hbm.config.StructureConfig; import com.hbm.main.StructureManager; -import com.hbm.world.gen.NBTStructure.JigsawPiece; -import com.hbm.world.gen.NBTStructure.JigsawPool; -import com.hbm.world.gen.NBTStructure.SpawnCondition; import com.hbm.world.gen.component.BunkerComponents.BunkerStart; import com.hbm.world.gen.component.Component.CrabSpawners; import com.hbm.world.gen.component.Component.GreenOoze; import com.hbm.world.gen.component.Component.MeteorBricks; import com.hbm.world.gen.component.Component.SupplyCrates; +import com.hbm.world.gen.nbt.JigsawPiece; +import com.hbm.world.gen.nbt.JigsawPool; +import com.hbm.world.gen.nbt.NBTStructure; +import com.hbm.world.gen.nbt.SpawnCondition; import cpw.mods.fml.common.IWorldGenerator; import cpw.mods.fml.common.eventhandler.SubscribeEvent; @@ -41,44 +42,44 @@ public class NTMWorldGenerator implements IWorldGenerator { final List lighthouseBiomes = Arrays.asList(new BiomeGenBase[] { BiomeGenBase.ocean, BiomeGenBase.deepOcean, BiomeGenBase.beach, BiomeGenBase.stoneBeach, BiomeGenBase.coldBeach }); /// SPIRE /// - NBTStructure.registerStructure(0, new SpawnCondition() {{ + NBTStructure.registerStructure(0, new SpawnCondition("spire") {{ canSpawn = biome -> biome.heightVariation <= 0.05F && !invalidBiomes.contains(biome); structure = new JigsawPiece("spire", StructureManager.spire, -1); spawnWeight = 2; }}); - - NBTStructure.registerStructure(0, new SpawnCondition() {{ + + NBTStructure.registerStructure(0, new SpawnCondition("features") {{ canSpawn = biome -> !invalidBiomes.contains(biome); start = d -> new MapGenNTMFeatures.Start(d.getW(), d.getX(), d.getY(), d.getZ()); spawnWeight = 14 * 4; }}); - NBTStructure.registerStructure(0, new SpawnCondition() {{ + NBTStructure.registerStructure(0, new SpawnCondition("bunker") {{ canSpawn = biome -> !invalidBiomes.contains(biome); start = d -> new BunkerStart(d.getW(), d.getX(), d.getY(), d.getZ()); spawnWeight = 1 * 4; }}); - NBTStructure.registerStructure(0, new SpawnCondition() {{ + NBTStructure.registerStructure(0, new SpawnCondition("vertibird") {{ canSpawn = biome -> !biome.canSpawnLightningBolt() && biome.temperature >= 2F; structure = new JigsawPiece("vertibird", StructureManager.vertibird, -3); spawnWeight = 3 * 4; }}); - NBTStructure.registerStructure(0, new SpawnCondition() {{ + NBTStructure.registerStructure(0, new SpawnCondition("crashed_vertibird") {{ canSpawn = biome -> !biome.canSpawnLightningBolt() && biome.temperature >= 2F; structure = new JigsawPiece("crashed_vertibird", StructureManager.crashed_vertibird, -10); spawnWeight = 3 * 4; }}); - NBTStructure.registerStructure(0, new SpawnCondition() {{ + NBTStructure.registerStructure(0, new SpawnCondition("aircraft_carrier") {{ canSpawn = oceanBiomes::contains; structure = new JigsawPiece("aircraft_carrier", StructureManager.aircraft_carrier, -6); maxHeight = 42; spawnWeight = 1; }}); - NBTStructure.registerStructure(0, new SpawnCondition() {{ + NBTStructure.registerStructure(0, new SpawnCondition("oil_rig") {{ canSpawn = biome -> biome == BiomeGenBase.deepOcean; structure = new JigsawPiece("oil_rig", StructureManager.oil_rig, -20); maxHeight = 12; @@ -86,7 +87,7 @@ public class NTMWorldGenerator implements IWorldGenerator { spawnWeight = 2; }}); - NBTStructure.registerStructure(0, new SpawnCondition() {{ + NBTStructure.registerStructure(0, new SpawnCondition("lighthouse") {{ canSpawn = lighthouseBiomes::contains; structure = new JigsawPiece("lighthouse", StructureManager.lighthouse, -40); maxHeight = 29; @@ -94,7 +95,7 @@ public class NTMWorldGenerator implements IWorldGenerator { spawnWeight = 2; }}); - NBTStructure.registerStructure(0, new SpawnCondition() {{ + NBTStructure.registerStructure(0, new SpawnCondition("beached_patrol") {{ canSpawn = beachBiomes::contains; structure = new JigsawPiece("beached_patrol", StructureManager.beached_patrol, -5); minHeight = 58; @@ -103,8 +104,8 @@ public class NTMWorldGenerator implements IWorldGenerator { }}); NBTStructure.registerNullWeight(0, 2, oceanBiomes::contains); //why the fuck did this change - - NBTStructure.registerStructure(0, new SpawnCondition() {{ + + NBTStructure.registerStructure(0, new SpawnCondition("dish") {{ canSpawn = biome -> biome == BiomeGenBase.plains; structure = new JigsawPiece("dish", StructureManager.dish, -10); minHeight = 53; @@ -128,13 +129,13 @@ public class NTMWorldGenerator implements IWorldGenerator { put(ModBlocks.concrete_colored, new GreenOoze()); }}; - NBTStructure.registerStructure(0, new SpawnCondition() {{ + NBTStructure.registerStructure(0, new SpawnCondition("meteor_dungeon") {{ minHeight = 32; maxHeight = 32; sizeLimit = 128; canSpawn = biome -> biome.rootHeight >= 0; startPool = "start"; - pools = new HashMap() {{ + pools = new HashMap() {{ put("start", new JigsawPool() {{ add(new JigsawPiece("meteor_core", StructureManager.meteor_core) {{ blockTable = bricks; }}, 1); }}); @@ -255,4 +256,13 @@ public class NTMWorldGenerator implements IWorldGenerator { nbtGen.generateStructures(world, rand, chunkProvider, chunkX, chunkZ); } + public SpawnCondition getStructureAt(World world, int chunkX, int chunkZ) { + if(StructureConfig.enableStructures == 0) return null; + if(StructureConfig.enableStructures == 2 && !world.getWorldInfo().isMapFeaturesEnabled()) return null; + + setRandomSeed(world, chunkX, chunkZ); + + return nbtGen.getStructureAt(world, chunkX, chunkZ); + } + } diff --git a/src/main/java/com/hbm/world/gen/INBTTransformable.java b/src/main/java/com/hbm/world/gen/nbt/INBTBlockTransformable.java similarity index 89% rename from src/main/java/com/hbm/world/gen/INBTTransformable.java rename to src/main/java/com/hbm/world/gen/nbt/INBTBlockTransformable.java index 1d2cb8746..0247478e6 100644 --- a/src/main/java/com/hbm/world/gen/INBTTransformable.java +++ b/src/main/java/com/hbm/world/gen/nbt/INBTBlockTransformable.java @@ -1,8 +1,8 @@ -package com.hbm.world.gen; +package com.hbm.world.gen.nbt; import net.minecraft.block.Block; -public interface INBTTransformable { +public interface INBTBlockTransformable { /** * Defines this block as something that has a rotation or some other blockstate @@ -80,6 +80,30 @@ public interface INBTTransformable { return meta; } + // what in the FUCK mojangles + // same as stairs but 1 & 3 flipped + public static int transformMetaTrapdoor(int meta, int coordBaseMode) { + if(coordBaseMode == 0) return meta; + switch(coordBaseMode) { + case 1: //West + if((meta & 3) < 2) + meta = meta ^ 3; + else + meta = meta ^ 2; + break; + case 2: //North + meta = meta ^ 1; //Flip first bit + break; + case 3: //East + if((meta & 3) < 2) + meta = meta ^ 2; + else + meta = meta ^ 3; + break; + } + return meta; + } + public static int transformMetaPillar(int meta, int coordBaseMode) { if(coordBaseMode == 0 || coordBaseMode == 2) return meta; int type = meta & 3; diff --git a/src/main/java/com/hbm/world/gen/INBTTileEntityTransformable.java b/src/main/java/com/hbm/world/gen/nbt/INBTTileEntityTransformable.java similarity index 90% rename from src/main/java/com/hbm/world/gen/INBTTileEntityTransformable.java rename to src/main/java/com/hbm/world/gen/nbt/INBTTileEntityTransformable.java index 33dc141c8..88a05ba2e 100644 --- a/src/main/java/com/hbm/world/gen/INBTTileEntityTransformable.java +++ b/src/main/java/com/hbm/world/gen/nbt/INBTTileEntityTransformable.java @@ -1,4 +1,4 @@ -package com.hbm.world.gen; +package com.hbm.world.gen.nbt; import net.minecraft.world.World; diff --git a/src/main/java/com/hbm/world/gen/nbt/JigsawPiece.java b/src/main/java/com/hbm/world/gen/nbt/JigsawPiece.java new file mode 100644 index 000000000..d58a5dcfa --- /dev/null +++ b/src/main/java/com/hbm/world/gen/nbt/JigsawPiece.java @@ -0,0 +1,35 @@ +package com.hbm.world.gen.nbt; + +import java.util.Map; + +import net.minecraft.block.Block; +import net.minecraft.world.gen.structure.StructureComponent.BlockSelector; + +// Assigned to a Component to build +public class JigsawPiece { + + public final String name; + public final NBTStructure structure; + + // Block modifiers, for randomization and terrain matching + public Map blockTable; + public boolean conformToTerrain = false; // moves every single column to the terrain (digging out trenches, natural formations) + public boolean alignToTerrain = false; // aligns this component y-level individually, without moving individual columns (village houses) + public int heightOffset = 0; // individual offset for the structure + + public JigsawPiece(String name, NBTStructure structure) { + this(name, structure, 0); + } + + public JigsawPiece(String name, NBTStructure structure, int heightOffset) { + if(name == null) throw new IllegalStateException("A severe error has occurred in NBTStructure! A jigsaw piece has been registered without a valid name!"); + if(NBTStructure.jigsawMap.containsKey(name)) throw new IllegalStateException("A severe error has occurred in NBTStructure! A jigsaw piece has been registered with the same name as another: " + name); + + this.name = name; + this.structure = structure; + NBTStructure.jigsawMap.put(name, this); + + this.heightOffset = heightOffset; + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/world/gen/nbt/JigsawPool.java b/src/main/java/com/hbm/world/gen/nbt/JigsawPool.java new file mode 100644 index 000000000..aaf0e70d2 --- /dev/null +++ b/src/main/java/com/hbm/world/gen/nbt/JigsawPool.java @@ -0,0 +1,58 @@ +package com.hbm.world.gen.nbt; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import com.hbm.util.Tuple.Pair; + +// A set of pieces with weights +public class JigsawPool { + + // Weighted list of pieces to pick from + List> pieces = new ArrayList<>(); + int totalWeight = 0; + + public String fallback; + + private boolean isClone; + + public void add(JigsawPiece piece, int weight) { + if(weight <= 0) throw new IllegalStateException("JigsawPool spawn weight must be positive!"); + pieces.add(new Pair<>(piece, weight)); + totalWeight += weight; + } + + protected JigsawPool clone() { + JigsawPool clone = new JigsawPool(); + clone.pieces = new ArrayList<>(this.pieces); + clone.fallback = this.fallback; + clone.totalWeight = this.totalWeight; + clone.isClone = true; + + return clone; + } + + // If from a clone, will remove from the pool + public JigsawPiece get(Random rand) { + if(totalWeight <= 0) return null; + int weight = rand.nextInt(totalWeight); + + for(int i = 0; i < pieces.size(); i++) { + Pair pair = pieces.get(i); + weight -= pair.getValue(); + + if(weight < 0) { + if(isClone) { + pieces.remove(i); + totalWeight -= pair.getValue(); + } + + return pair.getKey(); + } + } + + return null; + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/world/gen/NBTStructure.java b/src/main/java/com/hbm/world/gen/nbt/NBTStructure.java similarity index 84% rename from src/main/java/com/hbm/world/gen/NBTStructure.java rename to src/main/java/com/hbm/world/gen/nbt/NBTStructure.java index 60da4735a..ed1632ee1 100644 --- a/src/main/java/com/hbm/world/gen/NBTStructure.java +++ b/src/main/java/com/hbm/world/gen/nbt/NBTStructure.java @@ -1,11 +1,10 @@ -package com.hbm.world.gen; +package com.hbm.world.gen.nbt; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.*; -import java.util.function.Function; import java.util.function.Predicate; import com.hbm.blocks.ModBlocks; @@ -17,6 +16,7 @@ import com.hbm.main.MainRegistry; import com.hbm.util.Tuple.Pair; import com.hbm.util.Tuple.Quartet; import com.hbm.util.fauxpointtwelve.BlockPos; +import com.hbm.world.gen.nbt.SpawnCondition.WorldCoordinate; import cpw.mods.fml.common.registry.GameRegistry; import net.minecraft.block.*; @@ -31,6 +31,7 @@ import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; +import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.chunk.IChunkProvider; @@ -53,7 +54,10 @@ public class NBTStructure { * without having to define and register each structure manually */ + private static Map namedMap = new HashMap<>(); + protected static Map> weightedMap = new HashMap<>(); + protected static Map> customSpawnMap = new HashMap<>(); // serialization data protected static Map jigsawMap = new HashMap<>(); @@ -62,7 +66,7 @@ public class NBTStructure { private boolean isLoaded; - private ThreeInts size; + protected ThreeInts size; private List> itemPalette; private BlockState[][][] blockArray; @@ -89,6 +93,17 @@ public class NBTStructure { // Register a new structure for a given dimension public static void registerStructure(int dimensionId, SpawnCondition spawn) { + if(namedMap.containsKey(spawn.name) && namedMap.get(spawn.name) != spawn) + throw new IllegalStateException("A severe error has occurred in NBTStructure! A SpawnCondition has been registered with the same name as another: " + spawn.name); + + namedMap.put(spawn.name, spawn); + + if(spawn.checkCoordinates != null) { + List spawnList = customSpawnMap.computeIfAbsent(dimensionId, integer -> new ArrayList()); + spawnList.add(spawn); + return; + } + List weightedList = weightedMap.computeIfAbsent(dimensionId, integer -> new ArrayList()); for(int i = 0; i < spawn.spawnWeight; i++) { weightedList.add(spawn); @@ -107,10 +122,7 @@ public class NBTStructure { } public static void registerNullWeight(int dimensionId, int weight, Predicate predicate) { - SpawnCondition spawn = new SpawnCondition() {{ - spawnWeight = weight; - canSpawn = predicate; - }}; + SpawnCondition spawn = new SpawnCondition(weight, predicate); List weightedList = weightedMap.computeIfAbsent(dimensionId, integer -> new ArrayList()); for(int i = 0; i < spawn.spawnWeight; i++) { @@ -118,6 +130,19 @@ public class NBTStructure { } } + // Presents a list of all structures registered (so far) + public static List listStructures() { + List names = new ArrayList<>(namedMap.keySet()); + names.sort((a, b) -> a.compareTo(b)); + return names; + } + + // Fetches a registered structure by name, + // If one is not found, will simply return null. + public static SpawnCondition getStructure(String name) { + return namedMap.get(name); + } + // Saves a selected area into an NBT structure (+ some of our non-standard stuff to support 1.7.10) public static void saveArea(String filename, World world, int x1, int y1, int z1, int x2, int y2, int z2, Set> exclude) { NBTTagCompound structure = new NBTTagCompound(); @@ -552,7 +577,7 @@ public class NBTStructure { return selector.func_151561_a(); } - if(definition.block instanceof INBTTransformable) return ((INBTTransformable) definition.block).transformBlock(definition.block); + if(definition.block instanceof INBTBlockTransformable) return ((INBTBlockTransformable) definition.block).transformBlock(definition.block); return definition.block; } @@ -563,22 +588,23 @@ public class NBTStructure { } // Our shit - if(definition.block instanceof INBTTransformable) return ((INBTTransformable) definition.block).transformMeta(definition.meta, coordBaseMode); + if(definition.block instanceof INBTBlockTransformable) return ((INBTBlockTransformable) definition.block).transformMeta(definition.meta, coordBaseMode); if(coordBaseMode == 0) return definition.meta; // Vanilla shit - if(definition.block instanceof BlockStairs) return INBTTransformable.transformMetaStairs(definition.meta, coordBaseMode); - if(definition.block instanceof BlockRotatedPillar) return INBTTransformable.transformMetaPillar(definition.meta, coordBaseMode); - if(definition.block instanceof BlockDirectional) return INBTTransformable.transformMetaDirectional(definition.meta, coordBaseMode); - if(definition.block instanceof BlockTorch) return INBTTransformable.transformMetaTorch(definition.meta, coordBaseMode); - if(definition.block instanceof BlockButton) return INBTTransformable.transformMetaTorch(definition.meta, coordBaseMode); - if(definition.block instanceof BlockDoor) return INBTTransformable.transformMetaDoor(definition.meta, coordBaseMode); - if(definition.block instanceof BlockLever) return INBTTransformable.transformMetaLever(definition.meta, coordBaseMode); - if(definition.block instanceof BlockSign) return INBTTransformable.transformMetaDeco(definition.meta, coordBaseMode); - if(definition.block instanceof BlockLadder) return INBTTransformable.transformMetaDeco(definition.meta, coordBaseMode); - if(definition.block instanceof BlockTripWireHook) return INBTTransformable.transformMetaDirectional(definition.meta, coordBaseMode); - if(definition.block == Blocks.vine) return INBTTransformable.transformMetaVine(definition.meta, coordBaseMode); + if(definition.block instanceof BlockStairs) return INBTBlockTransformable.transformMetaStairs(definition.meta, coordBaseMode); + if(definition.block instanceof BlockRotatedPillar) return INBTBlockTransformable.transformMetaPillar(definition.meta, coordBaseMode); + if(definition.block instanceof BlockDirectional) return INBTBlockTransformable.transformMetaDirectional(definition.meta, coordBaseMode); + if(definition.block instanceof BlockTorch) return INBTBlockTransformable.transformMetaTorch(definition.meta, coordBaseMode); + if(definition.block instanceof BlockButton) return INBTBlockTransformable.transformMetaTorch(definition.meta, coordBaseMode); + if(definition.block instanceof BlockDoor) return INBTBlockTransformable.transformMetaDoor(definition.meta, coordBaseMode); + if(definition.block instanceof BlockLever) return INBTBlockTransformable.transformMetaLever(definition.meta, coordBaseMode); + if(definition.block instanceof BlockSign) return INBTBlockTransformable.transformMetaDeco(definition.meta, coordBaseMode); + if(definition.block instanceof BlockLadder) return INBTBlockTransformable.transformMetaDeco(definition.meta, coordBaseMode); + if(definition.block instanceof BlockTripWireHook) return INBTBlockTransformable.transformMetaDirectional(definition.meta, coordBaseMode); + if(definition.block instanceof BlockVine) return INBTBlockTransformable.transformMetaVine(definition.meta, coordBaseMode); + if(definition.block instanceof BlockTrapDoor) return INBTBlockTransformable.transformMetaTrapdoor(definition.meta, coordBaseMode); return definition.meta; } @@ -649,152 +675,6 @@ public class NBTStructure { } - public static class SpawnCondition { - - // If defined, will spawn a single jigsaw piece, for single nbt structures - public JigsawPiece structure; - - // If defined, will spawn in a non-nbt structure component - public Function, StructureStart> start; - - public Predicate canSpawn; - public int spawnWeight = 1; - - // Named jigsaw pools that are referenced within the structure - public Map pools; - public String startPool; - - // Maximum amount of components in this structure - public int sizeLimit = 8; - - // How far the structure can extend horizontally from the center, maximum of 128 - // This could be increased by changing GenStructure:range from 8, but this is already quite reasonably large - public int rangeLimit = 128; - - // Height modifiers, will clamp height that the start generates at, allowing for: - // * Submarines that must spawn under the ocean surface - // * Bunkers that sit underneath the ground - public int minHeight = 1; - public int maxHeight = 128; - - // Can this spawn in the current biome - protected boolean isValid(BiomeGenBase biome) { - if(canSpawn == null) return true; - return canSpawn.test(biome); - } - - protected JigsawPool getPool(String name) { - return pools.get(name).clone(); - } - - // Builds all of the pools into neat rows and columns, for editing and debugging! - // Make sure structure debug is enabled, or it will no-op - // Do not use in generation - public void buildAll(World world, int x, int y, int z) { - if(!StructureConfig.debugStructures) return; - - int padding = 5; - int oz = 0; - - for(JigsawPool pool : pools.values()) { - int highestWidth = 0; - int ox = 0; - - for(Pair entry : pool.pieces) { - NBTStructure structure = entry.key.structure; - structure.build(world, x + ox + (structure.size.x / 2), y, z + oz + (structure.size.z / 2)); - - ox += structure.size.x + padding; - highestWidth = Math.max(highestWidth, structure.size.z); - } - - oz += highestWidth + padding; - } - } - - } - - // A set of pieces with weights - public static class JigsawPool { - - // Weighted list of pieces to pick from - private List> pieces = new ArrayList<>(); - private int totalWeight = 0; - - public String fallback; - - private boolean isClone; - - public void add(JigsawPiece piece, int weight) { - if(weight <= 0) throw new IllegalStateException("JigsawPool spawn weight must be positive!"); - pieces.add(new Pair<>(piece, weight)); - totalWeight += weight; - } - - protected JigsawPool clone() { - JigsawPool clone = new JigsawPool(); - clone.pieces = new ArrayList<>(this.pieces); - clone.fallback = this.fallback; - clone.totalWeight = this.totalWeight; - clone.isClone = true; - - return clone; - } - - // If from a clone, will remove from the pool - public JigsawPiece get(Random rand) { - if(totalWeight <= 0) return null; - int weight = rand.nextInt(totalWeight); - - for(int i = 0; i < pieces.size(); i++) { - Pair pair = pieces.get(i); - weight -= pair.getValue(); - - if(weight < 0) { - if(isClone) { - pieces.remove(i); - totalWeight -= pair.getValue(); - } - - return pair.getKey(); - } - } - - return null; - } - - } - - // Assigned to a Component to build - public static class JigsawPiece { - - public final String name; - public final NBTStructure structure; - - // Block modifiers, for randomization and terrain matching - public Map blockTable; - public boolean conformToTerrain = false; // moves every single column to the terrain (digging out trenches, natural formations) - public boolean alignToTerrain = false; // aligns this component y-level individually, without moving individual columns (village houses) - public int heightOffset = 0; // individual offset for the structure - - public JigsawPiece(String name, NBTStructure structure) { - this(name, structure, 0); - } - - public JigsawPiece(String name, NBTStructure structure, int heightOffset) { - if(name == null) throw new IllegalStateException("A severe error has occurred in NBTStructure! A jigsaw piece has been registered without a valid name!"); - if(jigsawMap.containsKey(name)) throw new IllegalStateException("A severe error has occurred in NBTStructure! A jigsaw piece has been registered with the same name as another: " + name); - - this.name = name; - this.structure = structure; - jigsawMap.put(name, this); - - this.heightOffset = heightOffset; - } - - } - - // Each jigsaw block in a structure will instance one of these private static class JigsawConnection { @@ -872,7 +752,7 @@ public class NBTStructure { // Save to NBT @Override protected void func_143012_a(NBTTagCompound nbt) { - nbt.setString("piece", piece.name); + nbt.setString("piece", piece != null ? piece.name : "NULL"); nbt.setInteger("min", minHeight); nbt.setInteger("max", maxHeight); nbt.setBoolean("hasHeight", heightUpdated); @@ -1055,6 +935,10 @@ public class NBTStructure { } JigsawPool nextPool = spawn.getPool(fromConnection.poolName); + if(nextPool == null) { + MainRegistry.logger.warn("[Jigsaw] Jigsaw block points to invalid pool: " + fromConnection.poolName); + continue; + } Component nextComponent = null; @@ -1119,10 +1003,16 @@ public class NBTStructure { private Component buildNextComponent(Random rand, SpawnCondition spawn, JigsawPool pool, Component fromComponent, JigsawConnection fromConnection) { JigsawPiece nextPiece = pool.get(rand); - if(nextPiece == null) return null; + if(nextPiece == null) { + MainRegistry.logger.warn("[Jigsaw] Pool returned null piece: " + fromConnection.poolName); + return null; + } List connectionPool = getConnectionPool(nextPiece, fromConnection); - if(connectionPool == null) return null; + if(connectionPool == null || connectionPool.isEmpty()) { + MainRegistry.logger.warn("[Jigsaw] No valid connections for: " + fromConnection.targetName + " - in piece: " + nextPiece.name); + return null; + } JigsawConnection toConnection = connectionPool.get(rand.nextInt(connectionPool.size())); @@ -1192,7 +1082,42 @@ public class NBTStructure { @Override protected boolean canSpawnStructureAtCoords(int chunkX, int chunkZ) { - if(!weightedMap.containsKey(worldObj.provider.dimensionId)) return false; + nextSpawn = getSpawnAtCoords(chunkX, chunkZ); + return nextSpawn != null; + } + + public SpawnCondition getStructureAt(World world, int chunkX, int chunkZ) { + // make sure the random is in the correct state + this.worldObj = world; + this.rand.setSeed(world.getSeed()); + long l = this.rand.nextLong(); + long i1 = this.rand.nextLong(); + + long l1 = (long)chunkX * l; + long i2 = (long)chunkZ * i1; + this.rand.setSeed(l1 ^ i2 ^ world.getSeed()); + + // random nextInt call just before `canSpawnStructureAtCoords`, no, I don't know why Mojang added that + this.rand.nextInt(); + + return getSpawnAtCoords(chunkX, chunkZ); + } + + private SpawnCondition getSpawnAtCoords(int chunkX, int chunkZ) { + // attempt to spawn with custom chunk coordinate rules + if (customSpawnMap.containsKey(worldObj.provider.dimensionId)) { + WorldCoordinate coords = new WorldCoordinate(worldObj, new ChunkCoordIntPair(chunkX, chunkZ), rand); + + List spawnList = customSpawnMap.get(worldObj.provider.dimensionId); + for (SpawnCondition spawn : spawnList) { + if ((spawn.pools != null || spawn.structure != null) && spawn.checkCoordinates.test(coords)) { + return spawn; + } + } + } + + if (!weightedMap.containsKey(worldObj.provider.dimensionId)) + return null; int x = chunkX; int z = chunkZ; @@ -1208,15 +1133,16 @@ public class NBTStructure { x += rand.nextInt(StructureConfig.structureMaxChunks - StructureConfig.structureMinChunks); z += rand.nextInt(StructureConfig.structureMaxChunks - StructureConfig.structureMinChunks); - if(chunkX == x && chunkZ == z) { + if (chunkX == x && chunkZ == z) { BiomeGenBase biome = this.worldObj.getWorldChunkManager().getBiomeGenAt(chunkX * 16 + 8, chunkZ * 16 + 8); - nextSpawn = findSpawn(biome); + SpawnCondition spawn = findSpawn(biome); - return nextSpawn != null && (nextSpawn.pools != null || nextSpawn.start != null || nextSpawn.structure != null); + if(spawn != null && (spawn.pools != null || spawn.start != null || spawn.structure != null)) + return spawn; } - return false; + return null; } @Override diff --git a/src/main/java/com/hbm/world/gen/nbt/SpawnCondition.java b/src/main/java/com/hbm/world/gen/nbt/SpawnCondition.java new file mode 100644 index 000000000..b623ea864 --- /dev/null +++ b/src/main/java/com/hbm/world/gen/nbt/SpawnCondition.java @@ -0,0 +1,115 @@ +package com.hbm.world.gen.nbt; + +import java.util.Map; +import java.util.Random; +import java.util.function.Function; +import java.util.function.Predicate; + +import com.hbm.config.StructureConfig; +import com.hbm.util.Tuple.Pair; +import com.hbm.util.Tuple.Quartet; + +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.World; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraft.world.gen.structure.StructureStart; + +public class SpawnCondition { + + public final String name; + + // If defined, will spawn a single jigsaw piece, for single nbt structures + public JigsawPiece structure; + + // If defined, will spawn in a non-nbt structure component + public Function, StructureStart> start; + + // If defined, will override regular spawn location checking, for placing at specific coordinates or with special rules + public Predicate checkCoordinates; + + // Our regular spawning mechanics, based on biome, you should generally use these + public Predicate canSpawn; + public int spawnWeight = 1; + + // Named jigsaw pools that are referenced within the structure + public Map pools; + public String startPool; + + // Maximum amount of components in this structure + public int sizeLimit = 8; + + // How far the structure can extend horizontally from the center, maximum of 128 + // This could be increased by changing GenStructure:range from 8, but this is already quite reasonably large + public int rangeLimit = 128; + + // Height modifiers, will clamp height that the start generates at, allowing for: + // * Submarines that must spawn under the ocean surface + // * Bunkers that sit underneath the ground + public int minHeight = 1; + public int maxHeight = 128; + + protected SpawnCondition(int weight, Predicate predicate) { + name = null; + spawnWeight = weight; + canSpawn = predicate; + } + + public SpawnCondition(String name) { + this.name = name; + } + + // Can this spawn in the current biome + protected boolean isValid(BiomeGenBase biome) { + if(canSpawn == null) return true; + return canSpawn.test(biome); + } + + protected JigsawPool getPool(String name) { + JigsawPool pool = pools.get(name); + return pool != null ? pool.clone() : null; + } + + // Builds all of the pools into neat rows and columns, for editing and debugging! + // Make sure structure debug is enabled, or it will no-op + // Do not use in generation + public void buildAll(World world, int x, int y, int z) { + if(!StructureConfig.debugStructures) return; + + int padding = 5; + int oz = 0; + + for(JigsawPool pool : pools.values()) { + int highestWidth = 0; + int ox = 0; + + for(Pair entry : pool.pieces) { + NBTStructure structure = entry.key.structure; + structure.build(world, x + ox + (structure.size.x / 2), y, z + oz + (structure.size.z / 2)); + + ox += structure.size.x + padding; + highestWidth = Math.max(highestWidth, structure.size.z); + } + + oz += highestWidth + padding; + } + } + + /** + * Provides information about the current structure gen chunk, + * use the included random for consistent seeding! + */ + public static class WorldCoordinate { + + public final World world; + public final ChunkCoordIntPair coords; + public final Random rand; + + protected WorldCoordinate(World world, ChunkCoordIntPair coords, Random rand) { + this.world = world; + this.coords = coords; + this.rand = rand; + } + + } + +} \ No newline at end of file diff --git a/src/main/resources/assets/hbm/lang/en_US.lang b/src/main/resources/assets/hbm/lang/en_US.lang index 32d100935..608213a68 100644 --- a/src/main/resources/assets/hbm/lang/en_US.lang +++ b/src/main/resources/assets/hbm/lang/en_US.lang @@ -705,6 +705,10 @@ commands.satellite.satellite_descended=Satellite successfully descended. commands.satellite.satellite_orbited=Satellite launched. commands.satellite.should_be_run_as_player=This command should be run by a player! +commands.locate.no_match=No structures with that name! +commands.locate.none_found=No structures found nearby! +commands.locate.success.coordinates=Structure %s found at %d, %d + container.ammoBag=Ammo Bag container.amsBase=AMS Base (Deco) container.amsEmitter=AMS Emitter (Deco)