diff --git a/src/main/java/com/hbm/blocks/BlockDummyable.java b/src/main/java/com/hbm/blocks/BlockDummyable.java index cfedf6246..75dd39c2f 100644 --- a/src/main/java/com/hbm/blocks/BlockDummyable.java +++ b/src/main/java/com/hbm/blocks/BlockDummyable.java @@ -5,12 +5,15 @@ 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 cpw.mods.fml.common.network.internal.FMLNetworkHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.block.Block; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; @@ -32,7 +35,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -public abstract class BlockDummyable extends BlockContainer implements ICustomBlockHighlight, ICopiable { +public abstract class BlockDummyable extends BlockContainer implements ICustomBlockHighlight, ICopiable, INBTTransformable { public BlockDummyable(Material mat) { super(mat); @@ -116,7 +119,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl return findCoreRec(world, x, y, z); } - List positions = new ArrayList(); + List positions = new ArrayList<>(); public int[] findCoreRec(World world, int x, int y, int z) { @@ -216,11 +219,6 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl super.onBlockPlacedBy(world, x, y, z, player, itemStack); } - /*@Override - public void onBlockAdded(World world, int x, int y, int z) { - lastBlockSet = new BlockPos(x, y, z); - }*/ - /** * A bit more advanced than the dir modifier, but it is important that the resulting direction meta is in the core range. * Using the "extra" metas is technically possible but requires a bit of tinkering, e.g. preventing a recursive loop @@ -267,9 +265,9 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl return; // world.setBlockMetadataWithNotify(x, y, z, meta + extra, 3); - this.safeRem = true; + safeRem = true; world.setBlock(x, y, z, this, meta + extra, 3); - this.safeRem = false; + safeRem = false; } public void removeExtra(World world, int x, int y, int z) { @@ -283,9 +281,9 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl return; // world.setBlockMetadataWithNotify(x, y, z, meta + extra, 3); - this.safeRem = true; + safeRem = true; world.setBlock(x, y, z, this, meta - extra, 3); - this.safeRem = false; + safeRem = false; } // checks if the dummy metadata is within the extra range @@ -423,8 +421,9 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl return !bounding.isEmpty(); } - public List bounding = new ArrayList(); + public List bounding = new ArrayList<>(); + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public void addCollisionBoxesToList(World world, int x, int y, int z, AxisAlignedBB entityBounding, List list, Entity entity) { @@ -443,7 +442,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl z = pos[2]; for(AxisAlignedBB aabb :this.bounding) { - AxisAlignedBB boxlet = getAABBRotationOffset(aabb, x + 0.5, y, z + 0.5, ForgeDirection.getOrientation(world.getBlockMetadata(x, y, z) - this.offset).getRotation(ForgeDirection.UP)); + AxisAlignedBB boxlet = getAABBRotationOffset(aabb, x + 0.5, y, z + 0.5, ForgeDirection.getOrientation(world.getBlockMetadata(x, y, z) - offset).getRotation(ForgeDirection.UP)); if(entityBounding.intersectsWith(boxlet)) { list.add(boxlet); @@ -504,7 +503,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl int meta = world.getBlockMetadata(x, y, z); ICustomBlockHighlight.setup(); - for(AxisAlignedBB aabb : this.bounding) event.context.drawOutlinedBoundingBox(getAABBRotationOffset(aabb.expand(exp, exp, exp), 0, 0, 0, ForgeDirection.getOrientation(meta - offset).getRotation(ForgeDirection.UP)).getOffsetBoundingBox(x - dX + 0.5, y - dY, z - dZ + 0.5), -1); + for(AxisAlignedBB aabb : this.bounding) RenderGlobal.drawOutlinedBoundingBox(getAABBRotationOffset(aabb.expand(exp, exp, exp), 0, 0, 0, ForgeDirection.getOrientation(meta - offset).getRotation(ForgeDirection.UP)).getOffsetBoundingBox(x - dX + 0.5, y - dY, z - dZ + 0.5), -1); ICustomBlockHighlight.cleanup(); } @@ -534,4 +533,27 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl return ((ICopiable) tile).infoForDisplay(world, x, y, z); return null; } -} + + @Override + public int transformMeta(int meta, int coordBaseMode) { + boolean isOffset = meta >= 12; // squishing causes issues + boolean isExtra = !isOffset && meta >= extra; + + if(isOffset) { + meta -= offset; + } else if(isExtra) { + meta -= extra; + } + + meta = INBTTransformable.transformMetaDeco(meta, coordBaseMode); + + if(isOffset) { + meta += offset; + } else if(isExtra) { + meta += extra; + } + + return meta; + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/IBlockSideRotation.java b/src/main/java/com/hbm/blocks/IBlockSideRotation.java index d24282cce..a8769a139 100644 --- a/src/main/java/com/hbm/blocks/IBlockSideRotation.java +++ b/src/main/java/com/hbm/blocks/IBlockSideRotation.java @@ -11,4 +11,27 @@ public interface IBlockSideRotation { public static int getRenderType() { return renderID; } + + // 0 1 3 2 becomes 0 2 3 1 + // I want to smoke that swedish kush because it clearly makes you fucking stupid + public static int topToBottom(int topRotation) { + switch(topRotation) { + case 1: return 2; + case 2: return 1; + default: return topRotation; + } + } + + public static boolean isOpposite(int from, int to) { + switch(from) { + case 0: return to == 1; + case 1: return to == 0; + case 2: return to == 3; + case 3: return to == 2; + case 4: return to == 5; + case 5: return to == 4; + default: return false; + } + } + } diff --git a/src/main/java/com/hbm/blocks/ModBlocks.java b/src/main/java/com/hbm/blocks/ModBlocks.java index c80573666..6cf108b50 100644 --- a/src/main/java/com/hbm/blocks/ModBlocks.java +++ b/src/main/java/com/hbm/blocks/ModBlocks.java @@ -35,6 +35,7 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockFalling; import net.minecraft.block.material.*; import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; @@ -1228,6 +1229,11 @@ public class ModBlocks { public static Block pink_double_slab; public static Block pink_stairs; + // NBT Structure wand blocks + public static Block wand_air; + public static Block wand_loot; + public static Block wand_jigsaw; + public static Material materialGas = new MaterialGas(); private static void initializeBlock() { @@ -1654,7 +1660,7 @@ public class ModBlocks { plant_dead = new BlockDeadPlant().setBlockName("plant_dead").setCreativeTab(MainRegistry.blockTab).setStepSound(Block.soundTypeGrass).setHardness(0.0F); reeds = new BlockReeds().setBlockName("plant_reeds").setCreativeTab(MainRegistry.blockTab).setStepSound(Block.soundTypeGrass).setHardness(0.0F); vine_phosphor = new BlockHangingVine(thick_foliage).setBlockName("vine_phosphor").setCreativeTab(MainRegistry.blockTab).setStepSound(Block.soundTypeGrass).setHardness(0.5F); - + waste_earth = new WasteEarth(Material.ground, true).setBlockName("waste_earth").setStepSound(Block.soundTypeGrass).setCreativeTab(MainRegistry.blockTab).setHardness(0.6F).setBlockTextureName(RefStrings.MODID + ":waste_earth"); waste_mycelium = new WasteEarth(Material.ground, true).setBlockName("waste_mycelium").setStepSound(Block.soundTypeGrass).setLightLevel(1F).setCreativeTab(MainRegistry.blockTab).setHardness(0.6F).setBlockTextureName(RefStrings.MODID + ":waste_mycelium_side"); waste_trinitite = new BlockOre(Material.sand).noFortune().setBlockName("waste_trinitite").setStepSound(Block.soundTypeSand).setCreativeTab(MainRegistry.blockTab).setHardness(0.5F).setResistance(2.5F).setBlockTextureName(RefStrings.MODID + ":waste_trinitite"); @@ -1836,7 +1842,7 @@ public class ModBlocks { pa_quadrupole = new BlockPAQuadrupole().setStepSound(Block.soundTypeMetal).setBlockName("pa_quadrupole").setHardness(5.0F).setResistance(10.0F); pa_dipole = new BlockPADipole().setStepSound(Block.soundTypeMetal).setBlockName("pa_dipole").setHardness(5.0F).setResistance(10.0F); pa_detector = new BlockPADetector().setStepSound(Block.soundTypeMetal).setBlockName("pa_detector").setHardness(5.0F).setResistance(10.0F); - + machine_electric_furnace_off = new MachineElectricFurnace(false).setBlockName("machine_electric_furnace_off").setHardness(5.0F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab); machine_electric_furnace_on = new MachineElectricFurnace(true).setBlockName("machine_electric_furnace_on").setHardness(5.0F).setLightLevel(1.0F).setResistance(10.0F); machine_arc_furnace_off = new MachineArcFurnace(false).setBlockName("machine_arc_furnace_off").setHardness(5.0F).setResistance(10.0F); @@ -2354,6 +2360,10 @@ public class ModBlocks { pink_slab = new BlockPinkSlab(false, Material.wood).setBlockName("pink_slab").setStepSound(Block.soundTypeWood).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":pink_planks"); pink_double_slab = new BlockPinkSlab(true, Material.wood).setBlockName("pink_double_slab").setStepSound(Block.soundTypeWood).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":pink_planks"); pink_stairs = new BlockGenericStairs(pink_planks, 0).setBlockName("pink_stairs").setStepSound(Block.soundTypeWood).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":pink_planks"); + + wand_air = new BlockWand(Blocks.air).setBlockName("wand_air").setBlockTextureName(RefStrings.MODID + ":wand_air"); + wand_loot = new BlockWandLoot().setBlockName("wand_loot").setBlockTextureName(RefStrings.MODID + ":wand_loot"); + wand_jigsaw = new BlockWandJigsaw().setBlockName("wand_jigsaw").setBlockTextureName(RefStrings.MODID + ":wand_jigsaw"); } private static void registerBlock() { @@ -3475,6 +3485,10 @@ public class ModBlocks { GameRegistry.registerBlock(pink_slab, pink_slab.getUnlocalizedName()); GameRegistry.registerBlock(pink_double_slab, pink_double_slab.getUnlocalizedName()); GameRegistry.registerBlock(pink_stairs, pink_stairs.getUnlocalizedName()); + + register(wand_air); + register(wand_loot); + register(wand_jigsaw); } private static void register(Block b) { diff --git a/src/main/java/com/hbm/blocks/generic/BlockBobble.java b/src/main/java/com/hbm/blocks/generic/BlockBobble.java index df5d158ea..da175541c 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockBobble.java +++ b/src/main/java/com/hbm/blocks/generic/BlockBobble.java @@ -4,6 +4,9 @@ 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 cpw.mods.fml.common.network.internal.FMLNetworkHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -31,7 +34,7 @@ import net.minecraft.world.World; import java.util.List; import java.util.Random; -public class BlockBobble extends BlockContainer implements IGUIProvider { +public class BlockBobble extends BlockContainer implements IGUIProvider, INBTTransformable { public BlockBobble() { super(Material.iron); @@ -136,12 +139,17 @@ public class BlockBobble extends BlockContainer implements IGUIProvider { return AxisAlignedBB.getBoundingBox(x + this.minX, y + this.minY, z + this.minZ, x + this.maxX, y + this.maxY, z + this.maxZ); } + @Override + public int transformMeta(int meta, int coordBaseMode) { + return (meta + coordBaseMode * 4) % 16; + } + @Override public TileEntity createNewTileEntity(World world, int meta) { return new TileEntityBobble(); } - public static class TileEntityBobble extends TileEntity { + public static class TileEntityBobble extends TileEntity implements INBTTileEntityTransformable { public BobbleType type = BobbleType.NONE; @@ -173,6 +181,11 @@ public class BlockBobble extends BlockContainer implements IGUIProvider { super.writeToNBT(nbt); nbt.setByte("type", (byte) type.ordinal()); } + + @Override + public void transformTE(World world, int coordBaseMode) { + type = BobbleType.values()[world.rand.nextInt(BobbleType.values().length - 1) + 1]; + } } public static enum BobbleType { diff --git a/src/main/java/com/hbm/blocks/generic/BlockDecoCRT.java b/src/main/java/com/hbm/blocks/generic/BlockDecoCRT.java index 724912ed3..b1ede562a 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockDecoCRT.java +++ b/src/main/java/com/hbm/blocks/generic/BlockDecoCRT.java @@ -2,6 +2,7 @@ package com.hbm.blocks.generic; import com.hbm.blocks.BlockMulti; import com.hbm.lib.RefStrings; +import com.hbm.world.gen.INBTTransformable; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.relauncher.Side; @@ -14,7 +15,7 @@ import net.minecraft.util.IIcon; import net.minecraft.util.MathHelper; import net.minecraft.world.World; -public class BlockDecoCRT extends BlockMulti { +public class BlockDecoCRT extends BlockMulti implements INBTTransformable { protected String[] variants = new String[] {"crt_clean", "crt_broken", "crt_blinking", "crt_bsod"}; @SideOnly(Side.CLIENT) protected IIcon[] icons; @@ -24,17 +25,17 @@ public class BlockDecoCRT extends BlockMulti { } public static int renderID = RenderingRegistry.getNextAvailableRenderId(); - + @Override public int getRenderType(){ return renderID; } - + @Override public boolean isOpaqueCube() { return false; } - + @Override public boolean renderAsNormalBlock() { return false; @@ -45,12 +46,12 @@ public class BlockDecoCRT extends BlockMulti { public void registerBlockIcons(IIconRegister reg) { super.registerBlockIcons(reg); this.icons = new IIcon[variants.length]; - + for(int i = 0; i < variants.length; i++) { this.icons[i] = reg.registerIcon(RefStrings.MODID + ":" + variants[i]); } } - + @Override @SideOnly(Side.CLIENT) public IIcon getIcon(int side, int meta) { @@ -61,7 +62,7 @@ public class BlockDecoCRT extends BlockMulti { public int damageDropped(int meta) { return (Math.abs(meta) % 16) / 4; } - + @Override public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack stack) { int i = MathHelper.floor_double(player.rotationYaw * 4.0F / 360.0F + 0.5D) & 3; @@ -73,4 +74,10 @@ public class BlockDecoCRT extends BlockMulti { public int getSubCount() { return 4; } -} + + @Override + public int transformMeta(int meta, int coordBaseMode) { + return INBTTransformable.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 d70fd5fe4..f10edc069 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockDecoModel.java +++ b/src/main/java/com/hbm/blocks/generic/BlockDecoModel.java @@ -1,6 +1,7 @@ package com.hbm.blocks.generic; import com.hbm.blocks.BlockEnumMulti; +import com.hbm.world.gen.INBTTransformable; import cpw.mods.fml.client.registry.RenderingRegistry; import net.minecraft.block.material.Material; @@ -11,14 +12,14 @@ import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -public class BlockDecoModel extends BlockEnumMulti { - +public class BlockDecoModel extends BlockEnumMulti implements INBTTransformable { + public BlockDecoModel(Material mat, Class theEnum, boolean multiName, boolean multiTexture) { super(mat, theEnum, multiName, multiTexture); } - + public static int renderID = RenderingRegistry.getNextAvailableRenderId(); - + @Override public int getRenderType() { return renderID; @@ -33,18 +34,18 @@ public class BlockDecoModel extends BlockEnumMulti { public boolean renderAsNormalBlock() { return false; } - + //Did somebody say - pain? //Alright fuckers, looks like 2/b010 = North, 3/b011 = South, 4/b100 = West, 5/b101 = East for sides. //I'll just opt for something similar (0/b00 North, 1/b01 South, 2/b10 West, 3/b11 East) - + //Assumes meta is using the third and fourth bits. @Override public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack stack) { int i = MathHelper.floor_double(player.rotationYaw * 4.0F / 360.0F + 0.5D) & 3; - + int meta; - + if((i & 1) != 1) meta = i >> 1; //For North(b00>b00) and South(b10>b01), shift bits right by one else { @@ -53,15 +54,15 @@ public class BlockDecoModel extends BlockEnumMulti { else meta = 3; //For East(b01>b11), just set to 3 } - + world.setBlockMetadataWithNotify(x, y, z, (meta << 2) | stack.getItemDamage(), 2); } - + @Override public int damageDropped(int meta) { return meta & 3; } - + //These are separate because they have to be constant private float mnX = 0.0F; //min private float mnY = 0.0F; @@ -69,7 +70,7 @@ public class BlockDecoModel extends BlockEnumMulti { private float mxX = 1.0F; //max private float mxY = 1.0F; private float mxZ = 1.0F; - + public BlockDecoModel setBlockBoundsTo(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { mnX = minX; mnY = minY; @@ -77,10 +78,10 @@ public class BlockDecoModel extends BlockEnumMulti { mxX = maxX; mxY = maxY; mxZ = maxZ; - + return this; } - + @Override public void setBlockBoundsBasedOnState(IBlockAccess world, int x, int y, int z) { switch(world.getBlockMetadata(x, y, z) >> 2) { @@ -98,10 +99,39 @@ public class BlockDecoModel extends BlockEnumMulti { break; } } - + @Override public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) { this.setBlockBoundsBasedOnState(world, x, y, z); return AxisAlignedBB.getBoundingBox(x + this.minX, y + this.minY, z + this.minZ, x + this.maxX, y + this.maxY, z + this.maxZ); } + + @Override + public int transformMeta(int meta, int coordBaseMode) { + //N: 0b00, S: 0b01, W: 0b10, E: 0b11 + int rot = meta >> 2; + int type = meta & 3; + + switch(coordBaseMode) { + default: //South + break; + case 1: //West + if((rot & 3) < 2) //N & S can just have bits toggled + rot = rot ^ 3; + else //W & E can just have first bit set to 0 + rot = rot ^ 2; + break; + case 2: //North + rot = rot ^ 1; //N, W, E & S can just have first bit toggled + break; + case 3: //East + if((rot & 3) < 2)//N & S can just have second bit set to 1 + rot = rot ^ 2; + else //W & E can just have bits toggled + rot = rot ^ 3; + break; + } + //genuinely like. why did i do that + return (rot << 2) | type; //To accommodate for BlockDecoModel's shift in the rotation bits; otherwise, simply bit-shift right and or any non-rotation meta after + } } \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/generic/BlockDecoToaster.java b/src/main/java/com/hbm/blocks/generic/BlockDecoToaster.java index a11061fa0..c35dd1d3b 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockDecoToaster.java +++ b/src/main/java/com/hbm/blocks/generic/BlockDecoToaster.java @@ -2,6 +2,7 @@ package com.hbm.blocks.generic; import com.hbm.blocks.BlockMulti; import com.hbm.lib.RefStrings; +import com.hbm.world.gen.INBTTransformable; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.relauncher.Side; @@ -16,7 +17,7 @@ import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -public class BlockDecoToaster extends BlockMulti { +public class BlockDecoToaster extends BlockMulti implements INBTTransformable { protected String[] variants = new String[] {"toaster_iron", "toaster_steel", "toaster_wood"}; @SideOnly(Side.CLIENT) protected IIcon[] icons; @@ -26,17 +27,17 @@ public class BlockDecoToaster extends BlockMulti { } public static int renderID = RenderingRegistry.getNextAvailableRenderId(); - + @Override public int getRenderType(){ return renderID; } - + @Override public boolean isOpaqueCube() { return false; } - + @Override public boolean renderAsNormalBlock() { return false; @@ -47,12 +48,12 @@ public class BlockDecoToaster extends BlockMulti { public void registerBlockIcons(IIconRegister reg) { super.registerBlockIcons(reg); this.icons = new IIcon[variants.length]; - + for(int i = 0; i < variants.length; i++) { this.icons[i] = reg.registerIcon(RefStrings.MODID + ":" + variants[i]); } } - + @Override @SideOnly(Side.CLIENT) public IIcon getIcon(int side, int meta) { @@ -63,7 +64,7 @@ public class BlockDecoToaster extends BlockMulti { public int damageDropped(int meta) { return (Math.abs(meta) % 12) / 4; } - + @Override public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack stack) { int i = MathHelper.floor_double(player.rotationYaw * 4.0F / 360.0F + 0.5D) & 3; @@ -90,4 +91,10 @@ public class BlockDecoToaster extends BlockMulti { this.setBlockBoundsBasedOnState(world, x, y, z); return AxisAlignedBB.getBoundingBox(x + this.minX, y + this.minY, z + this.minZ, x + this.maxX, y + this.maxY, z + this.maxZ); } -} + + @Override + public int transformMeta(int meta, int coordBaseMode) { + return INBTTransformable.transformMetaDecoModel(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 a41d6cfdf..27eaf3b27 100644 --- a/src/main/java/com/hbm/blocks/generic/BlockPipe.java +++ b/src/main/java/com/hbm/blocks/generic/BlockPipe.java @@ -4,6 +4,7 @@ import java.util.List; import com.hbm.blocks.ITooltipProvider; import com.hbm.lib.RefStrings; +import com.hbm.world.gen.INBTTransformable; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.relauncher.Side; @@ -16,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 { +public class BlockPipe extends Block implements ITooltipProvider, INBTTransformable { @SideOnly(Side.CLIENT) private IIcon sideIcon; @@ -24,7 +25,7 @@ public class BlockPipe extends Block implements ITooltipProvider { public IIcon frameIcon; @SideOnly(Side.CLIENT) public IIcon meshIcon; - + private String sideString; public int rType = 0; //because registering either new renderer classes or making new block classes is a pain in the ass @@ -33,7 +34,7 @@ public class BlockPipe extends Block implements ITooltipProvider { this.sideString = tex; this.rType = rType; } - + @Override @SideOnly(Side.CLIENT) public void registerBlockIcons(IIconRegister iconRegister) { @@ -42,7 +43,7 @@ public class BlockPipe extends Block implements ITooltipProvider { this.frameIcon = iconRegister.registerIcon(RefStrings.MODID + ":pipe_frame"); this.meshIcon = iconRegister.registerIcon(RefStrings.MODID + ":pipe_mesh"); } - + @Override @SideOnly(Side.CLIENT) public IIcon getIcon(int side, int metadata) { @@ -92,4 +93,10 @@ public class BlockPipe extends Block implements ITooltipProvider { public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean ext) { list.add("Purely decorative"); } -} + + @Override + public int transformMeta(int meta, int coordBaseMode) { + return INBTTransformable.transformMetaPillar(meta, coordBaseMode); + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/generic/BlockWand.java b/src/main/java/com/hbm/blocks/generic/BlockWand.java new file mode 100644 index 000000000..c25c390eb --- /dev/null +++ b/src/main/java/com/hbm/blocks/generic/BlockWand.java @@ -0,0 +1,51 @@ +package com.hbm.blocks.generic; + +import cpw.mods.fml.client.registry.RenderingRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public class BlockWand extends Block { + + public final Block exportAs; + + public BlockWand(Block exportAs) { + super(Material.glass); + this.exportAs = exportAs; + setBlockBounds(1F/16F, 1F/16F, 1F/16F, 15F/16F, 15F/16F, 15F/16F); + } + + @Override + public boolean isOpaqueCube() { + return false; + } + + @Override + public boolean renderAsNormalBlock() { + return false; + } + + @Override + public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) { + return null; + } + + public static int renderID = RenderingRegistry.getNextAvailableRenderId(); + + @Override + public int getRenderType() { + return renderID; + } + + @SideOnly(Side.CLIENT) + public boolean shouldSideBeRendered(IBlockAccess world, int x, int y, int z, int side) { + Block block = world.getBlock(x, y, z); + + return block != this; + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/generic/BlockWandJigsaw.java b/src/main/java/com/hbm/blocks/generic/BlockWandJigsaw.java new file mode 100644 index 000000000..a8a44a55e --- /dev/null +++ b/src/main/java/com/hbm/blocks/generic/BlockWandJigsaw.java @@ -0,0 +1,387 @@ +package com.hbm.blocks.generic; + +import java.util.ArrayList; +import java.util.List; + +import org.lwjgl.input.Keyboard; + +import com.hbm.blocks.IBlockSideRotation; +import com.hbm.blocks.ILookOverlay; +import com.hbm.blocks.ModBlocks; +import com.hbm.interfaces.IControlReceiver; +import com.hbm.lib.RefStrings; +import com.hbm.main.MainRegistry; +import com.hbm.packet.PacketDispatcher; +import com.hbm.packet.toserver.NBTControlPacket; +import com.hbm.tileentity.IGUIProvider; +import com.hbm.tileentity.TileEntityLoadedBase; +import com.hbm.util.BufferUtil; +import com.hbm.util.I18nUtil; +import com.hbm.world.gen.INBTTransformable; + +import cpw.mods.fml.common.network.internal.FMLNetworkHandler; +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; +import net.minecraft.block.Block; +import net.minecraft.block.BlockContainer; +import net.minecraft.block.BlockPistonBase; +import net.minecraft.block.material.Material; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.Container; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IIcon; +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 { + + private IIcon iconTop; + private IIcon iconSide; + private IIcon iconBack; + + public BlockWandJigsaw() { + super(Material.iron); + } + + @Override + public TileEntity createNewTileEntity(World world, int meta) { + return new TileEntityWandJigsaw(); + } + + @Override + public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack stack) { + int l = BlockPistonBase.determineOrientation(world, x, y, z, player); + world.setBlockMetadataWithNotify(x, y, z, l, 2); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerBlockIcons(IIconRegister iconRegister) { + this.blockIcon = iconRegister.registerIcon(RefStrings.MODID + ":wand_jigsaw"); + this.iconTop = iconRegister.registerIcon(RefStrings.MODID + ":wand_jigsaw_top"); + this.iconSide = iconRegister.registerIcon(RefStrings.MODID + ":wand_jigsaw_side"); + this.iconBack = iconRegister.registerIcon(RefStrings.MODID + ":wand_jigsaw_back"); + } + + @Override + public IIcon getIcon(int side, int meta) { + if(side == meta) return blockIcon; + if(IBlockSideRotation.isOpposite(side, meta)) return iconBack; + if(side <= 1) return iconTop; + if(side > 3 && meta <= 1) return iconTop; + return iconSide; + } + + @Override + public int getRotationFromSide(IBlockAccess world, int x, int y, int z, int side) { + if(side == 0) return IBlockSideRotation.topToBottom(getRotationFromSide(world, x, y, z, 1)); + + int meta = world.getBlockMetadata(x, y, z); + if(side == meta || IBlockSideRotation.isOpposite(side, meta)) return 0; + + // downwards facing has no changes, upwards flips anything not handled already + if(meta == 0) return 0; + if(meta == 1) return 3; + + // top (and bottom) is rotated fairly normally + if(side == 1) { + switch(meta) { + case 2: return 3; + case 3: return 0; + case 4: return 1; + case 5: return 2; + } + } + + // you know what I aint explaining further, it's a fucking mess here + if(meta == 2) return side == 4 ? 2 : 1; + if(meta == 3) return side == 4 ? 1 : 2; + if(meta == 4) return side == 2 ? 1 : 2; + if(meta == 5) return side == 2 ? 2 : 1; + + return 0; + } + + @Override + public int getRenderType() { + return IBlockSideRotation.getRenderType(); + } + + @Override + public int transformMeta(int meta, int coordBaseMode) { + return INBTTransformable.transformMetaDeco(meta, coordBaseMode); + } + + @Override + public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) { + TileEntity te = world.getTileEntity(x, y, z); + + if(!(te instanceof TileEntityWandJigsaw)) return false; + + TileEntityWandJigsaw jigsaw = (TileEntityWandJigsaw) te; + + if(!player.isSneaking()) { + Block block = getBlock(world, player.getHeldItem()); + if(block == ModBlocks.wand_air) block = Blocks.air; + + if(block != null && block != ModBlocks.wand_jigsaw && block != ModBlocks.wand_loot) { + jigsaw.replaceBlock = block; + jigsaw.replaceMeta = player.getHeldItem().getItemDamage(); + + return true; + } + + if(world.isRemote) FMLNetworkHandler.openGui(player, MainRegistry.instance, 0, world, x, y, z); + + return true; + } + + return false; + } + + private Block getBlock(World world, ItemStack stack) { + if(stack == null) return null; + if(!(stack.getItem() instanceof ItemBlock)) return null; + + return ((ItemBlock) stack.getItem()).field_150939_a; + } + + @Override + @SideOnly(Side.CLIENT) + public Object provideGUI(int ID, EntityPlayer player, World world, int x, int y, int z) { + return new GuiWandJigsaw((TileEntityWandJigsaw) world.getTileEntity(x, y, z)); + } + + @Override + public Container provideContainer(int ID, EntityPlayer player, World world, int x, int y, int z) { + return null; + } + + @Override + public void printHook(Pre event, World world, int x, int y, int z) { + TileEntity te = world.getTileEntity(x, y, z); + if(!(te instanceof TileEntityWandJigsaw)) return; + TileEntityWandJigsaw jigsaw = (TileEntityWandJigsaw) te; + + List text = new ArrayList(); + + text.add(EnumChatFormatting.GRAY + "Target pool: " + EnumChatFormatting.RESET + jigsaw.pool); + text.add(EnumChatFormatting.GRAY + "Name: " + EnumChatFormatting.RESET + jigsaw.name); + text.add(EnumChatFormatting.GRAY + "Target name: " + EnumChatFormatting.RESET + jigsaw.target); + text.add(EnumChatFormatting.GRAY + "Turns into: " + EnumChatFormatting.RESET + GameRegistry.findUniqueIdentifierFor(jigsaw.replaceBlock).toString()); + text.add(EnumChatFormatting.GRAY + " with meta: " + EnumChatFormatting.RESET + jigsaw.replaceMeta); + text.add(EnumChatFormatting.GRAY + "Selection/Placement priority: " + EnumChatFormatting.RESET + jigsaw.selectionPriority + "/" + jigsaw.placementPriority); + text.add(EnumChatFormatting.GRAY + "Joint type: " + EnumChatFormatting.RESET + (jigsaw.isRollable ? "Rollable" : "Aligned")); + + ILookOverlay.printGeneric(event, I18nUtil.resolveKey(getUnlocalizedName() + ".name"), 0xffff00, 0x404000, text); + } + + + public static class TileEntityWandJigsaw extends TileEntityLoadedBase implements IControlReceiver { + + private int selectionPriority = 0; // higher priority = this jigsaw block is selected first for generation + private int placementPriority = 0; // higher priority = children of this jigsaw block are checked for jigsaw blocks of their own and selected first + private String pool = "default"; + private String name = "default"; + private String target = "default"; + private Block replaceBlock = Blocks.air; + private int replaceMeta = 0; + private boolean isRollable = true; // sets joint type, rollable joints can be placed in any orientation for vertical jigsaw connections + + @Override + public void updateEntity() { + if(!worldObj.isRemote) { + networkPackNT(15); + } + } + + @Override + public void serialize(ByteBuf buf) { + buf.writeInt(selectionPriority); + buf.writeInt(placementPriority); + BufferUtil.writeString(buf, pool); + BufferUtil.writeString(buf, name); + BufferUtil.writeString(buf, target); + buf.writeInt(Block.getIdFromBlock(replaceBlock)); + buf.writeInt(replaceMeta); + buf.writeBoolean(isRollable); + } + + @Override + public void deserialize(ByteBuf buf) { + selectionPriority = buf.readInt(); + placementPriority = buf.readInt(); + pool = BufferUtil.readString(buf); + name = BufferUtil.readString(buf); + target = BufferUtil.readString(buf); + replaceBlock = Block.getBlockById(buf.readInt()); + replaceMeta = buf.readInt(); + isRollable = buf.readBoolean(); + } + + @Override + public void writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + nbt.setInteger("direction", this.getBlockMetadata()); + + nbt.setInteger("selection", selectionPriority); + nbt.setInteger("placement", placementPriority); + nbt.setString("pool", pool); + nbt.setString("name", name); + nbt.setString("target", target); + nbt.setString("block", GameRegistry.findUniqueIdentifierFor(replaceBlock).toString()); + nbt.setInteger("meta", replaceMeta); + nbt.setBoolean("roll", isRollable); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + + selectionPriority = nbt.getInteger("selection"); + placementPriority = nbt.getInteger("placement"); + pool = nbt.getString("pool"); + name = nbt.getString("name"); + target = nbt.getString("target"); + replaceBlock = Block.getBlockFromName(nbt.getString("block")); + replaceMeta = nbt.getInteger("meta"); + isRollable = nbt.getBoolean("roll"); + } + + @Override + public boolean hasPermission(EntityPlayer player) { + return true; + } + + @Override + public void receiveControl(NBTTagCompound nbt) { + readFromNBT(nbt); + markDirty(); + } + + } + + public static class GuiWandJigsaw extends GuiScreen { + + private final TileEntityWandJigsaw jigsaw; + + private GuiTextField textPool; + private GuiTextField textName; + private GuiTextField textTarget; + + private GuiTextField textSelectionPriority; + private GuiTextField textPlacementPriority; + + private GuiButton jointToggle; + + public GuiWandJigsaw(TileEntityWandJigsaw jigsaw) { + this.jigsaw = jigsaw; + } + + @Override + public void initGui() { + Keyboard.enableRepeatEvents(true); + + textPool = new GuiTextField(fontRendererObj, this.width / 2 - 150, 50, 300, 20); + textPool.setText(jigsaw.pool); + + textName = new GuiTextField(fontRendererObj, this.width / 2 - 150, 100, 140, 20); + textName.setText(jigsaw.name); + + textTarget = new GuiTextField(fontRendererObj, this.width / 2 + 10, 100, 140, 20); + textTarget.setText(jigsaw.target); + + textSelectionPriority = new GuiTextField(fontRendererObj, this.width / 2 - 150, 150, 90, 20); + textSelectionPriority.setText("" + jigsaw.selectionPriority); + + textPlacementPriority = new GuiTextField(fontRendererObj, this.width / 2 - 40, 150, 90, 20); + textPlacementPriority.setText("" + jigsaw.placementPriority); + + jointToggle = new GuiButton(0, this.width / 2 + 60, 150, 90, 20, jigsaw.isRollable ? "Rollable" : "Aligned"); + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + drawDefaultBackground(); + + drawString(fontRendererObj, "Target pool:", this.width / 2 - 150, 37, 0xA0A0A0); + textPool.drawTextBox(); + + drawString(fontRendererObj, "Name:", this.width / 2 - 150, 87, 0xA0A0A0); + textName.drawTextBox(); + + drawString(fontRendererObj, "Target name:", this.width / 2 + 10, 87, 0xA0A0A0); + textTarget.drawTextBox(); + + drawString(fontRendererObj, "Selection priority:", this.width / 2 - 150, 137, 0xA0A0A0); + textSelectionPriority.drawTextBox(); + + drawString(fontRendererObj, "Placement priority:", this.width / 2 - 40, 137, 0xA0A0A0); + textPlacementPriority.drawTextBox(); + + drawString(fontRendererObj, "Joint type:", this.width / 2 + 60, 137, 0xA0A0A0); + jointToggle.drawButton(mc, mouseX, mouseY); + + super.drawScreen(mouseX, mouseY, partialTicks); + } + + @Override + public void onGuiClosed() { + Keyboard.enableRepeatEvents(false); + + NBTTagCompound data = new NBTTagCompound(); + jigsaw.writeToNBT(data); + + data.setString("pool", textPool.getText()); + data.setString("name", textName.getText()); + data.setString("target", textTarget.getText()); + + try { data.setInteger("selection", Integer.parseInt(textSelectionPriority.getText())); } catch(Exception ex) {} + try { data.setInteger("placement", Integer.parseInt(textPlacementPriority.getText())); } catch(Exception ex) {} + + data.setBoolean("roll", jointToggle.displayString == "Rollable"); + + PacketDispatcher.wrapper.sendToServer(new NBTControlPacket(data, jigsaw.xCoord, jigsaw.yCoord, jigsaw.zCoord)); + } + + @Override + protected void keyTyped(char typedChar, int keyCode) { + super.keyTyped(typedChar, keyCode); + textPool.textboxKeyTyped(typedChar, keyCode); + textName.textboxKeyTyped(typedChar, keyCode); + textTarget.textboxKeyTyped(typedChar, keyCode); + textSelectionPriority.textboxKeyTyped(typedChar, keyCode); + textPlacementPriority.textboxKeyTyped(typedChar, keyCode); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { + super.mouseClicked(mouseX, mouseY, mouseButton); + textPool.mouseClicked(mouseX, mouseY, mouseButton); + textName.mouseClicked(mouseX, mouseY, mouseButton); + textTarget.mouseClicked(mouseX, mouseY, mouseButton); + textSelectionPriority.mouseClicked(mouseX, mouseY, mouseButton); + textPlacementPriority.mouseClicked(mouseX, mouseY, mouseButton); + + if(jointToggle.mousePressed(mc, mouseX, mouseY)) { + System.out.println("displayString: " + jointToggle.displayString); + jointToggle.displayString = jointToggle.displayString == "Rollable" ? "Aligned" : "Rollable"; + } + } + + } + +} diff --git a/src/main/java/com/hbm/blocks/generic/BlockWandLoot.java b/src/main/java/com/hbm/blocks/generic/BlockWandLoot.java new file mode 100644 index 000000000..80b1f3b92 --- /dev/null +++ b/src/main/java/com/hbm/blocks/generic/BlockWandLoot.java @@ -0,0 +1,338 @@ +package com.hbm.blocks.generic; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import com.hbm.blocks.IBlockSideRotation; +import com.hbm.blocks.ILookOverlay; +import com.hbm.blocks.ITooltipProvider; +import com.hbm.blocks.ModBlocks; +import com.hbm.config.StructureConfig; +import com.hbm.itempool.ItemPool; +import com.hbm.lib.RefStrings; +import com.hbm.tileentity.TileEntityLoadedBase; +import com.hbm.util.BufferUtil; +import com.hbm.util.I18nUtil; +import com.hbm.util.LootGenerator; +import com.hbm.world.gen.INBTTileEntityTransformable; +import com.mojang.authlib.GameProfile; + +import api.hbm.block.IToolable; +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; +import net.minecraft.block.Block; +import net.minecraft.block.BlockContainer; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IIcon; +import net.minecraft.util.MathHelper; +import net.minecraft.util.WeightedRandomChestContent; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraftforge.client.event.RenderGameOverlayEvent.Pre; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.common.util.FakePlayerFactory; + +public class BlockWandLoot extends BlockContainer implements ILookOverlay, IToolable, ITooltipProvider, IBlockSideRotation { + + @SideOnly(Side.CLIENT) protected IIcon iconTop; + + public BlockWandLoot() { + super(Material.iron); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerBlockIcons(IIconRegister iconRegister) { + this.blockIcon = iconRegister.registerIcon(RefStrings.MODID + ":wand_loot"); + this.iconTop = iconRegister.registerIcon(RefStrings.MODID + ":wand_loot_top"); + } + + @Override + public IIcon getIcon(int side, int meta) { + return (side <= 1) ? iconTop : blockIcon; + } + + @Override + public int getRotationFromSide(IBlockAccess world, int x, int y, int z, int side) { + if(side == 0) return IBlockSideRotation.topToBottom(world.getBlockMetadata(x, y, z)); + if(side == 1) return world.getBlockMetadata(x, y, z); + return 0; + } + + @Override + public int getRenderType() { + return IBlockSideRotation.getRenderType(); + } + + @Override + public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemStack) { + int i = MathHelper.floor_double(player.rotationYaw * 4.0F / 360.0F + 0.5D) & 3; + + if(i == 0) world.setBlockMetadataWithNotify(x, y, z, 3, 2); + if(i == 1) world.setBlockMetadataWithNotify(x, y, z, 2, 2); + if(i == 2) world.setBlockMetadataWithNotify(x, y, z, 0, 2); + if(i == 3) world.setBlockMetadataWithNotify(x, y, z, 1, 2); + + TileEntity te = world.getTileEntity(x, y, z); + if(!(te instanceof TileEntityWandLoot)) return; + ((TileEntityWandLoot) te).placedRotation = player.rotationYaw; + } + + @Override + public void printHook(Pre event, World world, int x, int y, int z) { + TileEntity te = world.getTileEntity(x, y, z); + + if(!(te instanceof TileEntityWandLoot)) return; + + TileEntityWandLoot loot = (TileEntityWandLoot) te; + + List text = new ArrayList(); + text.add("Will replace with: " + loot.replaceBlock.getUnlocalizedName()); + text.add(" meta: " + loot.replaceMeta); + text.add("Loot pool: " + loot.poolName); + if(loot.replaceBlock != ModBlocks.deco_loot) { + text.add("Minimum items: " + loot.minItems); + text.add("Maximum items: " + loot.maxItems); + } + + ILookOverlay.printGeneric(event, I18nUtil.resolveKey(getUnlocalizedName() + ".name"), 0xffff00, 0x404000, text); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean ext) { + list.add("Define loot crates/piles in .nbt structures"); + list.add(EnumChatFormatting.GOLD + "Use screwdriver to increase/decrease minimum loot"); + list.add(EnumChatFormatting.GOLD + "Use hand drill to increase/decrease maximum loot"); + list.add(EnumChatFormatting.GOLD + "Use defuser to cycle loot types"); + list.add(EnumChatFormatting.GOLD + "Use container block to set the block that spawns with loot inside"); + } + + @Override + public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) { + TileEntity te = world.getTileEntity(x, y, z); + + if(!(te instanceof TileEntityWandLoot)) return false; + + TileEntityWandLoot loot = (TileEntityWandLoot) te; + + if(!player.isSneaking()) { + + Block block = getLootableBlock(world, player.getHeldItem()); + + if(block != null) { + loot.replaceBlock = block; + loot.replaceMeta = player.getHeldItem().getItemDamage(); + + List poolNames = loot.getPoolNames(block == ModBlocks.deco_loot); + if(!poolNames.contains(loot.poolName)) { + loot.poolName = poolNames.get(0); + } + + return true; + } + } + + return false; + } + + private Block getLootableBlock(World world, ItemStack stack) { + if(stack == null) return null; + + if(stack.getItem() instanceof ItemBlock) { + Block block = ((ItemBlock) stack.getItem()).field_150939_a; + + if(block == ModBlocks.deco_loot) return block; + + if(block instanceof ITileEntityProvider) { + TileEntity te = ((ITileEntityProvider) block).createNewTileEntity(world, 12); + if(te instanceof IInventory) return block; + } + } + + return null; + } + + @Override + public boolean onScrew(World world, EntityPlayer player, int x, int y, int z, int side, float fX, float fY, float fZ, ToolType tool) { + TileEntity te = world.getTileEntity(x, y, z); + + if(!(te instanceof TileEntityWandLoot)) return false; + + TileEntityWandLoot loot = (TileEntityWandLoot) te; + + switch(tool) { + case SCREWDRIVER: + if(player.isSneaking()) { + loot.minItems--; + if(loot.minItems < 0) loot.minItems = 0; + } else { + loot.minItems++; + loot.maxItems = Math.max(loot.minItems, loot.maxItems); + } + + return true; + + case HAND_DRILL: + if(player.isSneaking()) { + loot.maxItems--; + if(loot.maxItems < 0) loot.maxItems = 0; + loot.minItems = Math.min(loot.minItems, loot.maxItems); + } else { + loot.maxItems++; + } + + return true; + + case DEFUSER: + List poolNames = loot.getPoolNames(loot.replaceBlock == ModBlocks.deco_loot); + int index = poolNames.indexOf(loot.poolName); + + index += player.isSneaking() ? -1 : 1; + index = MathHelper.clamp_int(index, 0, poolNames.size() - 1); + + loot.poolName = poolNames.get(index); + + return true; + + default: return false; + } + } + + @Override + public TileEntity createNewTileEntity(World world, int meta) { + return new TileEntityWandLoot(); + } + + public static class TileEntityWandLoot extends TileEntityLoadedBase implements INBTTileEntityTransformable { + + private boolean triggerReplace; + + private Block replaceBlock = ModBlocks.deco_loot; + private int replaceMeta; + + private String poolName = LootGenerator.LOOT_BOOKLET; + private int minItems; + private int maxItems = 1; + + private float placedRotation; + + private static final GameProfile FAKE_PROFILE = new GameProfile(UUID.fromString("839eb18c-50bc-400c-8291-9383f09763e7"), "[NTM]"); + private static FakePlayer fakePlayer; + + @Override + public void updateEntity() { + if(!worldObj.isRemote) { + if(triggerReplace) { + // On the first tick of this TE, replace with intended block and fill with loot + replace(); + } else { + networkPackNT(15); + } + } + } + + private void replace() { + WeightedRandomChestContent[] pool = ItemPool.getPool(poolName); + + worldObj.setBlock(xCoord, yCoord, zCoord, replaceBlock, replaceMeta, 2); + + TileEntity te = worldObj.getTileEntity(xCoord, yCoord, zCoord); + + if(te instanceof IInventory) { + int count = minItems; + if(maxItems - minItems > 0) count += worldObj.rand.nextInt(maxItems - minItems); + WeightedRandomChestContent.generateChestContents(worldObj.rand, pool, (IInventory) te, count); + } else if(te instanceof BlockLoot.TileEntityLoot) { + LootGenerator.applyLoot(worldObj, xCoord, yCoord, zCoord, poolName); + } + + // Shouldn't happen but let's guard anyway, if it fails we just don't rotate the chest block correctly + if(!(worldObj instanceof WorldServer)) return; + + if(fakePlayer == null || fakePlayer.worldObj != worldObj) { + fakePlayer = FakePlayerFactory.get((WorldServer)worldObj, FAKE_PROFILE); + } + + fakePlayer.rotationYaw = fakePlayer.rotationYawHead = placedRotation; + + ItemStack fakeStack = new ItemStack(replaceBlock, 1, replaceMeta); + + replaceBlock.onBlockPlacedBy(worldObj, xCoord, yCoord, zCoord, fakePlayer, fakeStack); + } + + private List getPoolNames(boolean loot) { + if(loot) return Arrays.asList(LootGenerator.getLootNames()); + + List names = new ArrayList<>(); + names.addAll(ItemPool.pools.keySet()); + return names; + } + + @Override + public void transformTE(World world, int coordBaseMode) { + triggerReplace = !StructureConfig.debugStructures; + placedRotation = MathHelper.wrapAngleTo180_float(placedRotation + coordBaseMode * 90); + } + + @Override + public void writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + Block writeBlock = replaceBlock == null ? ModBlocks.deco_loot : replaceBlock; + nbt.setString("block", GameRegistry.findUniqueIdentifierFor(writeBlock).toString()); + nbt.setInteger("meta", replaceMeta); + nbt.setInteger("min", minItems); + nbt.setInteger("max", maxItems); + nbt.setString("pool", poolName); + nbt.setFloat("rot", placedRotation); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + replaceBlock = Block.getBlockFromName(nbt.getString("block")); + replaceMeta = nbt.getInteger("meta"); + minItems = nbt.getInteger("min"); + maxItems = nbt.getInteger("max"); + poolName = nbt.getString("pool"); + placedRotation = nbt.getFloat("rot"); + + if(replaceBlock == null) replaceBlock = ModBlocks.deco_loot; + } + + @Override + public void serialize(ByteBuf buf) { + buf.writeInt(Block.getIdFromBlock(replaceBlock)); + buf.writeInt(replaceMeta); + buf.writeInt(minItems); + buf.writeInt(maxItems); + BufferUtil.writeString(buf, poolName); + } + + @Override + public void deserialize(ByteBuf buf) { + replaceBlock = Block.getBlockById(buf.readInt()); + replaceMeta = buf.readInt(); + minItems = buf.readInt(); + maxItems = buf.readInt(); + poolName = BufferUtil.readString(buf); + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/generic/DecoBlock.java b/src/main/java/com/hbm/blocks/generic/DecoBlock.java index 9037b4f6a..bf25850eb 100644 --- a/src/main/java/com/hbm/blocks/generic/DecoBlock.java +++ b/src/main/java/com/hbm/blocks/generic/DecoBlock.java @@ -6,6 +6,7 @@ import java.util.Random; import com.hbm.blocks.ModBlocks; import com.hbm.tileentity.deco.TileEntityDecoBlock; +import com.hbm.world.gen.INBTTransformable; import api.hbm.block.IToolable; import cpw.mods.fml.client.registry.RenderingRegistry; @@ -24,8 +25,8 @@ import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -public class DecoBlock extends BlockContainer implements IToolable { - +public class DecoBlock extends BlockContainer implements IToolable, INBTTransformable { + Random rand = new Random(); public DecoBlock(Material p_i45386_1_) { @@ -36,7 +37,7 @@ public class DecoBlock extends BlockContainer implements IToolable { public boolean onScrew(World world, EntityPlayer player, int x, int y, int z, int side, float fX, float fY, float fZ, ToolType tool) { if(tool != ToolType.SCREWDRIVER) return false; if(this != ModBlocks.steel_wall && this != ModBlocks.steel_corner) return false; - + int meta = world.getBlockMetadata(x, y, z); if(!player.isSneaking()) { @@ -50,7 +51,7 @@ public class DecoBlock extends BlockContainer implements IToolable { else if(meta == 2) world.setBlockMetadataWithNotify(x, y, z, 4, 3); else if(meta == 5) world.setBlockMetadataWithNotify(x, y, z, 2, 3); } - + return true; } @@ -65,7 +66,7 @@ public class DecoBlock extends BlockContainer implements IToolable { public static int renderIDBeam = RenderingRegistry.getNextAvailableRenderId(); public static int renderIDWall = RenderingRegistry.getNextAvailableRenderId(); public static int renderIDCorner = RenderingRegistry.getNextAvailableRenderId(); - + @Override public int getRenderType(){ if(this == ModBlocks.steel_wall) return renderIDWall; @@ -73,32 +74,32 @@ public class DecoBlock extends BlockContainer implements IToolable { if(this == ModBlocks.steel_beam) return renderIDBeam; return -1; } - + @Override public boolean isOpaqueCube() { return false; } - + @Override public boolean renderAsNormalBlock() { return false; } - + @Override public Item getItemDropped(int p_149650_1_, Random p_149650_2_, int p_149650_3_) { return Item.getItemFromBlock(this); } - + @Override public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemStack) { int i = MathHelper.floor_double(player.rotationYaw * 4.0F / 360.0F + 0.5D) & 3; - + if(i == 0) world.setBlockMetadataWithNotify(x, y, z, 3, 2); if(i == 1) world.setBlockMetadataWithNotify(x, y, z, 4, 2); if(i == 2) world.setBlockMetadataWithNotify(x, y, z, 2, 2); if(i == 3) world.setBlockMetadataWithNotify(x, y, z, 5, 2); } - + @Override public void setBlockBoundsBasedOnState(IBlockAccess world, int x, int y, int z) { int te = world.getBlockMetadata(x, y, z); @@ -141,14 +142,14 @@ public class DecoBlock extends BlockContainer implements IToolable { this.setBlockBoundsBasedOnState(world, x, y, z); return AxisAlignedBB.getBoundingBox(x + this.minX, y + this.minY, z + this.minZ, x + this.maxX, y + this.maxY, z + this.maxZ); } - + @Override public void addCollisionBoxesToList(World world, int x, int y, int z, AxisAlignedBB aabb, List list, Entity collider) { - + if(this == ModBlocks.steel_corner) { int meta = world.getBlockMetadata(x, y, z); List bbs = new ArrayList(); - + switch(meta) { case 2: bbs.add(AxisAlignedBB.getBoundingBox(x + 0.25D, y + 0D, z + 0.875D, x + 1D, y + 1D, z + 1D)); @@ -171,7 +172,7 @@ public class DecoBlock extends BlockContainer implements IToolable { bbs.add(AxisAlignedBB.getBoundingBox(x + 0.25D, y + 0D, z + 0D, x + 1D, y + 1D, z + 0.125D)); break; } - + for(AxisAlignedBB bb : bbs) { if(aabb.intersectsWith(bb)) { list.add(bb); @@ -181,4 +182,9 @@ public class DecoBlock extends BlockContainer implements IToolable { super.addCollisionBoxesToList(world, x, y, z, aabb, list, collider); } } -} + + @Override + public int transformMeta(int meta, int coordBaseMode) { + return INBTTransformable.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 481236f78..109cabbc5 100644 --- a/src/main/java/com/hbm/blocks/generic/DecoPoleSatelliteReceiver.java +++ b/src/main/java/com/hbm/blocks/generic/DecoPoleSatelliteReceiver.java @@ -1,6 +1,7 @@ package com.hbm.blocks.generic; import com.hbm.tileentity.deco.TileEntityDecoPoleSatelliteReceiver; +import com.hbm.world.gen.INBTTransformable; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; @@ -10,7 +11,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; import net.minecraft.world.World; -public class DecoPoleSatelliteReceiver extends BlockContainer { +public class DecoPoleSatelliteReceiver extends BlockContainer implements INBTTransformable { public DecoPoleSatelliteReceiver(Material p_i45386_1_) { super(p_i45386_1_); @@ -20,26 +21,26 @@ public class DecoPoleSatelliteReceiver extends BlockContainer { public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_) { return new TileEntityDecoPoleSatelliteReceiver(); } - + @Override public int getRenderType(){ return -1; } - + @Override public boolean isOpaqueCube() { return false; } - + @Override public boolean renderAsNormalBlock() { return false; } - + @Override public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemStack) { int i = MathHelper.floor_double(player.rotationYaw * 4.0F / 360.0F + 0.5D) & 3; - + if(i == 0) { world.setBlockMetadataWithNotify(x, y, z, 2, 2); @@ -58,4 +59,9 @@ public class DecoPoleSatelliteReceiver extends BlockContainer { } } -} + @Override + public int transformMeta(int meta, int coordBaseMode) { + return INBTTransformable.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 6d94427e2..e7143aae6 100644 --- a/src/main/java/com/hbm/blocks/generic/DecoTapeRecorder.java +++ b/src/main/java/com/hbm/blocks/generic/DecoTapeRecorder.java @@ -1,5 +1,7 @@ package com.hbm.blocks.generic; +import com.hbm.world.gen.INBTTransformable; + import cpw.mods.fml.client.registry.RenderingRegistry; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; @@ -9,7 +11,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; import net.minecraft.world.World; -public class DecoTapeRecorder extends BlockContainer { +public class DecoTapeRecorder extends BlockContainer implements INBTTransformable { public DecoTapeRecorder(Material p_i45386_1_) { super(p_i45386_1_); @@ -19,28 +21,28 @@ public class DecoTapeRecorder extends BlockContainer { public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_) { return null; } - + public static int renderID = RenderingRegistry.getNextAvailableRenderId(); - + @Override public int getRenderType(){ return renderID; } - + @Override public boolean isOpaqueCube() { return false; } - + @Override public boolean renderAsNormalBlock() { return false; } - + @Override public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemStack) { int i = MathHelper.floor_double(player.rotationYaw * 4.0F / 360.0F + 0.5D) & 3; - + if(i == 0) { world.setBlockMetadataWithNotify(x, y, z, 2, 2); @@ -59,4 +61,9 @@ public class DecoTapeRecorder extends BlockContainer { } } -} + @Override + public int transformMeta(int meta, int coordBaseMode) { + return INBTTransformable.transformMetaDeco(meta, coordBaseMode); + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/blocks/machine/Spotlight.java b/src/main/java/com/hbm/blocks/machine/Spotlight.java index c40a9ef9c..f5a89d404 100644 --- a/src/main/java/com/hbm/blocks/machine/Spotlight.java +++ b/src/main/java/com/hbm/blocks/machine/Spotlight.java @@ -7,6 +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 cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.relauncher.Side; @@ -14,6 +15,7 @@ import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.block.Block; import net.minecraft.block.BlockSlab; import net.minecraft.block.material.Material; +import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.AxisAlignedBB; @@ -22,7 +24,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 { +public class Spotlight extends Block implements ISpotlight, INBTTransformable { // I'd be extending the ReinforcedLamp class if it wasn't for the inverted behaviour of these specific lights // I want these blocks to be eminently useful, so removing the need for redstone by default is desired, @@ -38,7 +40,7 @@ public class Spotlight extends Block implements ISpotlight { this.beamLength = beamLength; this.type = type; this.isOn = isOn; - + this.setHardness(1F); if(isOn) setLightLevel(1.0F); @@ -123,6 +125,8 @@ public class Spotlight extends Block implements ISpotlight { } private boolean updatePower(World world, int x, int y, int z) { + if(isBroken(world.getBlockMetadata(x, y, z))) return false; + boolean isPowered = world.isBlockIndirectlyGettingPowered(x, y, z); if(isOn && isPowered) { world.scheduleBlockUpdate(x, y, z, this, 4); @@ -148,7 +152,7 @@ public class Spotlight extends Block implements ISpotlight { @Override public void updateTick(World world, int x, int y, int z, Random p_149674_5_) { if (world.isRemote) return; - + if (isOn && world.isBlockIndirectlyGettingPowered(x, y, z)) { world.setBlock(x, y, z, getOff(), world.getBlockMetadata(x, y, z), 2); } @@ -159,6 +163,7 @@ public class Spotlight extends Block implements ISpotlight { public void onNeighborBlockChange(World world, int x, int y, int z, Block neighborBlock) { if(world.isRemote) return; if(neighborBlock instanceof SpotlightBeam) return; + if(neighborBlock == Blocks.air) return; ForgeDirection dir = getDirection(world, x, y, z); @@ -172,13 +177,13 @@ public class Spotlight extends Block implements ISpotlight { updateBeam(world, x, y, z); } - + @Override public boolean canPlaceBlockOnSide(World world, int x, int y, int z, int side) { if(!super.canPlaceBlockOnSide(world, x, y, z, side)) return false; - + ForgeDirection dir = ForgeDirection.getOrientation(side); - + return canPlace(world, x, y, z, dir); } @@ -215,6 +220,10 @@ public class Spotlight extends Block implements ISpotlight { return ForgeDirection.getOrientation(metadata >> 1); } + public boolean isBroken(int metadata) { + return (metadata & 1) == 1; + } + @Override public Item getItemDropped(int i, Random r, int j) { return Item.getItemFromBlock(getOn()); @@ -292,20 +301,20 @@ public class Spotlight extends Block implements ISpotlight { backPropagate(world, x, y, z, dir); } - + protected Block getOff() { if(this == ModBlocks.spotlight_incandescent) return ModBlocks.spotlight_incandescent_off; if(this == ModBlocks.spotlight_fluoro) return ModBlocks.spotlight_fluoro_off; if(this == ModBlocks.spotlight_halogen) return ModBlocks.spotlight_halogen_off; - + return this; } - + protected Block getOn() { if(this == ModBlocks.spotlight_incandescent_off) return ModBlocks.spotlight_incandescent; if(this == ModBlocks.spotlight_fluoro_off) return ModBlocks.spotlight_fluoro; if(this == ModBlocks.spotlight_halogen_off) return ModBlocks.spotlight_halogen; - + return this; } @@ -313,4 +322,19 @@ public class Spotlight extends Block implements ISpotlight { public int getBeamLength() { return this.beamLength; } -} + + @Override + public int transformMeta(int meta, int coordBaseMode) { + // +1 to set as broken, won't turn on until broken and replaced + return (INBTTransformable.transformMetaDeco(meta >> 1, coordBaseMode) << 1) + 1; + } + + @Override + public Block transformBlock(Block block) { + if(block == ModBlocks.spotlight_incandescent) return ModBlocks.spotlight_incandescent_off; + if(block == ModBlocks.spotlight_fluoro) return ModBlocks.spotlight_fluoro_off; + if(block == ModBlocks.spotlight_halogen) return ModBlocks.spotlight_halogen_off; + return block; + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/config/StructureConfig.java b/src/main/java/com/hbm/config/StructureConfig.java index 944a7cbb0..2f6bb9bf9 100644 --- a/src/main/java/com/hbm/config/StructureConfig.java +++ b/src/main/java/com/hbm/config/StructureConfig.java @@ -7,36 +7,40 @@ import com.hbm.main.MainRegistry; import net.minecraftforge.common.config.Configuration; public class StructureConfig { - + public static int enableStructures = 2; - + public static int structureMinChunks = 8; public static int structureMaxChunks = 24; - + public static double lootAmountFactor = 1D; - + + public static boolean debugStructures = false; + public static void loadFromConfig(Configuration config) { - + final String CATEGORY_STRUCTURES = CommonConfig.CATEGORY_STRUCTURES; String unparsedStructureFlag = CommonConfig.createConfigString(config, CATEGORY_STRUCTURES, "5.00_enableStructures", "Flag for whether modern NTM structures will spawn. Valid values are true|false|flag - flag will respect the \"Generate Structures\" world flag.", "flag"); enableStructures = CommonConfig.parseStructureFlag(unparsedStructureFlag); - + structureMinChunks = CommonConfig.createConfigInt(config, CATEGORY_STRUCTURES, "5.01_structureMinChunks", "Minimum non-zero distance between structures in chunks (Settings lower than 8 may be problematic).", 8); structureMaxChunks = CommonConfig.createConfigInt(config, CATEGORY_STRUCTURES, "5.02_structureMaxChunks", "Maximum non-zero distance between structures in chunks.", 24); - + lootAmountFactor = CommonConfig.createConfigDouble(config, CATEGORY_STRUCTURES, "5.03_lootAmountFactor", "General factor for loot spawns. Applies to spawned IInventories, not loot blocks.", 1D); - + + debugStructures = CommonConfig.createConfigBool(config, CATEGORY_STRUCTURES, "5.04_debugStructures", "If enabled, special structure blocks like jigsaw blocks will not be transformed after generating", false); + structureMinChunks = CommonConfig.setDef(structureMinChunks, 8); structureMaxChunks = CommonConfig.setDef(structureMaxChunks, 24); - + if(structureMinChunks > structureMaxChunks) { MainRegistry.logger.error("Fatal error config: Minimum value has been set higher than the maximum value!"); MainRegistry.logger.error(String.format(Locale.US, "Errored values will default back to %1$d and %2$d respectively, PLEASE REVIEW CONFIGURATION DESCRIPTION BEFORE MEDDLING WITH VALUES!", 8, 24)); structureMinChunks = 8; structureMaxChunks = 24; } - + } } diff --git a/src/main/java/com/hbm/crafting/handlers/MKUCraftingHandler.java b/src/main/java/com/hbm/crafting/handlers/MKUCraftingHandler.java index 5086e6388..8405b0f77 100644 --- a/src/main/java/com/hbm/crafting/handlers/MKUCraftingHandler.java +++ b/src/main/java/com/hbm/crafting/handlers/MKUCraftingHandler.java @@ -6,50 +6,52 @@ import java.util.List; import java.util.Random; import com.hbm.items.ModItems; +import com.hbm.items.special.ItemBookLore; import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; import net.minecraft.world.World; public class MKUCraftingHandler implements IRecipe { - + public static ItemStack[] MKURecipe; private static long lastSeed; @Override public boolean matches(InventoryCrafting inventory, World world) { - + if(world == null) return false; - + if(MKURecipe == null || world.getSeed() != lastSeed) generateRecipe(world); - + for(int i = 0; i < 9; i++) { ItemStack stack = inventory.getStackInRowAndColumn(i % 3, i / 3); ItemStack recipe = MKURecipe[i]; - + if(stack == null && recipe == null) continue; - + if(stack != null && recipe != null && stack.getItem() == recipe.getItem() && stack.getItemDamage() == recipe.getItemDamage()) continue; - + return false; } - + return true; } - + public static void generateRecipe(World world) { Random rand = new Random(world.getSeed()); - + if(lastSeed == world.getSeed() && MKURecipe != null) return; - + lastSeed = world.getSeed(); - + List list = Arrays.asList(new ItemStack[] { new ItemStack(ModItems.powder_iodine), new ItemStack(ModItems.powder_fire), @@ -61,12 +63,54 @@ public class MKUCraftingHandler implements IRecipe { null, null }); - + Collections.shuffle(list, rand); - + MKURecipe = list.toArray(new ItemStack[9]); } + public static Item getMKUItem(World world) { + switch(world.rand.nextInt(6)) { + case 0: return ModItems.powder_iodine; + case 1: return ModItems.powder_fire; + case 2: return ModItems.dust; + case 3: return ModItems.ingot_mercury; + case 4: return ModItems.morning_glory; + case 5: return ModItems.syringe_metal_empty; + default: return ModItems.flame_pony; + } + } + + public static ItemStack generateBook(World world, Item mkuItem) { + MKUCraftingHandler.generateRecipe(world); + ItemStack[] recipe = MKUCraftingHandler.MKURecipe; + + if(recipe == null) return new ItemStack(ModItems.flame_pony); + + String key = null; + int pages = 1; + if(mkuItem == ModItems.powder_iodine) { key = "book_iodine"; pages = 3; } + if(mkuItem == ModItems.powder_fire) { key = "book_phosphorous"; pages = 2; } + if(mkuItem == ModItems.dust) { key = "book_dust"; pages = 3; } + if(mkuItem == ModItems.ingot_mercury) { key = "book_mercury"; pages = 2; } + if(mkuItem == ModItems.morning_glory) { key = "book_flower"; pages = 2; } + if(mkuItem == ModItems.syringe_metal_empty) { key = "book_syringe"; pages = 2; } + + if(key == null) return new ItemStack(ModItems.flame_pony); + + int s = 1; + for(int i = 0; i < 9; i++) { + if(recipe[i] != null && recipe[i].getItem() == mkuItem) { + s = i + 1; break; + } + } + + ItemStack book = ItemBookLore.createBook(key, pages, 0x271E44, 0xFBFFF4); + ItemBookLore.addArgs(book, pages - 1, String.valueOf(s)); + + return book; + } + @Override public int getRecipeSize() { return 6; @@ -81,4 +125,4 @@ public class MKUCraftingHandler implements IRecipe { public ItemStack getRecipeOutput() { return new ItemStack(ModItems.syringe_mkunicorn); } -} +} \ No newline at end of file diff --git a/src/main/java/com/hbm/items/tool/ItemWandS.java b/src/main/java/com/hbm/items/tool/ItemWandS.java index 303a3114f..2de5998fb 100644 --- a/src/main/java/com/hbm/items/tool/ItemWandS.java +++ b/src/main/java/com/hbm/items/tool/ItemWandS.java @@ -1,7 +1,156 @@ package com.hbm.items.tool; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.text.DateFormat; +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 net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.world.World; public class ItemWandS extends Item { - -} + + private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss"); + + @Override + public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean bool) { + list.add("Creative-only item"); + list.add("\"Replication breeds decadence\""); + list.add("(Saves an area defined by two right-clicks,"); + list.add("adds a block to the blacklist by crouch right-clicking!)"); + + if(stack.stackTagCompound != null) { + int px = stack.stackTagCompound.getInteger("x"); + int py = stack.stackTagCompound.getInteger("y"); + int pz = stack.stackTagCompound.getInteger("z"); + + if(px != 0 || py != 0 || pz != 0) { + list.add(EnumChatFormatting.AQUA + "From: " + px + ", " + py + ", " + pz); + } else { + list.add(EnumChatFormatting.AQUA + "No start position set"); + } + + Set> blocks = getBlocks(stack); + + if(blocks.size() > 0) { + list.add("Blacklist:"); + for(Pair block : blocks) { + list.add(EnumChatFormatting.RED + "- " + block.key.getUnlocalizedName()); + } + } + } + } + + // why the fuck ye'd leave this whole thing obfuscated is beyond me + @Override + public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float fx, float fy, float fz) { + if(stack.stackTagCompound == null) { + stack.stackTagCompound = new NBTTagCompound(); + } + + if(player.isSneaking()) { + Pair target = new Pair(world.getBlock(x, y, z), world.getBlockMetadata(x, y, z)); + Set> blocks = getBlocks(stack); + + if(blocks.contains(target)) { + blocks.remove(target); + if(world.isRemote) player.addChatMessage(new ChatComponentText("Removed from blacklist " + target.key.getUnlocalizedName())); + } else { + blocks.add(target); + if(world.isRemote) player.addChatMessage(new ChatComponentText("Added to blacklist " + target.key.getUnlocalizedName())); + } + + setBlocks(stack, blocks); + + } else { + int px = stack.stackTagCompound.getInteger("x"); + int py = stack.stackTagCompound.getInteger("y"); + int pz = stack.stackTagCompound.getInteger("z"); + + if(px == 0 && py == 0 && pz == 0) { + setPosition(stack, x, y, z); + + if(world.isRemote) player.addChatMessage(new ChatComponentText("First position set!")); + } else { + setPosition(stack, 0, 0, 0); + + Set> blocks = getBlocks(stack); + blocks.add(new Pair(Blocks.air, 0)); + blocks.add(new Pair(ModBlocks.spotlight_beam, 0)); + + String filename = "structure_" + dateFormat.format(new Date()).toString() + ".nbt"; + + NBTStructure.saveArea(filename, world, x, y, z, px, py, pz, blocks); + + if(world.isRemote) player.addChatMessage(new ChatComponentText("Structure saved to: .minecraft/structures/" + filename)); + } + } + + return true; + } + + private void setPosition(ItemStack stack, int x, int y, int z) { + stack.stackTagCompound.setInteger("x", x); + stack.stackTagCompound.setInteger("y", y); + stack.stackTagCompound.setInteger("z", z); + } + + private Set> getBlocks(ItemStack stack) { + if(stack.stackTagCompound == null) { + return new HashSet<>(); + } + + int[] blockIds = stack.stackTagCompound.getIntArray("blocks"); + int[] metas = stack.stackTagCompound.getIntArray("metas"); + Set> blocks = new HashSet<>(blockIds.length); + + for(int i = 0; i < blockIds.length; i++) { + blocks.add(new Pair(Block.getBlockById(blockIds[i]), metas[i])); + } + + return blocks; + } + + @SuppressWarnings("unchecked") + private void setBlocks(ItemStack stack, Set> blocks) { + if(stack.stackTagCompound == null) { + stack.stackTagCompound = new NBTTagCompound(); + } + + stack.stackTagCompound.setIntArray("blocks", BobMathUtil.collectionToIntArray(blocks, i -> Block.getIdFromBlock(((Pair)i).getKey()))); + stack.stackTagCompound.setIntArray("metas", BobMathUtil.collectionToIntArray(blocks, i -> ((Pair)i).getValue())); + } + + @Override + public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player) { + if(stack.stackTagCompound == null) { + stack.stackTagCompound = new NBTTagCompound(); + } + + if(player.isSneaking()) { + stack.stackTagCompound.setIntArray("blocks", new int[0]); + stack.stackTagCompound.setIntArray("metas", new int[0]); + + if(world.isRemote) { + player.addChatMessage(new ChatComponentText("Cleared blacklist")); + } + } + + return stack; + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/lib/HbmWorld.java b/src/main/java/com/hbm/lib/HbmWorld.java index 3cd40d0ba..ed4ca9208 100644 --- a/src/main/java/com/hbm/lib/HbmWorld.java +++ b/src/main/java/com/hbm/lib/HbmWorld.java @@ -1,6 +1,7 @@ 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; @@ -18,9 +19,6 @@ public class HbmWorld { public static NTMWorldGenerator worldGenerator; public static void initWorldGen() { - - //MapGenStructureIO.registerStructure(StructureStartTest.class, "HFR_STRUCTURE"); - //MapGenStructureIO.func_143031_a(StructureComponentTest.class, "HFR_COMPONENT"); MapGenStructureIO.registerStructure(MapGenNTMFeatures.Start.class, "NTMFeatures"); MapGenStructureIO.registerStructure(BunkerStart.class, "NTMBunker"); registerNTMFeatures(); @@ -30,19 +28,20 @@ public class HbmWorld { worldGenerator = new NTMWorldGenerator(); registerWorldGen(worldGenerator, 1); //Ideally, move everything over from HbmWorldGen to NTMWorldGenerator MinecraftForge.EVENT_BUS.register(worldGenerator); - //registerWorldGen(new WorldGenTest(), 1); + + NBTStructure.register(); } - public static void registerWorldGen(IWorldGenerator nukerWorldGen, int weightedProbability) { + private static void registerWorldGen(IWorldGenerator nukerWorldGen, int weightedProbability) { GameRegistry.registerWorldGenerator(nukerWorldGen, weightedProbability); } /** Register structures in MapGenStructureIO */ - public static void registerNTMFeatures() { + private static void registerNTMFeatures() { CivilianFeatures.registerComponents(); OfficeFeatures.registerComponents(); RuinFeatures.registerComponents(); BunkerComponents.registerComponents(); MapGenStructureIO.func_143031_a(SiloComponent.class, "NTMSiloComponent"); } -} +} \ No newline at end of file diff --git a/src/main/java/com/hbm/lib/HbmWorldGen.java b/src/main/java/com/hbm/lib/HbmWorldGen.java index d3ed3f571..c78fe7219 100644 --- a/src/main/java/com/hbm/lib/HbmWorldGen.java +++ b/src/main/java/com/hbm/lib/HbmWorldGen.java @@ -545,37 +545,6 @@ public class HbmWorldGen implements IWorldGenerator { } - if (WorldConfig.meteorStructure > 0 && rand.nextInt(WorldConfig.meteorStructure) == 0 && biome != BiomeGenBase.ocean && biome != BiomeGenBase.deepOcean) { - int x = i + rand.nextInt(16) + 8; - int z = j + rand.nextInt(16) + 8; - - CellularDungeonFactory.meteor.generate(world, x, 10, z, rand); - - if(GeneralConfig.enableDebugMode) - MainRegistry.logger.info("[Debug] Successfully spawned meteor dungeon at " + x + " 10 " + z); - - int y = world.getHeightValue(x, z); - - for(int f = 0; f < 3; f++) - world.setBlock(x, y + f, z, ModBlocks.meteor_pillar); - world.setBlock(x, y + 3, z, ModBlocks.meteor_brick_chiseled); - - for(int f = 0; f < 10; f++) { - - x = i + rand.nextInt(65) - 32; - z = j + rand.nextInt(65) - 32; - y = world.getHeightValue(x, z); - - if(world.getBlock(x, y - 1, z).canPlaceTorchOnTop(world, x, y - 1, z)) { - world.setBlock(x, y, z, Blocks.skull, 1, 2); - TileEntitySkull skull = (TileEntitySkull)world.getTileEntity(x, y, z); - - if(skull != null) - skull.func_145903_a(rand.nextInt(16)); - } - } - } - if((biome == BiomeGenBase.jungle || biome == BiomeGenBase.jungleEdge || biome == BiomeGenBase.jungleHills) && WorldConfig.jungleStructure > 0 && rand.nextInt(WorldConfig.jungleStructure) == 0) { int x = i + rand.nextInt(16); diff --git a/src/main/java/com/hbm/main/ClientProxy.java b/src/main/java/com/hbm/main/ClientProxy.java index 95534ecbc..ed344f1e7 100644 --- a/src/main/java/com/hbm/main/ClientProxy.java +++ b/src/main/java/com/hbm/main/ClientProxy.java @@ -157,7 +157,7 @@ public class ClientProxy extends ServerProxy { registerBlockRenderer(); Jars.initJars(); - + ((IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager()).registerReloadListener(new QMAWLoader()); if(GeneralConfig.enableSoundExtension) { @@ -831,6 +831,8 @@ public class ClientProxy extends ServerProxy { RenderingRegistry.registerBlockHandler(new RenderRBMKReflector()); RenderingRegistry.registerBlockHandler(new RenderRBMKControl()); RenderingRegistry.registerBlockHandler(new RenderPribris()); + + RenderingRegistry.registerBlockHandler(new RenderBlockWand()); } @Override @@ -1733,12 +1735,12 @@ public class ClientProxy extends ServerProxy { EntityFX fx = new net.minecraft.client.particle.EntityCritFX(world, x, y, z, mX, mY, mZ); fx.nextTextureIndexX(); - + if(data.hasKey("color")) { Color color = new Color(data.getInteger("color")); fx.setRBGColorF(color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F); } - + Minecraft.getMinecraft().effectRenderer.addEffect(fx); } diff --git a/src/main/java/com/hbm/main/StructureManager.java b/src/main/java/com/hbm/main/StructureManager.java new file mode 100644 index 000000000..2456533ff --- /dev/null +++ b/src/main/java/com/hbm/main/StructureManager.java @@ -0,0 +1,63 @@ +package com.hbm.main; + +import com.hbm.lib.RefStrings; +import com.hbm.world.gen.NBTStructure; + +import net.minecraft.util.ResourceLocation; + +public class StructureManager { + + // METEOR DUNGEON + public static final NBTStructure meteor_spike = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/meteor-spike.nbt")); + public static final NBTStructure meteor_core = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/meteor-core.nbt")); + public static final NBTStructure meteor_corner = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/meteor-corner.nbt")); + public static final NBTStructure meteor_t = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/meteor-t.nbt")); + public static final NBTStructure meteor_stairs = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/meteor-stairs.nbt")); + public static final NBTStructure meteor_fallback = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/meteor-fallback.nbt")); + + public static final NBTStructure meteor_3_bale = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-bale.nbt")); + public static final NBTStructure meteor_3_blank = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-blank.nbt")); + public static final NBTStructure meteor_3_block = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-block.nbt")); + public static final NBTStructure meteor_3_crab = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-crab.nbt")); + public static final NBTStructure meteor_3_crab_tesla = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-crab-tesla.nbt")); + public static final NBTStructure meteor_3_crate = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-crate.nbt")); + public static final NBTStructure meteor_3_dirt = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-dirt.nbt")); + public static final NBTStructure meteor_3_lead = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-lead.nbt")); + public static final NBTStructure meteor_3_ooze = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-ooze.nbt")); + public static final NBTStructure meteor_3_pillar = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-pillar.nbt")); + public static final NBTStructure meteor_3_star = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-star.nbt")); + public static final NBTStructure meteor_3_tesla = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-tesla.nbt")); + public static final NBTStructure meteor_3_book = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-book.nbt")); + public static final NBTStructure meteor_3_mku = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-mku.nbt")); + public static final NBTStructure meteor_3_statue = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/loot3x3/meteor-3-statue.nbt")); + + public static final NBTStructure meteor_room_base_end = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-base-end.nbt")); + public static final NBTStructure meteor_room_base_thru = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-base-thru.nbt")); + + public static final NBTStructure meteor_room_balcony = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-balcony.nbt")); + public static final NBTStructure meteor_room_basic = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-basic.nbt")); + public static final NBTStructure meteor_room_dragon = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-dragon.nbt")); + public static final NBTStructure meteor_room_ladder = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-ladder.nbt")); + public static final NBTStructure meteor_room_ooze = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-ooze.nbt")); + public static final NBTStructure meteor_room_split = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-split.nbt")); + public static final NBTStructure meteor_room_stairs = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-stairs.nbt")); + public static final NBTStructure meteor_room_triple = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-triple.nbt")); + public static final NBTStructure meteor_room_fallback = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/room-fallback.nbt")); + + public static final NBTStructure meteor_dragon_chest = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/headloot/loot-chest.nbt")); + public static final NBTStructure meteor_dragon_tesla = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/headloot/loot-tesla.nbt")); + public static final NBTStructure meteor_dragon_trap = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/headloot/loot-trap.nbt")); + public static final NBTStructure meteor_dragon_crate_crab = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/meteor/room10/headloot/loot-crate-crab.nbt")); + + + + + public static final NBTStructure vertibird = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/vertibird.nbt")); + public static final NBTStructure crashed_vertibird = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/crashed-vertibird.nbt")); + + // public static final NBTStructure test_rot = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/test-rot.nbt")); + // public static final NBTStructure test_jigsaw = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/test-jigsaw.nbt")); + // public static final NBTStructure test_jigsaw_core = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/test-jigsaw-core.nbt")); + // public static final NBTStructure test_jigsaw_hall = new NBTStructure(new ResourceLocation(RefStrings.MODID, "structures/test-jigsaw-hall.nbt")); + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/render/block/RenderBlockWand.java b/src/main/java/com/hbm/render/block/RenderBlockWand.java new file mode 100644 index 000000000..d6d22efe2 --- /dev/null +++ b/src/main/java/com/hbm/render/block/RenderBlockWand.java @@ -0,0 +1,37 @@ +package com.hbm.render.block; + +import com.hbm.blocks.generic.BlockWand; + +import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler; +import net.minecraft.block.Block; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.world.IBlockAccess; + +public class RenderBlockWand implements ISimpleBlockRenderingHandler { + + @Override + public void renderInventoryBlock(Block block, int metadata, int modelId, RenderBlocks renderer) { + + } + + @Override + public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) { + renderer.renderFromInside = true; + renderer.renderStandardBlock(block, x, y, z); + renderer.renderFromInside = false; + renderer.renderStandardBlock(block, x, y, z); + + return true; + } + + @Override + public boolean shouldRender3DInInventory(int modelId) { + return false; + } + + @Override + public int getRenderId() { + return BlockWand.renderID; + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/tileentity/TileMappings.java b/src/main/java/com/hbm/tileentity/TileMappings.java index 12257b52e..d1cc8eaf6 100644 --- a/src/main/java/com/hbm/tileentity/TileMappings.java +++ b/src/main/java/com/hbm/tileentity/TileMappings.java @@ -15,6 +15,8 @@ import com.hbm.blocks.generic.BlockPedestal.TileEntityPedestal; import com.hbm.blocks.generic.BlockPlushie.TileEntityPlushie; import com.hbm.blocks.generic.BlockSnowglobe.TileEntitySnowglobe; import com.hbm.blocks.generic.BlockSupplyCrate.TileEntitySupplyCrate; +import com.hbm.blocks.generic.BlockWandJigsaw.TileEntityWandJigsaw; +import com.hbm.blocks.generic.BlockWandLoot.TileEntityWandLoot; import com.hbm.blocks.generic.PartEmitter.TileEntityPartEmitter; import com.hbm.blocks.machine.BlockICF.TileEntityBlockICF; import com.hbm.blocks.machine.BlockPWR.TileEntityBlockPWR; @@ -48,7 +50,7 @@ public class TileMappings { public static HashMap, String[]> map = new HashMap, String[]>(); public static List> configurables = new ArrayList>(); - + public static void writeMappings() { put(TileEntityDiFurnace.class, "tilentity_diFurnace"); put(TileEntityObjTester.class, "tilentity_objtester"); @@ -206,7 +208,7 @@ public class TileMappings { put(TileEntityMachineOrbus.class, "tileentity_orbus"); put(TileEntityGlpyhidSpawner.class, "tileentity_glyphid_spawner"); put(TileEntityCustomMachine.class, "tileentity_custom_machine"); - + put(TileEntityLoot.class, "tileentity_ntm_loot"); put(TileEntityPedestal.class, "tileentity_ntm_pedestal"); put(TileEntityBobble.class, "tileentity_ntm_bobblehead"); @@ -218,9 +220,9 @@ public class TileMappings { put(TileEntityCharger.class, "tileentity_ntm_charger"); put(TileEntityRefueler.class, "tileentity_ntm_refueler"); - + put(TileEntityFileCabinet.class, "tileentity_file_cabinet"); - + put(TileEntityProxyInventory.class, "tileentity_proxy_inventory"); put(TileEntityProxyEnergy.class, "tileentity_proxy_power"); put(TileEntityProxyCombo.class, "tileentity_proxy_combo"); @@ -232,7 +234,10 @@ public class TileMappings { put(TileEntityPWRController.class, "tileentity_pwr_controller"); put(TileEntityData.class, "tileentity_data"); - + + put(TileEntityWandLoot.class, "tileentity_wand_loot"); + put(TileEntityWandJigsaw.class, "tileentity_wand_jigsaw"); + putNetwork(); putBombs(); putTurrets(); @@ -243,7 +248,7 @@ public class TileMappings { TileEntityMachineRadarNT.registerEntityClasses(); TileEntityMachineRadarNT.registerConverters(); } - + private static void putBombs() { put(TileEntityBombMulti.class, "tileentity_bombmulti"); put(TileEntityNukeGadget.class, "tilentity_nukegadget"); @@ -258,7 +263,7 @@ public class TileMappings { put(TileEntityCharge.class, "tileentity_explosive_charge"); put(TileEntityVolcanoCore.class, "tileentity_volcano_core"); } - + private static void putTurrets() { put(TileEntityTurretChekhov.class, "tileentity_turret_chekhov"); put(TileEntityTurretJeremy.class, "tileentity_turret_jeremy"); @@ -275,7 +280,7 @@ public class TileMappings { put(TileEntityTurretSentry.class, "tileentity_turret_sentry"); put(TileEntityTurretSentryDamaged.class, "tileentity_turret_sentry_damaged"); } - + private static void putMachines() { put(TileEntityHeaterFirebox.class, "tileentity_firebox"); put(TileEntityHeaterOven.class, "tileentity_heating_oven"); @@ -295,7 +300,7 @@ public class TileMappings { put(TileEntityMachinePumpSteam.class, "tileentity_steam_pump"); put(TileEntityMachinePumpElectric.class, "tileentity_electric_pump"); - + put(TileEntityFoundryMold.class, "tileentity_foundry_mold"); put(TileEntityFoundryBasin.class, "tileentity_foundry_basin"); put(TileEntityFoundryChannel.class, "tileentity_foundry_channel"); @@ -310,7 +315,7 @@ public class TileMappings { put(TileEntityDiFurnaceRTG.class, "tileentity_rtg_difurnace"); put(TileEntityMachineRadiolysis.class, "tileentity_radiolysis"); put(TileEntityMachineAutosaw.class, "tileentity_autosaw"); - + put(TileEntityCondenser.class, "tileentity_condenser"); put(TileEntityTowerSmall.class, "tileentity_cooling_tower_small"); put(TileEntityTowerLarge.class, "tileentity_cooling_tower_large"); @@ -332,12 +337,12 @@ public class TileMappings { put(TileEntityChungus.class, "tileentity_chungus"); put(TileEntityMachineCombustionEngine.class, "tileentity_combustion_engine"); - + put(TileEntityMachineAssembler.class, "tileentity_assembly_machine"); put(TileEntityMachineAssemfac.class, "tileentity_assemfac"); put(TileEntityMachineChemplant.class, "tileentity_chemical_plant"); put(TileEntityMachineChemfac.class, "tileentity_chemfac"); - + put(TileEntityMachineOilWell.class, "tileentity_derrick"); put(TileEntityMachinePumpjack.class, "tileentity_machine_pumpjack"); put(TileEntityMachineFrackingTower.class, "tileentity_fracking_tower"); @@ -353,21 +358,21 @@ public class TileMappings { put(TileEntityMachinePyroOven.class, "tileentity_pyrooven"); put(TileEntityChimneyBrick.class, "tileentity_chimney_brick"); put(TileEntityChimneyIndustrial.class, "tileentity_chimney_industrial"); - + put(TileEntityReactorZirnox.class, "tileentity_zirnox"); put(TileEntityZirnoxDestroyed.class, "tileentity_zirnox_destroyed"); put(TileEntityWatz.class, "tileentity_watz"); put(TileEntityWatzPump.class, "tileentity_watz_pump"); } - + private static void putPile() { put(TileEntityPileFuel.class, "tileentity_pile_fuel"); put(TileEntityPileSource.class, "tileentity_pile_source"); put(TileEntityPileBreedingFuel.class, "tileentity_pile_breedingfuel"); put(TileEntityPileNeutronDetector.class, "tileentity_pile_neutrondetector"); } - + private static void putRBMK() { put(TileEntityRBMKRod.class, "tileentity_rbmk_rod"); put(TileEntityRBMKRodReaSim.class, "tileentity_rbmk_rod_reasim"); @@ -387,12 +392,12 @@ public class TileMappings { put(TileEntityRBMKInlet.class, "tileentity_rbmk_inlet"); put(TileEntityRBMKOutlet.class, "tileentity_rbmk_outlet"); } - + private static void putNetwork() { put(TileEntityCableBaseNT.class, "tileentity_cable", "tileentity_wirecoated"); put(TileEntityCableSwitch.class, "tileentity_cable_switch"); put(TileEntityDiode.class, "tileentity_cable_diode"); - + put(TileEntityConnector.class, "tileentity_connector_redwire"); put(TileEntityPylon.class, "tileentity_pylon_redwire"); put(TileEntityPylonMedium.class, "tileentity_pylon_medium"); @@ -415,24 +420,24 @@ public class TileMappings { put(TileEntityRadioTorchCounter.class, "tileentity_rtty_counter"); put(TileEntityRadioTorchLogic.class, "tileentity_rtty_logic"); put(TileEntityRadioTelex.class, "tileentity_rtty_telex"); - + put(TileEntityDroneWaypoint.class, "tileentity_drone_waypoint"); put(TileEntityDroneCrate.class, "tileentity_drone_crate"); put(TileEntityDroneWaypointRequest.class, "tileentity_drone_waypoint_request"); put(TileEntityDroneDock.class, "tileentity_drone_dock"); put(TileEntityDroneProvider.class, "tileentity_drone_provider"); put(TileEntityDroneRequester.class, "tileentity_drone_requester"); - + put(TileEntityRailSwitch.class, "tileentity_rail_switch"); } - + private static void put(Class clazz, String... names) { map.put(clazz, names); /*if((IFluidSource.class.isAssignableFrom(clazz) || IFluidAcceptor.class.isAssignableFrom(clazz)) && !IFluidConnector.class.isAssignableFrom(clazz)) { LoggingUtil.errorWithHighlight(clazz.getCanonicalName() + " implements the old interfaces but not IFluidConnector!"); }*/ - + if(IConfigurableMachine.class.isAssignableFrom(clazz)) { configurables.add((Class) clazz); } diff --git a/src/main/java/com/hbm/util/LootGenerator.java b/src/main/java/com/hbm/util/LootGenerator.java index b55cc92c8..b14306b9e 100644 --- a/src/main/java/com/hbm/util/LootGenerator.java +++ b/src/main/java/com/hbm/util/LootGenerator.java @@ -2,6 +2,7 @@ package com.hbm.util; import com.hbm.blocks.ModBlocks; import com.hbm.blocks.generic.BlockLoot.TileEntityLoot; +import com.hbm.crafting.handlers.MKUCraftingHandler; import com.hbm.inventory.OreDictManager.DictFrame; import com.hbm.itempool.ItemPool; import com.hbm.itempool.ItemPoolsPile; @@ -10,6 +11,7 @@ import com.hbm.items.special.ItemBookLore; import com.hbm.items.weapon.sedna.factory.GunFactory.EnumAmmo; import net.minecraft.init.Items; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.world.World; @@ -17,6 +19,45 @@ import java.util.Random; public class LootGenerator { + public static final String LOOT_BOOKLET = "LOOT_BOOKLET"; + public static final String LOOT_CAPNUKE = "LOOT_CAPNUKE"; + public static final String LOOT_MEDICINE = "LOOT_MEDICINE"; + public static final String LOOT_CAPSTASH = "LOOT_CAPSTASH"; + public static final String LOOT_MAKESHIFT_GUN = "LOOT_MAKESHIFT_GUN"; + public static final String LOOT_NUKE_STORAGE = "LOOT_NUKE_STORAGE"; + public static final String LOOT_BONES = "LOOT_BONES"; + public static final String LOOT_GLYPHID_HIVE = "LOOT_GLYPHID_HIVE"; + public static final String LOOT_METEOR = "LOOT_METEOR"; + + public static void applyLoot(World world, int x, int y, int z, String name) { + switch(name) { + case LOOT_BOOKLET: lootBooklet(world, x, y, z); + case LOOT_CAPNUKE: lootCapNuke(world, x, y, z); + case LOOT_MEDICINE: lootMedicine(world, x, y, z); + case LOOT_CAPSTASH: lootCapStash(world, x, y, z); + case LOOT_MAKESHIFT_GUN: lootMakeshiftGun(world, x, y, z); + case LOOT_NUKE_STORAGE: lootNukeStorage(world, x, y, z); + case LOOT_BONES: lootBones(world, x, y, z); + case LOOT_GLYPHID_HIVE: lootGlyphidHive(world, x, y, z); + case LOOT_METEOR: lootBookMeteor(world, x, y, z); + default: lootBones(world, x, y, z); break; + } + } + + public static String[] getLootNames() { + return new String[] { + LOOT_BOOKLET, + LOOT_CAPNUKE, + LOOT_MEDICINE, + LOOT_CAPSTASH, + LOOT_MAKESHIFT_GUN, + LOOT_NUKE_STORAGE, + LOOT_BONES, + LOOT_GLYPHID_HIVE, + LOOT_METEOR, + }; + } + public static void setBlock(World world, int x, int y, int z) { world.setBlock(x, y, z, ModBlocks.deco_loot); } @@ -142,6 +183,19 @@ public class LootGenerator { } } + public static void lootBookMeteor(World world, int x, int y, int z) { + + TileEntityLoot loot = (TileEntityLoot) world.getTileEntity(x, y, z); + + if(loot != null && loot.items.isEmpty()) { + Item mkuItem = MKUCraftingHandler.getMKUItem(world); + ItemStack mkuBook = MKUCraftingHandler.generateBook(world, mkuItem); + + addItemWithDeviation(loot, world.rand, new ItemStack(mkuItem), 0, 0, 0.25); + addItemWithDeviation(loot, world.rand, mkuBook, 0, 0, -0.25); + } + } + public static void lootBookLore(World world, int x, int y, int z, ItemStack book) { TileEntityLoot loot = (TileEntityLoot) world.getTileEntity(x, y, z); @@ -157,4 +211,4 @@ public class LootGenerator { } } -} +} \ No newline at end of file diff --git a/src/main/java/com/hbm/world/gen/INBTTileEntityTransformable.java b/src/main/java/com/hbm/world/gen/INBTTileEntityTransformable.java new file mode 100644 index 000000000..33dc141c8 --- /dev/null +++ b/src/main/java/com/hbm/world/gen/INBTTileEntityTransformable.java @@ -0,0 +1,14 @@ +package com.hbm.world.gen; + +import net.minecraft.world.World; + +public interface INBTTileEntityTransformable { + + /** + * Like INBTTransformable but for TileEntities, like for randomizing bobbleheads + */ + + // Allows for the TE to modify itself when spawned in an NBT structure + public void transformTE(World world, int coordBaseMode); + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/world/gen/INBTTransformable.java b/src/main/java/com/hbm/world/gen/INBTTransformable.java new file mode 100644 index 000000000..b42d6bd43 --- /dev/null +++ b/src/main/java/com/hbm/world/gen/INBTTransformable.java @@ -0,0 +1,161 @@ +package com.hbm.world.gen; + +import net.minecraft.block.Block; + +public interface INBTTransformable { + + /** + * Defines this block as something that has a rotation or some other blockstate + * which needs transformations applied when building from an .nbt structure file + */ + + // Takes the block current meta and translates it into a rotated meta + public int transformMeta(int meta, int coordBaseMode); + + // Takes the block and turns it into a different block entirely, to turn off lights, shit like that + public default Block transformBlock(Block block) { + return block; + } + + + /** + * A fair few blocks have generalized rotations so, since we have all this space, put em here + */ + + public static int transformMetaDeco(int meta, int coordBaseMode) { + switch(coordBaseMode) { + case 1: //West + switch(meta) { + case 2: return 5; + case 3: return 4; + case 4: return 2; + case 5: return 3; + } + case 2: //North + switch(meta) { + case 2: return 3; + case 3: return 2; + case 4: return 5; + case 5: return 4; + } + case 3: //East + switch(meta) { + case 2: return 4; + case 3: return 5; + case 4: return 3; + case 5: return 2; + } + } + return meta; + } + + public static int transformMetaDecoModel(int meta, int coordBaseMode) { + int rot = (meta + coordBaseMode) % 4; + int type = (meta / 4) * 4; + + return rot | type; + } + + public static int transformMetaStairs(int meta, int coordBaseMode) { + switch(coordBaseMode) { + case 1: //West + if((meta & 3) < 2) //Flip second bit for E/W + meta = meta ^ 2; + else + meta = meta ^ 3; //Flip both bits for N/S + break; + case 2: //North + meta = meta ^ 1; //Flip first bit + break; + case 3: //East + if((meta & 3) < 2) //Flip both bits for E/W + meta = meta ^ 3; + else //Flip second bit for N/S + meta = meta ^ 2; + break; + } + + return meta; + } + + public static int transformMetaPillar(int meta, int coordBaseMode) { + if(coordBaseMode == 2) return meta; + int type = meta & 3; + int rot = meta & 12; + + if(rot == 4) return type | 8; + if(rot == 8) return type | 4; + + return meta; + } + + public static int transformMetaDirectional(int meta, int coordBaseMode) { + int rot = meta & 3; + int other = meta & 12; + + switch(coordBaseMode) { + default: //S + break; + case 1: //W + rot = (rot + 1) % 4; break; + case 2: //N + rot ^= 2; break; + case 3: //E + rot = (rot + 3) % 4; break; + } + + return other | rot; + } + + public static int transformMetaTorch(int meta, int coordBaseMode) { + switch(coordBaseMode) { + case 1: //West + switch(meta) { + case 1: return 3; + case 2: return 4; + case 3: return 2; + case 4: return 1; + } + case 2: //North + switch(meta) { + case 1: return 2; + case 2: return 1; + case 3: return 4; + case 4: return 3; + } + case 3: //East + switch(meta) { + case 1: return 4; + case 2: return 3; + case 3: return 1; + case 4: return 2; + } + } + return meta; + } + + public static int transformMetaDoor(int meta, int coordBaseMode) { + if(meta == 8 || meta == 9) return meta; // ignore top parts + + return transformMetaDirectional(meta, coordBaseMode); + } + + public static int transformMetaLever(int meta, int coordBaseMode) { + if(meta <= 0 || meta >= 7) { //levers suck ass + switch(coordBaseMode) { + case 1: case 3: //west / east + meta ^= 0b111; + } + } else if(meta >= 5) { + switch(coordBaseMode) { + case 1: case 3: //west / east + meta = (meta + 1) % 2 + 5; + } + } else { + meta = transformMetaTorch(meta, coordBaseMode); + } + + return meta; + } + +} \ 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/NBTStructure.java new file mode 100644 index 000000000..43625a627 --- /dev/null +++ b/src/main/java/com/hbm/world/gen/NBTStructure.java @@ -0,0 +1,1155 @@ +package com.hbm.world.gen; + +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; +import com.hbm.blocks.generic.BlockWand; +import com.hbm.config.GeneralConfig; +import com.hbm.config.StructureConfig; +import com.hbm.handler.ThreeInts; +import com.hbm.main.MainRegistry; +import com.hbm.util.Tuple.Pair; +import com.hbm.util.Tuple.Quartet; + +import cpw.mods.fml.common.registry.GameRegistry; +import net.minecraft.block.*; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagInt; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.structure.MapGenStructure; +import net.minecraft.world.gen.structure.MapGenStructureIO; +import net.minecraft.world.gen.structure.StructureBoundingBox; +import net.minecraft.world.gen.structure.StructureComponent; +import net.minecraft.world.gen.structure.StructureComponent.BlockSelector; +import net.minecraft.world.gen.structure.StructureStart; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.common.util.Constants.NBT; + +public class NBTStructure { + + /** + * Now with structure support! + * + * the type of structure to generate is saved into the Component, + * meaning this can generate all sorts of different structures, + * without having to define and register each structure manually + */ + + protected static Map> weightedMap = new HashMap<>(); + + // serialization data + protected static Map jigsawMap = new HashMap<>(); + + private String name; + + private boolean isLoaded; + + private ThreeInts size; + private List> itemPalette; + private BlockState[][][] blockArray; + + private List> fromConnections; + private Map> toTopConnections; + private Map> toBottomConnections; + private Map> toHorizontalConnections; + + public NBTStructure(ResourceLocation resource) { + // Can't use regular resource loading, servers don't know how! + InputStream stream = NBTStructure.class.getResourceAsStream("/assets/" + resource.getResourceDomain() + "/" + resource.getResourcePath()); + if(stream != null) { + name = resource.getResourcePath(); + loadStructure(stream); + } else { + MainRegistry.logger.error("NBT Structure not found: " + resource.getResourcePath()); + } + } + + public static void register() { + MapGenStructureIO.registerStructure(Start.class, "NBTStructures"); + MapGenStructureIO.func_143031_a(Component.class, "NBTComponents"); + } + + // Register a new structure for a given dimension + public static void registerStructure(int dimensionId, SpawnCondition spawn) { + List weightedList = weightedMap.computeIfAbsent(dimensionId, integer -> new ArrayList()); + for(int i = 0; i < spawn.spawnWeight; i++) { + weightedList.add(spawn); + } + } + + public static void registerStructure(SpawnCondition spawn, int... dimensionIds) { + for(int dimensionId : dimensionIds) { + registerStructure(dimensionId, spawn); + } + } + + // Add a chance for nothing to spawn at a given valid spawn location + public static void registerNullWeight(int dimensionId, int weight) { + registerNullWeight(dimensionId, weight, null); + } + + public static void registerNullWeight(int dimensionId, int weight, Predicate predicate) { + SpawnCondition spawn = new SpawnCondition() {{ + spawnWeight = weight; + canSpawn = predicate; + }}; + + List weightedList = weightedMap.computeIfAbsent(dimensionId, integer -> new ArrayList()); + for(int i = 0; i < spawn.spawnWeight; i++) { + weightedList.add(spawn); + } + } + + // 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(); + NBTTagList nbtBlocks = new NBTTagList(); + NBTTagList nbtPalette = new NBTTagList(); + NBTTagList nbtItemPalette = new NBTTagList(); + + // Quick access hash slinging slashers + Map, Integer> palette = new HashMap<>(); + Map itemPalette = new HashMap<>(); + + structure.setInteger("version", 1); + + int ox = Math.min(x1, x2); + int oy = Math.min(y1, y2); + int oz = Math.min(z1, z2); + + for(int x = ox; x <= Math.max(x1, x2); x++) { + for(int y = oy; y <= Math.max(y1, y2); y++) { + for(int z = oz; z <= Math.max(z1, z2); z++) { + Pair block = new Pair(world.getBlock(x, y, z), world.getBlockMetadata(x, y, z)); + + if(exclude.contains(block)) continue; + + if(block.key instanceof BlockWand) { + block.key = ((BlockWand) block.key).exportAs; + } + + int paletteId = palette.size(); + if(palette.containsKey(block)) { + paletteId = palette.get(block); + } else { + palette.put(block, paletteId); + + NBTTagCompound nbtBlock = new NBTTagCompound(); + nbtBlock.setString("Name", GameRegistry.findUniqueIdentifierFor(block.key).toString()); + + NBTTagCompound nbtProp = new NBTTagCompound(); + nbtProp.setString("meta", block.value.toString()); + + nbtBlock.setTag("Properties", nbtProp); + + nbtPalette.appendTag(nbtBlock); + } + + NBTTagCompound nbtBlock = new NBTTagCompound(); + nbtBlock.setInteger("state", paletteId); + + NBTTagList nbtPos = new NBTTagList(); + nbtPos.appendTag(new NBTTagInt(x - ox)); + nbtPos.appendTag(new NBTTagInt(y - oy)); + nbtPos.appendTag(new NBTTagInt(z - oz)); + + nbtBlock.setTag("pos", nbtPos); + + TileEntity te = world.getTileEntity(x, y, z); + if(te != null) { + NBTTagCompound nbt = new NBTTagCompound(); + te.writeToNBT(nbt); + + nbt.removeTag("x"); + nbt.removeTag("y"); + nbt.removeTag("z"); + + nbtBlock.setTag("nbt", nbt); + + String itemKey = null; + if(nbt.hasKey("items")) itemKey = "items"; + if(nbt.hasKey("Items")) itemKey = "Items"; + + if(nbt.hasKey(itemKey)) { + NBTTagList items = nbt.getTagList(itemKey, NBT.TAG_COMPOUND); + for(int i = 0; i < items.tagCount(); i++) { + NBTTagCompound item = items.getCompoundTagAt(i); + short id = item.getShort("id"); + String name = GameRegistry.findUniqueIdentifierFor(Item.getItemById(id)).toString(); + + if(!itemPalette.containsKey(id)) { + int itemPaletteId = itemPalette.size(); + itemPalette.put(id, itemPaletteId); + + NBTTagCompound nbtItem = new NBTTagCompound(); + nbtItem.setShort("ID", id); + nbtItem.setString("Name", name); + + nbtItemPalette.appendTag(nbtItem); + } + } + } + } + + nbtBlocks.appendTag(nbtBlock); + } + } + } + + structure.setTag("blocks", nbtBlocks); + structure.setTag("palette", nbtPalette); + structure.setTag("itemPalette", nbtItemPalette); + + NBTTagList nbtSize = new NBTTagList(); + nbtSize.appendTag(new NBTTagInt(Math.abs(x1 - x2) + 1)); + nbtSize.appendTag(new NBTTagInt(Math.abs(y1 - y2) + 1)); + nbtSize.appendTag(new NBTTagInt(Math.abs(z1 - z2) + 1)); + structure.setTag("size", nbtSize); + + structure.setTag("entities", new NBTTagList()); + + try { + File structureDirectory = new File(Minecraft.getMinecraft().mcDataDir, "structures"); + structureDirectory.mkdir(); + + File structureFile = new File(structureDirectory, filename); + + CompressedStreamTools.writeCompressed(structure, new FileOutputStream(structureFile)); + } catch (Exception ex) { + MainRegistry.logger.warn("Failed to save NBT structure", ex); + } + } + + private void loadStructure(InputStream inputStream) { + try { + NBTTagCompound data = CompressedStreamTools.readCompressed(inputStream); + + + // GET SIZE (for offsetting to center) + size = parsePos(data.getTagList("size", NBT.TAG_INT)); + + + // PARSE BLOCK PALETTE + NBTTagList paletteList = data.getTagList("palette", NBT.TAG_COMPOUND); + BlockDefinition[] palette = new BlockDefinition[paletteList.tagCount()]; + + for(int i = 0; i < paletteList.tagCount(); i++) { + NBTTagCompound p = paletteList.getCompoundTagAt(i); + + String blockName = p.getString("Name"); + NBTTagCompound prop = p.getCompoundTag("Properties"); + + int meta = 0; + try { + meta = Integer.parseInt(prop.getString("meta")); + } catch(NumberFormatException ex) { + MainRegistry.logger.info("Failed to parse: " + prop.getString("meta")); + meta = 0; + } + + palette[i] = new BlockDefinition(blockName, meta); + } + + + // PARSE ITEM PALETTE (custom shite) + if(data.hasKey("itemPalette")) { + NBTTagList itemPaletteList = data.getTagList("itemPalette", NBT.TAG_COMPOUND); + itemPalette = new ArrayList<>(itemPaletteList.tagCount()); + + for(int i = 0; i < itemPaletteList.tagCount(); i++) { + NBTTagCompound p = itemPaletteList.getCompoundTagAt(i); + + short id = p.getShort("ID"); + String name = p.getString("Name"); + + itemPalette.add(new Pair<>(id, name)); + } + } else { + itemPalette = null; + } + + + // LOAD IN BLOCKS + NBTTagList blockData = data.getTagList("blocks", NBT.TAG_COMPOUND); + blockArray = new BlockState[size.x][size.y][size.z]; + + List connections = new ArrayList<>(); + + for(int i = 0; i < blockData.tagCount(); i++) { + NBTTagCompound block = blockData.getCompoundTagAt(i); + int state = block.getInteger("state"); + ThreeInts pos = parsePos(block.getTagList("pos", NBT.TAG_INT)); + + BlockState blockState = new BlockState(palette[state]); + + if(block.hasKey("nbt")) { + NBTTagCompound nbt = block.getCompoundTag("nbt"); + blockState.nbt = nbt; + + // Load in connection points for jigsaws + if(blockState.definition.block == ModBlocks.wand_jigsaw) { + if(toTopConnections == null) toTopConnections = new HashMap<>(); + if(toBottomConnections == null) toBottomConnections = new HashMap<>(); + if(toHorizontalConnections == null) toHorizontalConnections = new HashMap<>(); + + int selectionPriority = nbt.getInteger("selection"); + int placementPriority = nbt.getInteger("placement"); + ForgeDirection direction = ForgeDirection.getOrientation(nbt.getInteger("direction")); + String poolName = nbt.getString("pool"); + String ourName = nbt.getString("name"); + String targetName = nbt.getString("target"); + String replaceBlock = nbt.getString("block"); + int replaceMeta = nbt.getInteger("meta"); + boolean isRollable = nbt.getBoolean("roll"); + + JigsawConnection connection = new JigsawConnection(pos, direction, poolName, targetName, isRollable, selectionPriority, placementPriority); + + connections.add(connection); + + Map> toConnections = null; + if(direction == ForgeDirection.UP) { + toConnections = toTopConnections; + } else if(direction == ForgeDirection.DOWN) { + toConnections = toBottomConnections; + } else { + toConnections = toHorizontalConnections; + } + + List namedConnections = toConnections.computeIfAbsent(ourName, name -> new ArrayList<>()); + namedConnections.add(connection); + + if(!StructureConfig.debugStructures) { + blockState = new BlockState(new BlockDefinition(replaceBlock, replaceMeta)); + } + } + } + + blockArray[pos.x][pos.y][pos.z] = blockState; + } + + + // MAP OUT CONNECTIONS + PRIORITIES + if(connections.size() > 0) { + fromConnections = new ArrayList<>(); + + connections.sort((a, b) -> a.selectionPriority - b.selectionPriority); // sort by descending priority, highest first + + // Sort out our from connections, splitting into individual lists for each priority level + List innerList = null; + int currentPriority = 0; + for(JigsawConnection connection : connections) { + if(innerList == null || currentPriority != connection.selectionPriority) { + innerList = new ArrayList<>(); + fromConnections.add(innerList); + currentPriority = connection.selectionPriority; + } + + innerList.add(connection); + } + } + + + + isLoaded = true; + + } catch(Exception e) { + MainRegistry.logger.error("Exception reading NBT Structure format", e); + } finally { + try { + inputStream.close(); + } catch(IOException e) { + // hush + } + } + } + + private HashMap getWorldItemPalette() { + if(itemPalette == null) return null; + + HashMap worldItemPalette = new HashMap<>(); + + for(Pair entry : itemPalette) { + Item item = (Item)Item.itemRegistry.getObject(entry.getValue()); + + worldItemPalette.put(entry.getKey(), (short)Item.getIdFromItem(item)); + } + + return worldItemPalette; + } + + private TileEntity buildTileEntity(World world, Block block, HashMap worldItemPalette, NBTTagCompound nbt, int coordBaseMode) { + nbt = (NBTTagCompound)nbt.copy(); + + if(worldItemPalette != null) relinkItems(worldItemPalette, nbt); + + TileEntity te = TileEntity.createAndLoadEntity(nbt); + + if(te instanceof INBTTileEntityTransformable) { + ((INBTTileEntityTransformable) te).transformTE(world, coordBaseMode); + } + + return te; + } + + public void build(World world, int x, int y, int z) { + build(world, x, y, z, 0); + } + + public void build(World world, int x, int y, int z, int coordBaseMode) { + if(!isLoaded) { + MainRegistry.logger.info("NBTStructure is invalid"); + return; + } + + HashMap worldItemPalette = getWorldItemPalette(); + + boolean swizzle = coordBaseMode == 1 || coordBaseMode == 3; + x -= (swizzle ? size.z : size.x) / 2; + z -= (swizzle ? size.x : size.z) / 2; + + int maxX = size.x; + int maxZ = size.z; + + for(int bx = 0; bx < maxX; bx++) { + for(int bz = 0; bz < maxZ; bz++) { + int rx = rotateX(bx, bz, coordBaseMode) + x; + int rz = rotateZ(bx, bz, coordBaseMode) + z; + + for(int by = 0; by < size.y; by++) { + BlockState state = blockArray[bx][by][bz]; + if(state == null) continue; + + int ry = by + y; + + Block block = transformBlock(state.definition, null, world.rand); + int meta = coordBaseMode != 0 ? transformMeta(state.definition, coordBaseMode) : state.definition.meta; + + world.setBlock(rx, ry, rz, block, meta, 2); + + if(state.nbt != null) { + TileEntity te = buildTileEntity(world, block, worldItemPalette, state.nbt, coordBaseMode); + world.setTileEntity(rx, ry, rz, te); + } + } + } + } + } + + protected boolean build(World world, JigsawPiece piece, StructureBoundingBox totalBounds, StructureBoundingBox generatingBounds, int coordBaseMode) { + if(!isLoaded) { + MainRegistry.logger.info("NBTStructure is invalid"); + return false; + } + + HashMap worldItemPalette = getWorldItemPalette(); + + int sizeX = totalBounds.maxX - totalBounds.minX; + int sizeZ = totalBounds.maxZ - totalBounds.minZ; + + // voxel grid transforms can fuck you up + // you have my respect, vaer + int absMinX = Math.max(generatingBounds.minX - totalBounds.minX, 0); + int absMaxX = Math.min(generatingBounds.maxX - totalBounds.minX, sizeX); + int absMinZ = Math.max(generatingBounds.minZ - totalBounds.minZ, 0); + int absMaxZ = Math.min(generatingBounds.maxZ - totalBounds.minZ, sizeZ); + + // A check to see that we're actually inside the generating area at all + if(absMinX > sizeX || absMaxX < 0 || absMinZ > sizeZ || absMaxZ < 0) return true; + + int rotMinX = unrotateX(absMinX, absMinZ, coordBaseMode); + int rotMaxX = unrotateX(absMaxX, absMaxZ, coordBaseMode); + int rotMinZ = unrotateZ(absMinX, absMinZ, coordBaseMode); + int rotMaxZ = unrotateZ(absMaxX, absMaxZ, coordBaseMode); + + int minX = Math.min(rotMinX, rotMaxX); + int maxX = Math.max(rotMinX, rotMaxX); + int minZ = Math.min(rotMinZ, rotMaxZ); + int maxZ = Math.max(rotMinZ, rotMaxZ); + + for(int bx = minX; bx <= maxX; bx++) { + for(int bz = minZ; bz <= maxZ; bz++) { + int rx = rotateX(bx, bz, coordBaseMode) + totalBounds.minX; + int rz = rotateZ(bx, bz, coordBaseMode) + totalBounds.minZ; + int oy = piece.conformToTerrain ? world.getTopSolidOrLiquidBlock(rx, rz) + piece.heightOffset : totalBounds.minY; + + for(int by = 0; by < size.y; by++) { + BlockState state = blockArray[bx][by][bz]; + if(state == null) continue; + + int ry = by + oy; + + Block block = transformBlock(state.definition, piece.blockTable, world.rand); + int meta = coordBaseMode != 0 ? transformMeta(state.definition, coordBaseMode) : state.definition.meta; + + world.setBlock(rx, ry, rz, block, meta, 2); + + if(state.nbt != null) { + TileEntity te = buildTileEntity(world, block, worldItemPalette, state.nbt, coordBaseMode); + world.setTileEntity(rx, ry, rz, te); + } + } + } + } + + return true; + } + + // What a fucken mess, why even implement the IntArray NBT if ye aint gonna use it Moe Yang? + private ThreeInts parsePos(NBTTagList pos) { + NBTBase xb = (NBTBase)pos.tagList.get(0); + int x = ((NBTTagInt)xb).func_150287_d(); + NBTBase yb = (NBTBase)pos.tagList.get(1); + int y = ((NBTTagInt)yb).func_150287_d(); + NBTBase zb = (NBTBase)pos.tagList.get(2); + int z = ((NBTTagInt)zb).func_150287_d(); + + return new ThreeInts(x, y, z); + } + + // NON-STANDARD, items are serialized with IDs, which will differ from world to world! + // So our fixed exporter adds an itemPalette, please don't hunt me down for fucking with the spec + private void relinkItems(HashMap palette, NBTTagCompound nbt) { + NBTTagList items = null; + if(nbt.hasKey("items")) + items = nbt.getTagList("items", NBT.TAG_COMPOUND); + if(nbt.hasKey("Items")) + items = nbt.getTagList("Items", NBT.TAG_COMPOUND); + + if(items == null) return; + + for(int i = 0; i < items.tagCount(); i++) { + NBTTagCompound item = items.getCompoundTagAt(i); + item.setShort("id", palette.get(item.getShort("id"))); + } + } + + private Block transformBlock(BlockDefinition definition, Map blockTable, Random rand) { + if(blockTable != null && blockTable.containsKey(definition.block)) { + final BlockSelector selector = blockTable.get(definition.block); + selector.selectBlocks(rand, 0, 0, 0, false); // fuck the vanilla shit idc + return selector.func_151561_a(); + } + + if(definition.block instanceof INBTTransformable) return ((INBTTransformable) definition.block).transformBlock(definition.block); + + return definition.block; + } + + private int transformMeta(BlockDefinition definition, int coordBaseMode) { + // Our shit + if(definition.block instanceof INBTTransformable) return ((INBTTransformable) definition.block).transformMeta(definition.meta, coordBaseMode); + + // 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); + + return definition.meta; + } + + private int rotateX(int x, int z, int coordBaseMode) { + switch(coordBaseMode) { + case 1: return size.z - 1 - z; + case 2: return size.x - 1 - x; + case 3: return z; + default: return x; + } + } + + private int rotateZ(int x, int z, int coordBaseMode) { + switch(coordBaseMode) { + case 1: return x; + case 2: return size.z - 1 - z; + case 3: return size.x - 1 - x; + default: return z; + } + } + + private int unrotateX(int x, int z, int coordBaseMode) { + switch(coordBaseMode) { + case 3: return size.x - 1 - z; + case 2: return size.x - 1 - x; + case 1: return z; + default: return x; + } + } + + private int unrotateZ(int x, int z, int coordBaseMode) { + switch(coordBaseMode) { + case 3: return x; + case 2: return size.z - 1 - z; + case 1: return size.z - 1 - x; + default: return z; + } + } + + private static class BlockState { + + final BlockDefinition definition; + NBTTagCompound nbt; + + BlockState(BlockDefinition definition) { + this.definition = definition; + } + + } + + private static class BlockDefinition { + + final Block block; + final int meta; + + BlockDefinition(String name, int meta) { + Block block = Block.getBlockFromName(name); + if(block == null) block = Blocks.air; + + this.block = block; + this.meta = meta; + } + + } + + 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; + + // 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(); + } + + } + + // 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 { + + private final ThreeInts pos; + private final ForgeDirection dir; + + // what pool should we look through to find a connection + private final String poolName; + + // when we successfully find a pool, what connections in that jigsaw piece can we target + private final String targetName; + + private final boolean isRollable; + + private final int selectionPriority; + private final int placementPriority; + + private JigsawConnection(ThreeInts pos, ForgeDirection dir, String poolName, String targetName, boolean isRollable, int selectionPriority, int placementPriority) { + this.pos = pos; + this.dir = dir; + this.poolName = poolName; + this.targetName = targetName; + this.isRollable = isRollable; + this.selectionPriority = selectionPriority; + this.placementPriority = placementPriority; + } + + } + + public static class Component extends StructureComponent { + + JigsawPiece piece; + + int minHeight = 1; + int maxHeight = 128; + + boolean heightUpdated = false; + + int priority; // placement priority not yet implemented because selection priority is far more useful whatever + + // this is fucking hacky but we need a way to update ALL component bounds once a Y-level is determined + private Start parent; + + private JigsawConnection connectedFrom; + + public Component() {} + + public Component(SpawnCondition spawn, JigsawPiece piece, Random rand, int x, int z) { + this(spawn, piece, rand, x, 0, z, rand.nextInt(4)); + } + + public Component(SpawnCondition spawn, JigsawPiece piece, Random rand, int x, int y, int z, int coordBaseMode) { + super(0); + this.coordBaseMode = coordBaseMode; + this.piece = piece; + this.minHeight = spawn.minHeight; + this.maxHeight = spawn.maxHeight; + + switch(this.coordBaseMode) { + case 1: + case 3: + this.boundingBox = new StructureBoundingBox(x, y, z, x + piece.structure.size.z - 1, y + piece.structure.size.y - 1, z + piece.structure.size.x - 1); + break; + default: + this.boundingBox = new StructureBoundingBox(x, y, z, x + piece.structure.size.x - 1, y + piece.structure.size.y - 1, z + piece.structure.size.z - 1); + break; + } + } + + public Component connectedFrom(JigsawConnection connection) { + this.connectedFrom = connection; + return this; + } + + // Save to NBT + @Override + protected void func_143012_a(NBTTagCompound nbt) { + nbt.setString("piece", piece.name); + nbt.setInteger("min", minHeight); + nbt.setInteger("max", maxHeight); + nbt.setBoolean("hasHeight", heightUpdated); + } + + // Load from NBT + @Override + protected void func_143011_b(NBTTagCompound nbt) { + piece = jigsawMap.get(nbt.getString("piece")); + minHeight = nbt.getInteger("min"); + maxHeight = nbt.getInteger("max"); + heightUpdated = nbt.getBoolean("hasHeight"); + } + + @Override + public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { + if(piece == null) return false; + + // now we're in the world, update minY/maxY + if(!piece.conformToTerrain && !heightUpdated) { + int y = MathHelper.clamp_int(getAverageHeight(world, box) + piece.heightOffset, minHeight, maxHeight); + + if(!piece.alignToTerrain && parent != null) { + parent.offsetYHeight(y); + } else { + offsetYHeight(y); + } + } + + return piece.structure.build(world, piece, boundingBox, box, coordBaseMode); + } + + public void offsetYHeight(int y) { + boundingBox.minY += y; + boundingBox.maxY += y; + + heightUpdated = true; + } + + // Overrides to fix Mojang's fucked rotations which FLIP instead of rotating in two instances + // vaer being in the mines doing this the hard way for years was absolutely not for naught + @Override + protected int getXWithOffset(int x, int z) { + return boundingBox.minX + piece.structure.rotateX(x, z, coordBaseMode); + } + + @Override + protected int getYWithOffset(int y) { + return boundingBox.minY + y; + } + + @Override + protected int getZWithOffset(int x, int z) { + return boundingBox.minZ + piece.structure.rotateZ(x, z, coordBaseMode); + } + + private ForgeDirection rotateDir(ForgeDirection dir) { + if(dir == ForgeDirection.UP || dir == ForgeDirection.DOWN) return dir; + switch(coordBaseMode) { + default: return dir; + case 1: return dir.getRotation(ForgeDirection.UP); + case 2: return dir.getOpposite(); + case 3: return dir.getRotation(ForgeDirection.DOWN); + } + } + + private int getAverageHeight(World world, StructureBoundingBox box) { + int total = 0; + int iterations = 0; + + for(int z = box.minZ; z <= box.maxZ; z++) { + for(int x = box.minX; x <= box.maxX; x++) { + total += world.getTopSolidOrLiquidBlock(x, z); + iterations++; + } + } + + if(iterations == 0) + return 64; + + return total / iterations; + } + + private int getNextCoordBase(JigsawConnection fromConnection, JigsawConnection toConnection, Random rand) { + if(fromConnection.dir == ForgeDirection.DOWN || fromConnection.dir == ForgeDirection.UP) { + if(fromConnection.isRollable) return rand.nextInt(4); + return coordBaseMode; + } + + return directionOffsetToCoordBase(fromConnection.dir.getOpposite(), toConnection.dir); + } + + private int directionOffsetToCoordBase(ForgeDirection from, ForgeDirection to) { + for(int i = 0; i < 4; i++) { + if(from == to) return (i + coordBaseMode) % 4; + from = from.getRotation(ForgeDirection.DOWN); + } + return coordBaseMode; + } + + protected boolean hasIntersectionIgnoringSelf(LinkedList components, StructureBoundingBox box) { + for(StructureComponent component : components) { + if(component == this) continue; + if(component.getBoundingBox() == null) continue; + + if(component.getBoundingBox().intersectsWith(box)) return true; + } + + return false; + } + + } + + public static class Start extends StructureStart { + + public Start() {} + + @SuppressWarnings("unchecked") + public Start(World world, Random rand, SpawnCondition spawn, int chunkX, int chunkZ) { + super(chunkX, chunkZ); + + int x = chunkX << 4; + int z = chunkZ << 4; + + JigsawPiece startPiece = spawn.structure != null ? spawn.structure : spawn.pools.get(spawn.startPool).get(rand); + + Component startComponent = new Component(spawn, startPiece, rand, x, z); + startComponent.parent = this; + + components.add(startComponent); + + List queuedComponents = new ArrayList<>(); + if(spawn.structure == null) queuedComponents.add(startComponent); + + // Iterate through and build out all the components we intend to spawn + while(!queuedComponents.isEmpty()) { + final int i = rand.nextInt(queuedComponents.size()); + Component fromComponent = queuedComponents.remove(i); + + if(fromComponent.piece.structure.fromConnections == null) continue; + + boolean fallbacksOnly = this.components.size() >= spawn.sizeLimit; + + for(List unshuffledList : fromComponent.piece.structure.fromConnections) { + List connectionList = new ArrayList<>(unshuffledList); + Collections.shuffle(connectionList, rand); + + for(JigsawConnection fromConnection : connectionList) { + if(fromComponent.connectedFrom == fromConnection) continue; // if we already connected to this piece, don't process + + if(fallbacksOnly) { + String fallback = spawn.pools.get(fromConnection.poolName).fallback; + + if(fallback != null) { + Component fallbackComponent = buildNextComponent(rand, spawn, spawn.pools.get(fallback), fromComponent, fromConnection); + addComponent(fallbackComponent, fromConnection.placementPriority); + } + + continue; + } + + JigsawPool nextPool = spawn.getPool(fromConnection.poolName); + + Component nextComponent = null; + + // Iterate randomly through the pool, attempting each piece until one fits + while(nextPool.totalWeight > 0) { + nextComponent = buildNextComponent(rand, spawn, nextPool, fromComponent, fromConnection); + if(nextComponent != null && !fromComponent.hasIntersectionIgnoringSelf(components, nextComponent.getBoundingBox())) break; + nextComponent = null; + } + + if(nextComponent != null) { + addComponent(nextComponent, fromConnection.placementPriority); + queuedComponents.add(nextComponent); + } else { + // If we failed to fit anything in, grab something from the fallback pool, ignoring bounds check + if(nextPool.fallback != null) { + nextComponent = buildNextComponent(rand, spawn, spawn.pools.get(nextPool.fallback), fromComponent, fromConnection); + addComponent(nextComponent, fromConnection.placementPriority); // don't add to queued list, we don't want to try continue from fallback + } + } + } + } + } + + if(GeneralConfig.enableDebugMode) { + MainRegistry.logger.info("[Debug] Spawning NBT structure at: " + chunkX * 16 + ", " + chunkZ * 16); + String componentList = "[Debug] Components: "; + for(Object component : this.components) { + componentList += ((Component) component).piece.structure.name + " "; + } + MainRegistry.logger.info(componentList); + } + + updateBoundingBox(); + } + + @SuppressWarnings("unchecked") + private void addComponent(Component component, int placementPriority) { + components.add(component); + + component.parent = this; + component.priority = placementPriority; + } + + private Component buildNextComponent(Random rand, SpawnCondition spawn, JigsawPool pool, Component fromComponent, JigsawConnection fromConnection) { + JigsawPiece nextPiece = pool.get(rand); + if(nextPiece == null) return null; + + List connectionPool = getConnectionPool(nextPiece, fromConnection); + if(connectionPool == null) return null; + + JigsawConnection toConnection = connectionPool.get(rand.nextInt(connectionPool.size())); + + // The direction this component is extending towards in ABSOLUTE direction + ForgeDirection extendDir = fromComponent.rotateDir(fromConnection.dir); + + // Rotate our incoming piece to plug it in + int nextCoordBase = fromComponent.getNextCoordBase(fromConnection, toConnection, rand); + + // Set the starting point for the next structure to the location of the connector block + int nextX = fromComponent.getXWithOffset(fromConnection.pos.x, fromConnection.pos.z) + extendDir.offsetX; + int nextY = fromComponent.getYWithOffset(fromConnection.pos.y) + extendDir.offsetY; + int nextZ = fromComponent.getZWithOffset(fromConnection.pos.x, fromConnection.pos.z) + extendDir.offsetZ; + + // offset the starting point to the connecting point + nextX -= nextPiece.structure.rotateX(toConnection.pos.x, toConnection.pos.z, nextCoordBase); + nextY -= toConnection.pos.y; + nextZ -= nextPiece.structure.rotateZ(toConnection.pos.x, toConnection.pos.z, nextCoordBase); + + return new Component(spawn, nextPiece, rand, nextX, nextY, nextZ, nextCoordBase).connectedFrom(toConnection); + } + + private List getConnectionPool(JigsawPiece nextPiece, JigsawConnection fromConnection) { + if(fromConnection.dir == ForgeDirection.DOWN) { + return nextPiece.structure.toTopConnections.get(fromConnection.targetName); + } else if(fromConnection.dir == ForgeDirection.UP) { + return nextPiece.structure.toBottomConnections.get(fromConnection.targetName); + } + + return nextPiece.structure.toHorizontalConnections.get(fromConnection.targetName); + } + + // post loading, update parent reference for loaded components + @Override + public void func_143017_b(NBTTagCompound nbt) { + for(Object o : components) { + ((Component) o).parent = this; + } + } + + public void offsetYHeight(int y) { + for(Object o : components) { + Component component = (Component) o; + if(component.heightUpdated || component.piece.conformToTerrain || component.piece.alignToTerrain) continue; + component.offsetYHeight(y); + } + } + + } + + public static class GenStructure extends MapGenStructure { + + private SpawnCondition nextSpawn; + + public void generateStructures(World world, Random rand, IChunkProvider chunkProvider, int chunkX, int chunkZ) { + Block[] ablock = new Block[65536]; + + func_151539_a(chunkProvider, world, chunkX, chunkZ, ablock); + generateStructuresInChunk(world, rand, chunkX, chunkZ); + } + + @Override + public String func_143025_a() { + return "NBTStructures"; + } + + @Override + protected boolean canSpawnStructureAtCoords(int chunkX, int chunkZ) { + if(!weightedMap.containsKey(worldObj.provider.dimensionId)) return false; + + int x = chunkX; + int z = chunkZ; + + if(x < 0) x -= StructureConfig.structureMaxChunks - 1; + if(z < 0) z -= StructureConfig.structureMaxChunks - 1; + + x /= StructureConfig.structureMaxChunks; + z /= StructureConfig.structureMaxChunks; + rand.setSeed((long)x * 341873128712L + (long)z * 132897987541L + this.worldObj.getWorldInfo().getSeed() + (long)996996996 - worldObj.provider.dimensionId); + x *= StructureConfig.structureMaxChunks; + z *= StructureConfig.structureMaxChunks; + x += rand.nextInt(StructureConfig.structureMaxChunks - StructureConfig.structureMinChunks); + z += rand.nextInt(StructureConfig.structureMaxChunks - StructureConfig.structureMinChunks); + + if(chunkX == x && chunkZ == z) { + BiomeGenBase biome = this.worldObj.getWorldChunkManager().getBiomeGenAt(chunkX * 16 + 8, chunkZ * 16 + 8); + + nextSpawn = findSpawn(biome); + + return nextSpawn != null && (nextSpawn.pools != null || nextSpawn.start != null || nextSpawn.structure != null); + } + + return false; + } + + @Override + protected StructureStart getStructureStart(int chunkX, int chunkZ) { + if(nextSpawn.start != null) return nextSpawn.start.apply(new Quartet(this.worldObj, this.rand, chunkX, chunkZ)); + return new Start(this.worldObj, this.rand, nextSpawn, chunkX, chunkZ); + } + + private SpawnCondition findSpawn(BiomeGenBase biome) { + List spawnList = weightedMap.get(worldObj.provider.dimensionId); + + for(int i = 0; i < 64; i++) { + SpawnCondition spawn = spawnList.get(rand.nextInt(spawnList.size())); + if(spawn.isValid(biome)) return spawn; + } + + return null; + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/hbm/world/gen/NTMWorldGenerator.java b/src/main/java/com/hbm/world/gen/NTMWorldGenerator.java index 6fb9e7fd1..3d9306b28 100644 --- a/src/main/java/com/hbm/world/gen/NTMWorldGenerator.java +++ b/src/main/java/com/hbm/world/gen/NTMWorldGenerator.java @@ -1,8 +1,22 @@ package com.hbm.world.gen; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; 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 cpw.mods.fml.common.IWorldGenerator; import cpw.mods.fml.common.eventhandler.SubscribeEvent; @@ -10,125 +24,163 @@ import net.minecraft.block.Block; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.chunk.IChunkProvider; -import static net.minecraftforge.common.BiomeDictionary.*; +import net.minecraft.world.gen.structure.StructureComponent.BlockSelector; import net.minecraftforge.event.terraingen.InitMapGenEvent.EventType; import net.minecraftforge.event.terraingen.PopulateChunkEvent; -import static net.minecraftforge.event.terraingen.TerrainGen.*; +import net.minecraftforge.event.terraingen.TerrainGen; import net.minecraftforge.event.world.WorldEvent; public class NTMWorldGenerator implements IWorldGenerator { - private MapGenNTMFeatures scatteredFeatureGen = new MapGenNTMFeatures(); - + + boolean regTest = false; + + public NTMWorldGenerator() { + final List invalidBiomes = Arrays.asList(new BiomeGenBase[] {BiomeGenBase.ocean, BiomeGenBase.river, BiomeGenBase.frozenOcean, BiomeGenBase.frozenRiver, BiomeGenBase.deepOcean}); + + NBTStructure.registerStructure(0, new SpawnCondition() {{ + canSpawn = biome -> !invalidBiomes.contains(biome); + start = d -> new MapGenNTMFeatures.Start(d.getW(), d.getX(), d.getY(), d.getZ()); + spawnWeight = 14; + }}); + + NBTStructure.registerStructure(0, new SpawnCondition() {{ + canSpawn = biome -> !invalidBiomes.contains(biome); + start = d -> new BunkerStart(d.getW(), d.getX(), d.getY(), d.getZ()); + spawnWeight = 1; + }}); + + Map bricks = new HashMap() {{ + put(ModBlocks.meteor_brick, new MeteorBricks()); + }}; + Map crates = new HashMap() {{ + put(ModBlocks.meteor_brick, new MeteorBricks()); + put(ModBlocks.crate, new SupplyCrates()); + put(ModBlocks.meteor_spawner, new CrabSpawners()); + }}; + Map ooze = new HashMap() {{ + put(ModBlocks.meteor_brick, new MeteorBricks()); + put(ModBlocks.concrete_colored, new GreenOoze()); + }}; + + NBTStructure.registerStructure(0, new SpawnCondition() {{ + minHeight = 32; + maxHeight = 32; + sizeLimit = 128; + canSpawn = biome -> biome.rootHeight >= 0; + startPool = "start"; + pools = new HashMap() {{ + put("start", new JigsawPool() {{ + add(new JigsawPiece("meteor_core", StructureManager.meteor_core) {{ blockTable = bricks; }}, 1); + }}); + put("spike", new JigsawPool() {{ + add(new JigsawPiece("meteor_spike", StructureManager.meteor_spike) {{ heightOffset = -3; conformToTerrain = true; }}, 1); + }}); + put("default", new JigsawPool() {{ + add(new JigsawPiece("meteor_corner", StructureManager.meteor_corner) {{ blockTable = bricks; }}, 2); + add(new JigsawPiece("meteor_t", StructureManager.meteor_t) {{ blockTable = bricks; }}, 3); + add(new JigsawPiece("meteor_stairs", StructureManager.meteor_stairs) {{ blockTable = bricks; }}, 1); + add(new JigsawPiece("meteor_room_base_thru", StructureManager.meteor_room_base_thru) {{ blockTable = bricks; }}, 3); + add(new JigsawPiece("meteor_room_base_end", StructureManager.meteor_room_base_end) {{ blockTable = bricks; }}, 4); + fallback = "fallback"; + }}); + put("10room", new JigsawPool() {{ + add(new JigsawPiece("meteor_room_basic", StructureManager.meteor_room_basic) {{ blockTable = bricks; }}, 1); + add(new JigsawPiece("meteor_room_balcony", StructureManager.meteor_room_balcony) {{ blockTable = bricks; }}, 1); + add(new JigsawPiece("meteor_room_dragon", StructureManager.meteor_room_dragon) {{ blockTable = bricks; }}, 1); + add(new JigsawPiece("meteor_room_ladder", StructureManager.meteor_room_ladder) {{ blockTable = bricks; }}, 1); + add(new JigsawPiece("meteor_room_ooze", StructureManager.meteor_room_ooze) {{ blockTable = ooze; }}, 1); + add(new JigsawPiece("meteor_room_split", StructureManager.meteor_room_split) {{ blockTable = bricks; }}, 1); + add(new JigsawPiece("meteor_room_stairs", StructureManager.meteor_room_stairs) {{ blockTable = bricks; }}, 1); + add(new JigsawPiece("meteor_room_triple", StructureManager.meteor_room_triple) {{ blockTable = bricks; }}, 1); + fallback = "roomback"; + }}); + put("3x3loot", new JigsawPool() {{ + add(new JigsawPiece("meteor_3_bale", StructureManager.meteor_3_bale), 1); + add(new JigsawPiece("meteor_3_blank", StructureManager.meteor_3_blank), 1); + add(new JigsawPiece("meteor_3_block", StructureManager.meteor_3_block), 1); + add(new JigsawPiece("meteor_3_crab", StructureManager.meteor_3_crab), 1); + add(new JigsawPiece("meteor_3_crab_tesla", StructureManager.meteor_3_crab_tesla), 1); + add(new JigsawPiece("meteor_3_crate", StructureManager.meteor_3_crate), 1); + add(new JigsawPiece("meteor_3_dirt", StructureManager.meteor_3_dirt), 1); + add(new JigsawPiece("meteor_3_lead", StructureManager.meteor_3_lead), 1); + add(new JigsawPiece("meteor_3_ooze", StructureManager.meteor_3_ooze), 1); + add(new JigsawPiece("meteor_3_pillar", StructureManager.meteor_3_pillar), 1); + add(new JigsawPiece("meteor_3_star", StructureManager.meteor_3_star), 1); + add(new JigsawPiece("meteor_3_tesla", StructureManager.meteor_3_tesla), 1); + add(new JigsawPiece("meteor_3_book", StructureManager.meteor_3_book), 1); + add(new JigsawPiece("meteor_3_mku", StructureManager.meteor_3_mku), 1); + add(new JigsawPiece("meteor_3_statue", StructureManager.meteor_3_statue), 1); + }}); + put("headloot", new JigsawPool() {{ + add(new JigsawPiece("meteor_dragon_chest", StructureManager.meteor_dragon_chest) {{ blockTable = crates; }}, 1); + add(new JigsawPiece("meteor_dragon_tesla", StructureManager.meteor_dragon_tesla) {{ blockTable = crates; }}, 1); + add(new JigsawPiece("meteor_dragon_trap", StructureManager.meteor_dragon_trap) {{ blockTable = crates; }}, 1); + add(new JigsawPiece("meteor_dragon_crate_crab", StructureManager.meteor_dragon_crate_crab) {{ blockTable = crates; }}, 1); + }}); + put("fallback", new JigsawPool() {{ + add(new JigsawPiece("meteor_fallback", StructureManager.meteor_fallback) {{ blockTable = bricks; }}, 1); + }}); + put("roomback", new JigsawPool() {{ + add(new JigsawPiece("meteor_room_fallback", StructureManager.meteor_room_fallback) {{ blockTable = bricks; }}, 1); + }}); + }}; + }}); + } + + private NBTStructure.GenStructure nbtGen = new NBTStructure.GenStructure(); + private final Random rand = new Random(); //A central random, used to cleanly generate our stuff without affecting vanilla or modded seeds. - + /** Inits all MapGen upon the loading of a new world. Hopefully clears out structureMaps and structureData when a different world is loaded. */ @SubscribeEvent public void onLoad(WorldEvent.Load event) { - scatteredFeatureGen = (MapGenNTMFeatures) getModdedMapGen(new MapGenNTMFeatures(), EventType.CUSTOM); - + nbtGen = (NBTStructure.GenStructure) TerrainGen.getModdedMapGen(new NBTStructure.GenStructure(), EventType.CUSTOM); + hasPopulationEvent = false; } - + /** Called upon the initial population of a chunk. Called in the pre-population event first; called again if pre-population didn't occur (flatland) */ private void setRandomSeed(World world, int chunkX, int chunkZ) { - rand.setSeed(world.getSeed()); + rand.setSeed(world.getSeed() + world.provider.dimensionId); final long i = rand.nextLong() / 2L * 2L + 1L; final long j = rand.nextLong() / 2L * 2L + 1L; rand.setSeed((long)chunkX * i + (long)chunkZ * j ^ world.getSeed()); } - + /* * Pre-population Events / Structure Generation * Used to generate structures without unnecessary intrusion by biome decoration, like trees. */ - + private boolean hasPopulationEvent = false; // Does the given chunkGenerator have a population event? If not (flatlands), default to using generate. - + @SubscribeEvent public void generateStructures(PopulateChunkEvent.Pre event) { - setRandomSeed(event.world, event.chunkX, event.chunkZ); //Set random for population down the line. hasPopulationEvent = true; - + if(StructureConfig.enableStructures == 0) return; if(StructureConfig.enableStructures == 2 && !event.world.getWorldInfo().isMapFeaturesEnabled()) return; - - switch (event.world.provider.dimensionId) { - case -1: - break; - case 0: - generateOverworldStructures(event.world, event.chunkProvider, event.chunkX, event.chunkZ); - break; - case 1: - break; - } + + setRandomSeed(event.world, event.chunkX, event.chunkZ); //Set random for population down the line. + + nbtGen.generateStructures(event.world, rand, event.chunkProvider, event.chunkX, event.chunkZ); } - - protected void generateOverworldStructures(World world, IChunkProvider chunkProvider, int chunkX, int chunkZ) { - Block[] ablock = new Block[65536]; //ablock isn't actually used for anything in MapGenStructure - - this.scatteredFeatureGen.func_151539_a(chunkProvider, world, chunkX, chunkZ, ablock); - this.scatteredFeatureGen.generateStructuresInChunk(world, rand, chunkX, chunkZ); - } - + /* * Post-Vanilla / Modded Generation * Used to generate features that don't care about intrusions (ores, craters, caves, etc.) */ - + @Override - public void generate(Random rand, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { - - switch (world.provider.dimensionId) { - case -1: - generateNether(world, rand, chunkGenerator, chunkX, chunkZ); break; - case 0: - generateSurface(world, rand, chunkGenerator, chunkProvider, chunkX, chunkZ); break; - case 1: - generateEnd(world, rand, chunkGenerator, chunkX, chunkZ); break; - } - } - - private void generateNether(World world, Random rand, IChunkProvider chunkGenerator, int chunkX, int chunkZ) { } - - /* Overworld Generation */ - - private void generateSurface(World world, Random rand, IChunkProvider chunkGenerator, IChunkProvider chunkProvider, int chunkX, int chunkZ) { - if(!hasPopulationEvent) { //If we've failed to generate any structures (flatlands) - setRandomSeed(world, chunkX, chunkZ); //Reset the random seed to compensate - - boolean enableStructures = world.getWorldInfo().isMapFeaturesEnabled(); - if(StructureConfig.enableStructures == 1) enableStructures = true; - if(StructureConfig.enableStructures == 0) enableStructures = false; + public void generate(Random unusedRandom, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { + if(hasPopulationEvent) return; //If we've failed to generate any structures (flatlands) - if(enableStructures) generateOverworldStructures(world, chunkGenerator, chunkX, chunkZ); //Do it through the post-population generation directly - } - - /* biome dictionary my beloved <3 - * no check for tom here because the event handler already checks for decoration events, + this way they won't become permanently extinct. - */ - - /* Biome check, followed by chance, followed by event (for compat, both intra- and inter- (in the case of Tom). */ - - + if(StructureConfig.enableStructures == 0) return; + if(StructureConfig.enableStructures == 2 && !world.getWorldInfo().isMapFeaturesEnabled()) return; + + setRandomSeed(world, chunkX, chunkZ); //Reset the random seed to compensate + + nbtGen.generateStructures(world, rand, chunkProvider, chunkX, chunkZ); } - private void generateEnd(World world, Random rand, IChunkProvider chunkGenerator, int chunkX, int chunkZ) { } - - /** Utility method for biome checking multiple types exclusively. Not sure why it wasn't already present. */ - public static boolean isBiomeOfTypes(BiomeGenBase biome, Type... types) { //If new biomes are implemented, move this to any biome-related utility class. - for(Type type : types) { - if(!isBiomeOfType(biome, type)) return false; - } - - return true; - } - - /** utility method, same as above but inclusive. useful for catch-alls, like the dirty glass structures have */ - public static boolean doesBiomeHaveTypes(BiomeGenBase biome, Type... types) { - for(Type type : types) { - if(isBiomeOfType(biome, type)) return true; - } - - return false; - } } \ No newline at end of file diff --git a/src/main/java/com/hbm/world/gen/component/Component.java b/src/main/java/com/hbm/world/gen/component/Component.java index 0a652a6eb..80d85bcfd 100644 --- a/src/main/java/com/hbm/world/gen/component/Component.java +++ b/src/main/java/com/hbm/world/gen/component/Component.java @@ -12,6 +12,7 @@ import com.hbm.tileentity.machine.TileEntityLockableBase; import net.minecraft.block.Block; import net.minecraft.block.material.Material; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; @@ -27,19 +28,19 @@ abstract public class Component extends StructureComponent { /** Average height (Presumably stands for height position) */ protected int hpos = -1; - + protected Component() { super(0); } - + protected Component(int componentType) { super(componentType); } - + protected Component(Random rand, int minX, int minY, int minZ, int maxX, int maxY, int maxZ ) { super(0); this.coordBaseMode = rand.nextInt(4); - + switch(this.coordBaseMode) { case 0: this.boundingBox = new StructureBoundingBox(minX, minY, minZ, minX + maxX, minY + maxY, minZ + maxZ); @@ -55,25 +56,25 @@ abstract public class Component extends StructureComponent { break; default: this.boundingBox = new StructureBoundingBox(minX, minY, minZ, minX + maxX, minY + maxY, minZ + maxZ); - + } } - + /** Set to NBT */ protected void func_143012_a(NBTTagCompound nbt) { nbt.setInteger("HPos", this.hpos); } - + /** Get from NBT */ protected void func_143011_b(NBTTagCompound nbt) { this.hpos = nbt.getInteger("HPos"); } - + protected boolean setAverageHeight(World world, StructureBoundingBox box, int y) { - + int total = 0; int iterations = 0; - + for(int z = this.boundingBox.minZ; z <= this.boundingBox.maxZ; z++) { for(int x = this.boundingBox.minX; x <= this.boundingBox.maxX; x++) { if(box.isVecInside(x, y, z)) { @@ -82,20 +83,20 @@ abstract public class Component extends StructureComponent { } } } - + if(iterations == 0) return false; - + this.hpos = total / iterations; //finds mean of every block in bounding box this.boundingBox.offset(0, this.hpos - this.boundingBox.minY, 0); return true; } - + protected static int getAverageHeight(World world, StructureBoundingBox area, StructureBoundingBox box, int y) { - + int total = 0; int iterations = 0; - + for(int z = area.minZ; z <= area.maxZ; z++) { for(int x = area.minX; x <= area.maxX; x++) { if(box.isVecInside(x, y, z)) { @@ -104,19 +105,19 @@ abstract public class Component extends StructureComponent { } } } - + if(iterations == 0) return -1; - + return total / iterations; } - + public int getCoordMode() { return this.coordBaseMode; } - + /** Metadata for Decoration Methods **/ - + /** * Gets metadata for rotatable pillars. * @param metadata (First two digits are equal to block metadata, other two are equal to orientation @@ -125,10 +126,10 @@ abstract public class Component extends StructureComponent { protected int getPillarMeta(int metadata) { if(this.coordBaseMode % 2 != 0 && this.coordBaseMode != -1) metadata = metadata ^ 12; - + return metadata; } - + /** * Gets metadata for rotatable DecoBlock * honestly i don't remember how i did this and i'm scared to optimize it because i fail to see any reasonable patterns like the pillar @@ -168,14 +169,14 @@ abstract public class Component extends StructureComponent { } return 0; } - + /** * Get orientation-offset metadata for BlockDecoModel; also suitable for trapdoors * @param metadata (0 for facing North, 1 for facing South, 2 for facing West, 3 for facing East) */ protected int getDecoModelMeta(int metadata) { //N: 0b00, S: 0b01, W: 0b10, E: 0b11 - + switch(this.coordBaseMode) { default: //South break; @@ -198,12 +199,12 @@ abstract public class Component extends StructureComponent { //genuinely like. why did i do that return metadata << 2; //To accommodate for BlockDecoModel's shift in the rotation bits; otherwise, simply bit-shift right and or any non-rotation meta after } - + //works for crts, toasters, and anything that follows mc's cardinal dirs. S: 0, W: 1, N: 2, E: 3 protected int getCRTMeta(int meta) { return (meta + this.coordBaseMode) % 4; } - + /** * Gets orientation-adjusted meta for stairs. * 0 = West, 1 = East, 2 = North, 3 = South @@ -228,11 +229,11 @@ abstract public class Component extends StructureComponent { metadata = metadata ^ 2; break; } - + return metadata; } - - /* + + /* * Assuming door is on opposite side of block from direction: East: 0, South: 1, West: 2, North: 3
* Doors cleverly take advantage of the use of two blocks to get around the 16 value limit on metadata, with the top and bottom blocks essentially relying on eachother for everything.
*
  • The 4th bit (0b1000 or 8) indicates whether it is the top block: on for yes, off for no. @@ -245,9 +246,9 @@ abstract public class Component extends StructureComponent { int posX = this.getXWithOffset(featureX, featureZ); int posY = this.getYWithOffset(featureY); int posZ = this.getZWithOffset(featureX, featureZ); - + if(!box.isVecInside(posX, posY, posZ)) return; - + switch(this.coordBaseMode) { default: //South break; @@ -258,11 +259,11 @@ abstract public class Component extends StructureComponent { case 3: //East dirMeta = (dirMeta + 3) % 4; break; //fuck you modulo } - + //hee hoo int metaTop = opensRight ? 0b1001 : 0b1000; int metaBottom = dirMeta | (isOpen ? 0b100 : 0); - + if(world.doesBlockHaveSolidTopSurface(world, posX, posY - 1, posZ)) { world.setBlock(posX, posY, posZ, door, metaBottom, 2); world.setBlock(posX, posY + 1, posZ, door, metaTop, 2); @@ -273,9 +274,9 @@ abstract public class Component extends StructureComponent { int posX = this.getXWithOffset(featureX, featureZ); int posY = this.getYWithOffset(featureY); int posZ = this.getZWithOffset(featureX, featureZ); - + if(!box.isVecInside(posX, posY, posZ)) return; - + if(dirMeta <= 0 || dirMeta >= 7) { //levers suck ass switch(this.coordBaseMode) { case 1: case 3: //west / east @@ -289,10 +290,10 @@ abstract public class Component extends StructureComponent { } else { dirMeta = getButtonMeta(dirMeta); } - + world.setBlock(posX, posY, posZ, Blocks.lever, on ? dirMeta | 8 : dirMeta, 2); } - + /** pain. works for side-facing levers as well */ protected int getButtonMeta(int dirMeta) { switch(this.coordBaseMode) { //are you ready for the pain? @@ -310,12 +311,12 @@ abstract public class Component extends StructureComponent { return dirMeta; } } - + /**N:0 W:1 S:2 E:3 */ protected void placeBed(World world, StructureBoundingBox box, int meta, int featureX, int featureY, int featureZ) { int xOffset = 0; int zOffset = 0; - + switch(meta & 3) { default: zOffset = 1; break; @@ -326,7 +327,7 @@ abstract public class Component extends StructureComponent { case 3: xOffset = 1; break; } - + switch(this.coordBaseMode) { default: //S break; @@ -337,11 +338,11 @@ abstract public class Component extends StructureComponent { case 3: //E meta = (meta - 1) % 4; break; } - + placeBlockAtCurrentPosition(world, Blocks.bed, meta, featureX, featureY, featureZ, box); placeBlockAtCurrentPosition(world, Blocks.bed, meta + 8, featureX + xOffset, featureY, featureZ + zOffset, box); } - + /**Tripwire Hook: S:0 W:1 N:2 E:3 */ protected int getTripwireMeta(int metadata) { switch(this.coordBaseMode) { @@ -355,10 +356,10 @@ abstract public class Component extends StructureComponent { return (metadata - 1) % 4; } } - - + + /** Loot Methods **/ - + /** * it feels disgusting to make a method with this many parameters but fuck it, it's easier * @return TE implementing IInventory with randomized contents @@ -366,29 +367,29 @@ abstract public class Component extends StructureComponent { protected boolean generateInvContents(World world, StructureBoundingBox box, Random rand, Block block, int featureX, int featureY, int featureZ, WeightedRandomChestContent[] content, int amount) { return generateInvContents(world, box, rand, block, 0, featureX, featureY, featureZ, content, amount); } - + //TODO: explore min / max item generations: e.g., between 3 and 5 separate items are generated protected boolean generateInvContents(World world, StructureBoundingBox box, Random rand, Block block, int meta, int featureX, int featureY, int featureZ, WeightedRandomChestContent[] content, int amount) { int posX = this.getXWithOffset(featureX, featureZ); int posY = this.getYWithOffset(featureY); int posZ = this.getZWithOffset(featureX, featureZ); - + if(!box.isVecInside(posX, posY, posZ) || world.getBlock(posX, posY, posZ) == block) //replacement for hasPlacedLoot checks return true; - + this.placeBlockAtCurrentPosition(world, block, meta, featureX, featureY, featureZ, box); IInventory inventory = (IInventory)world.getTileEntity(posX, posY, posZ); - + if(inventory != null) { amount = (int)Math.floor(amount * StructureConfig.lootAmountFactor); WeightedRandomChestContent.generateChestContents(rand, content, inventory, amount < 1 ? 1 : amount); return true; } - + return false; } - - + + /** * Block TE MUST extend TileEntityLockableBase, otherwise this will not work and crash! * @return TE implementing IInventory and extending TileEntityLockableBase with randomized contents + lock @@ -397,48 +398,48 @@ abstract public class Component extends StructureComponent { WeightedRandomChestContent[] content, int amount, double mod) { return generateLockableContents(world, box, rand, block, 0, featureX, featureY, featureZ, content, amount, mod); } - + protected boolean generateLockableContents(World world, StructureBoundingBox box, Random rand, Block block, int meta, int featureX, int featureY, int featureZ, WeightedRandomChestContent[] content, int amount, double mod) { int posX = this.getXWithOffset(featureX, featureZ); int posY = this.getYWithOffset(featureY); int posZ = this.getZWithOffset(featureX, featureZ); - + if(!box.isVecInside(posX, posY, posZ) || world.getBlock(posX, posY, posZ) == block) //replacement for hasPlacedLoot checks return false; - + this.placeBlockAtCurrentPosition(world, block, meta, featureX, featureY, featureZ, box); TileEntity tile = world.getTileEntity(posX, posY, posZ); TileEntityLockableBase lock = (TileEntityLockableBase) tile; IInventory inventory = (IInventory) tile; - + if(inventory != null && lock != null) { amount = (int)Math.floor(amount * StructureConfig.lootAmountFactor); WeightedRandomChestContent.generateChestContents(rand, content, inventory, amount < 1 ? 1 : amount); - + lock.setPins(rand.nextInt(999) + 1); lock.setMod(mod); lock.lock(); return true; } - + return false; } - + protected void generateLoreBook(World world, StructureBoundingBox box, int featureX, int featureY, int featureZ, int slot, ItemStack stack) { //kept for compat int posX = this.getXWithOffset(featureX, featureZ); int posY = this.getYWithOffset(featureY); int posZ = this.getZWithOffset(featureX, featureZ); - + if(!box.isVecInside(posX, posY, posZ)) return; - + IInventory inventory = (IInventory) world.getTileEntity(posX, posY, posZ); - + if(inventory != null) { inventory.setInventorySlotContents(slot, stack); } } - + /** * Places random bobblehead with a randomized orientation at specified location */ @@ -446,71 +447,71 @@ abstract public class Component extends StructureComponent { int posX = this.getXWithOffset(featureX, featureZ); int posY = this.getYWithOffset(featureY); int posZ = this.getZWithOffset(featureX, featureZ); - + placeBlockAtCurrentPosition(world, ModBlocks.bobblehead, rand.nextInt(16), featureX, featureY, featureZ, box); TileEntityBobble bobble = (TileEntityBobble) world.getTileEntity(posX, posY, posZ); - + if(bobble != null) { bobble.type = BobbleType.values()[rand.nextInt(BobbleType.values().length - 1) + 1]; bobble.markDirty(); } } - + /** Block Placement Utility Methods **/ - + /** * Places blocks underneath location until reaching a solid block; good for foundations */ protected void placeFoundationUnderneath(World world, Block placeBlock, int meta, int minX, int minZ, int maxX, int maxZ, int featureY, StructureBoundingBox box) { - + for(int featureX = minX; featureX <= maxX; featureX++) { for(int featureZ = minZ; featureZ <= maxZ; featureZ++) { int posX = this.getXWithOffset(featureX, featureZ); int posY = this.getYWithOffset(featureY); int posZ = this.getZWithOffset(featureX, featureZ); - + if(box.isVecInside(posX, posY, posZ)) { Block block = world.getBlock(posX, posY, posZ); int brake = 0; - - while ((world.isAirBlock(posX, posY, posZ) || - !block.getMaterial().isSolid() || - (block.isFoliage(world, posX, posY, posZ) || block.getMaterial() == Material.leaves)) && + + while ((world.isAirBlock(posX, posY, posZ) || + !block.getMaterial().isSolid() || + (block.isFoliage(world, posX, posY, posZ) || block.getMaterial() == Material.leaves)) && posY > 1 && brake <= 15) { world.setBlock(posX, posY, posZ, placeBlock, meta, 2); block = world.getBlock(posX, --posY, posZ); - + brake++; } } } } } - + /** * Places specified blocks on top of pre-existing blocks in a given area, up to a certain height. Does NOT place blocks on top of liquids. * Useful for stuff like fences and walls most likely. */ protected void placeBlocksOnTop(World world, StructureBoundingBox box, Block block, int minX, int minZ, int maxX, int maxZ, int height) { - + for(int x = minX; x <= maxX; x++) { for(int z = minZ; z <= maxZ; z++) { int posX = this.getXWithOffset(x, z); int posZ = this.getZWithOffset(x, z); int topHeight = world.getTopSolidOrLiquidBlock(posX, posZ); - + if(!world.getBlock(posX, topHeight, posZ).getMaterial().isLiquid()) { - + for(int i = 0; i < height; i++) { int posY = topHeight + i; - + world.setBlock(posX, posY, posZ, block, 0, 2); } } } } } - + /** getXWithOffset & getZWithOffset Methods that are actually fixed **/ //Turns out, this entire time every single minecraft structure is mirrored instead of rotated when facing East and North //Also turns out, it's a scarily easy fix that they somehow didn't see *entirely* @@ -529,7 +530,7 @@ abstract public class Component extends StructureComponent { return x; } } - + @Override public int getZWithOffset(int x, int z) { switch(this.coordBaseMode) { @@ -545,46 +546,46 @@ abstract public class Component extends StructureComponent { return z; } } - + /** Methods that are actually optimized, including ones that cut out replaceBlock and onlyReplace functionality when it's redundant. */ protected void fillWithAir(World world, StructureBoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { //TODO these could technically be optimized a bit more. probably won't do anything but worth - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); - + world.setBlock(posX, posY, posZ, Blocks.air, 0, 2); } } } } } - + @Override protected void fillWithBlocks(World world, StructureBoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, Block block, Block replaceBlock, boolean onlyReplace) { - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); - + if(!onlyReplace || world.getBlock(posX, posY, posZ).getMaterial() != Material.air) { if(x != minX && x != maxX && y != minY && y != maxY && z != minZ && z != maxZ) world.setBlock(posX, posY, posZ, replaceBlock, 0, 2); @@ -596,49 +597,49 @@ abstract public class Component extends StructureComponent { } } } - + protected void fillWithBlocks(World world, StructureBoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, Block block) { - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); - + world.setBlock(posX, posY, posZ, block, 0, 2); } } } } } - + @Override protected void fillWithMetadataBlocks(World world, StructureBoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, Block block, int meta, Block replaceBlock, int replaceMeta, boolean onlyReplace) { - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); - + if(!onlyReplace || world.getBlock(posX, posY, posZ).getMaterial() != Material.air) { if(x != minX && x != maxX && y != minY && y != maxY && z != minZ && z != maxZ) world.setBlock(posX, posY, posZ, replaceBlock, replaceMeta, 2); - else + else world.setBlock(posX, posY, posZ, block, meta, 2); } } @@ -646,45 +647,45 @@ abstract public class Component extends StructureComponent { } } } - + protected void fillWithMetadataBlocks(World world, StructureBoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, Block block, int meta) { - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); - + world.setBlock(posX, posY, posZ, block, meta, 2); } } } } } - + @Override protected void fillWithRandomizedBlocks(World world, StructureBoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, boolean onlyReplace, Random rand, BlockSelector selector) { - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); - + if(!onlyReplace || world.getBlock(posX, posY, posZ).getMaterial() != Material.air) { selector.selectBlocks(rand, posX, posY, posZ, x == minX || x == maxX || y == minY || y == maxY || z == minZ || z == maxZ); world.setBlock(posX, posY, posZ, selector.func_151561_a(), selector.getSelectedBlockMetaData(), 2); @@ -696,16 +697,16 @@ abstract public class Component extends StructureComponent { } //TODO replace the shitty block selector with something else. probably a lambda that returns a metablock for convenience protected void fillWithRandomizedBlocks(World world, StructureBoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, Random rand, BlockSelector selector) { //so i don't have to replace shit - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); @@ -717,19 +718,19 @@ abstract public class Component extends StructureComponent { } } } - + //stairs and shit protected void fillWithRandomizedBlocksMeta(World world, StructureBoundingBox box, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, Random rand, BlockSelector selector, int meta) { - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); @@ -741,23 +742,23 @@ abstract public class Component extends StructureComponent { } } } - + @Override protected void randomlyFillWithBlocks(World world, StructureBoundingBox box, Random rand, float randLimit, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, Block block, Block replaceBlock, boolean onlyReplace) { - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); - + if(rand.nextFloat() <= randLimit && (!onlyReplace || world.getBlock(posX, posY, posZ).getMaterial() != Material.air)) { if(x != minX && x != maxX && y != minY && y != maxY && z != minZ && z != maxZ) world.setBlock(posX, posY, posZ, replaceBlock, 0, 2); @@ -769,22 +770,22 @@ abstract public class Component extends StructureComponent { } } } - + protected void randomlyFillWithBlocks(World world, StructureBoundingBox box, Random rand, float randLimit, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, Block block) { - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); - + if(rand.nextFloat() <= randLimit) world.setBlock(posX, posY, posZ, block, 0, 2); } @@ -792,22 +793,22 @@ abstract public class Component extends StructureComponent { } } } - + protected void randomlyFillWithBlocks(World world, StructureBoundingBox box, Random rand, float randLimit, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, Block block, int meta) { - + if(getYWithOffset(minY) < box.minY || getYWithOffset(maxY) > box.maxY) return; - + for(int x = minX; x <= maxX; x++) { - + for(int z = minZ; z <= maxZ; z++) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); - + if(posX >= box.minX && posX <= box.maxX && posZ >= box.minZ && posZ <= box.maxZ) { for(int y = minY; y <= maxY; y++) { int posY = getYWithOffset(y); - + if(rand.nextFloat() <= randLimit) world.setBlock(posX, posY, posZ, block, meta, 2); } @@ -815,7 +816,7 @@ abstract public class Component extends StructureComponent { } } } - + protected ForgeDirection getDirection(ForgeDirection dir) { switch(coordBaseMode) { default: //South @@ -828,7 +829,7 @@ abstract public class Component extends StructureComponent { return dir.getRotation(ForgeDirection.DOWN); } } - + /** Sets the core block for a BlockDummyable multiblock. WARNING: Does not take {@link com.hbm.blocks.BlockDummyable#getDirModified(ForgeDirection)} or {@link com.hbm.blocks.BlockDummyable#getMetaForCore(World, int, int, int, EntityPlayer, int)} * into account yet! This will be changed as it comes up!
    * For BlockDummyables, 'dir' always faces the player, being the opposite of the player's direction. This is already taken into account. */ @@ -836,47 +837,47 @@ abstract public class Component extends StructureComponent { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); int posY = getYWithOffset(y); - + if(!box.isVecInside(posX, posY, posZ)) return; - + if(dir == null) dir = ForgeDirection.NORTH; - + dir = getDirection(dir.getOpposite()); world.setBlock(posX, posY, posZ, block, dir.ordinal() + BlockDummyable.offset, 2); } - + //always set the core block first /** StructureComponent-friendly method for {@link com.hbm.handler.MultiblockHandlerXR#fillSpace(World, int, int, int, int[], Block, ForgeDirection)}. Prevents runoff outside of the provided bounding box.
    * For BlockDummyables, 'dir' always faces the player, being the opposite of the player's direction. This is already taken into account. */ protected void fillSpace(World world, StructureBoundingBox box, int x, int y, int z, int[] dim, Block block, ForgeDirection dir) { - + if(getYWithOffset(y - dim[1]) < box.minY || getYWithOffset(y + dim[0]) > box.maxY) //the BlockDummyable will be fucked regardless if it goes beyond either limit return; - + if(dir == null) dir = ForgeDirection.NORTH; - + dir = getDirection(dir.getOpposite()); - + int count = 0; - + int[] rot = MultiblockHandlerXR.rotate(dim, dir); - + int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); //MY SILLY ASS OPERATING WITH ALREADY FUCKING MODIFIED VARIABLES CLOWNKOEN int posY = getYWithOffset(y); - + BlockDummyable.safeRem = true; - + for(int a = posX - rot[4]; a <= posX + rot[5]; a++) { for(int c = posZ - rot[2]; c <= posZ + rot[3]; c++) { - + if(a >= box.minX && a <= box.maxX && c >= box.minZ && c <= box.maxZ) { for(int b = posY - rot[1]; b <= posY + rot[0]; b++) { - + int meta = 0; - + if(b < posY) { meta = ForgeDirection.DOWN.ordinal(); } else if(b > posY) { @@ -892,14 +893,14 @@ abstract public class Component extends StructureComponent { } else { continue; } - + world.setBlock(a, b, c, block, meta, 2); - + count++; - + if(count > 2000) { System.out.println("component's fillspace: ded " + a + " " + b + " " + c + " " + x + " " + y + " " + z); - + BlockDummyable.safeRem = false; return; } @@ -907,19 +908,19 @@ abstract public class Component extends StructureComponent { } } } - + BlockDummyable.safeRem = false; } - + /** StructureComponent-friendly method for {@link com.hbm.blocks.BlockDummyable#makeExtra(World, int, int, int)}. Prevents runoff outside of the provided bounding box. */ public void makeExtra(World world, StructureBoundingBox box, Block block, int x, int y, int z) { int posX = getXWithOffset(x, z); int posZ = getZWithOffset(x, z); int posY = getYWithOffset(y); - + if(!box.isVecInside(posX, posY, posZ)) return; - + if(world.getBlock(posX, posY, posZ) != block) return; @@ -927,23 +928,23 @@ abstract public class Component extends StructureComponent { if(meta > 5) return; - + BlockDummyable.safeRem = true; world.setBlock(posX, posY, posZ, block, meta + BlockDummyable.extra, 3); BlockDummyable.safeRem = false; } - + /** Block Selectors **/ - + static class Sandstone extends StructureComponent.BlockSelector { - + Sandstone() { } - + /** Selects blocks */ @Override public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean notInterior) { float chance = rand.nextFloat(); - + if(chance > 0.6F) { this.field_151562_a = Blocks.sandstone; } else if (chance < 0.5F ) { @@ -953,16 +954,16 @@ abstract public class Component extends StructureComponent { } } } - + static class ConcreteBricks extends StructureComponent.BlockSelector { - + ConcreteBricks() { } - + /** Selects blocks */ @Override public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean notInterior) { float chance = rand.nextFloat(); - + if(chance < 0.4F) { this.field_151562_a = ModBlocks.brick_concrete; } else if (chance < 0.7F) { @@ -974,18 +975,18 @@ abstract public class Component extends StructureComponent { } } } - + static class ConcreteBricksStairs extends StructureComponent.BlockSelector { - + ConcreteBricksStairs() { this.selectedBlockMetaData = 0; } - + /** Selects blocks */ @Override public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean notInterior) { float chance = rand.nextFloat(); - + if(chance < 0.4F) { this.field_151562_a = ModBlocks.brick_concrete_stairs; } else if (chance < 0.7F) { @@ -997,19 +998,19 @@ abstract public class Component extends StructureComponent { } } } - + static class ConcreteBricksSlabs extends StructureComponent.BlockSelector { - + ConcreteBricksSlabs() { this.field_151562_a = ModBlocks.concrete_brick_slab; this.selectedBlockMetaData = 0; } - + /** Selects blocks */ @Override public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean notInterior) { float chance = rand.nextFloat(); - + if (chance >= 0.4F && chance < 0.7F) { this.selectedBlockMetaData |= 1; } else if (chance < 0.9F) { @@ -1019,17 +1020,17 @@ abstract public class Component extends StructureComponent { } } } - + //ag static class LabTiles extends StructureComponent.BlockSelector { - + LabTiles() { } - + /** Selects blocks */ @Override public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean notInterior) { float chance = rand.nextFloat(); - + if(chance < 0.5F) { this.field_151562_a = ModBlocks.tile_lab; } else if (chance < 0.9F) { @@ -1039,18 +1040,84 @@ abstract public class Component extends StructureComponent { } } } - + static class SuperConcrete extends StructureComponent.BlockSelector { - + SuperConcrete() { this.field_151562_a = ModBlocks.concrete_super; } - + /** Selects blocks */ @Override public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean notInterior) { this.selectedBlockMetaData = rand.nextInt(6) + 10; } } - + + public static class MeteorBricks extends BlockSelector { + + @Override + public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean notInterior) { + float chance = rand.nextFloat(); + + if(chance < 0.4F) { + this.field_151562_a = ModBlocks.meteor_brick; + } else if (chance < 0.7F) { + this.field_151562_a = ModBlocks.meteor_brick_mossy; + } else { + this.field_151562_a = ModBlocks.meteor_brick_cracked; + } + } + + } + + public static class SupplyCrates extends BlockSelector { + + @Override + public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean notInterior) { + float chance = rand.nextFloat(); + + if(chance < 0.6F) { + this.field_151562_a = Blocks.air; + } else if(chance < 0.8F) { + this.field_151562_a = ModBlocks.crate_ammo; + } else if(chance < 0.9F) { + this.field_151562_a = ModBlocks.crate_can; + } else { + this.field_151562_a = ModBlocks.crate; + } + } + + } + + public static class CrabSpawners extends BlockSelector { + + @Override + public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean notInterior) { + float chance = rand.nextFloat(); + + if(chance < 0.8F) { + this.field_151562_a = ModBlocks.meteor_brick; + } else { + this.field_151562_a = ModBlocks.meteor_spawner; + } + } + + } + + public static class GreenOoze extends BlockSelector { + + @Override + public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean notInterior) { + float chance = rand.nextFloat(); + + if(chance < 0.8F) { + this.field_151562_a = ModBlocks.toxic_block; + } else { + this.field_151562_a = ModBlocks.meteor_polished; + } + } + + } + } diff --git a/src/main/resources/assets/hbm/lang/en_US.lang b/src/main/resources/assets/hbm/lang/en_US.lang index d4817b135..14ce1f4f0 100644 --- a/src/main/resources/assets/hbm/lang/en_US.lang +++ b/src/main/resources/assets/hbm/lang/en_US.lang @@ -5329,6 +5329,7 @@ tile.deco_computer.ibm_300pl.name=IBM Personal Computer 300PL tile.deco_crt.name=Old CRT Screen tile.deco_emitter.name=Deco Light Emitter tile.deco_lead.name=Lead Deco Block +tile.deco_loot.name=Loot Pile tile.deco_rbmk.name=RBMK Deco Block tile.deco_rbmk_smooth.name=Smooth RBMK Deco Block tile.deco_red_copper.name=Red Copper Deco Block @@ -6151,6 +6152,9 @@ tile.vitrified_barrel.name=Vitrified Nuclear Waste Drum tile.volcanic_lava_block.name=Volcanic Lava tile.volcano_core.name=Volcano Core tile.volcano_rad_core.name=Rad Volcano Core +tile.wand_air.name=Structure Wand Block (Air) +tile.wand_loot.name=Structure Wand Block (Lootable) +tile.wand_jigsaw.name=Structure Wand Block (Jigsaw) tile.waste_earth.name=Dead Grass tile.waste_leaves.name=Dead Leaves tile.waste_log.name=Charred Log diff --git a/src/main/resources/assets/hbm/structures/crashed-vertibird.nbt b/src/main/resources/assets/hbm/structures/crashed-vertibird.nbt new file mode 100644 index 000000000..93e22b9fb Binary files /dev/null and b/src/main/resources/assets/hbm/structures/crashed-vertibird.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-bale.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-bale.nbt new file mode 100644 index 000000000..b8f9aee0d Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-bale.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-blank.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-blank.nbt new file mode 100644 index 000000000..67e460c1e Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-blank.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-block.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-block.nbt new file mode 100644 index 000000000..53fd15326 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-block.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-book.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-book.nbt new file mode 100644 index 000000000..73dd17a40 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-book.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-crab-tesla.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-crab-tesla.nbt new file mode 100644 index 000000000..f707d794e Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-crab-tesla.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-crab.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-crab.nbt new file mode 100644 index 000000000..7891ce8b0 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-crab.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-crate.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-crate.nbt new file mode 100644 index 000000000..22c5c2e30 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-crate.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-dirt.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-dirt.nbt new file mode 100644 index 000000000..3afc135c2 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-dirt.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-lead.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-lead.nbt new file mode 100644 index 000000000..8ea4a132b Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-lead.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-mku.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-mku.nbt new file mode 100644 index 000000000..bbd46c68e Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-mku.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-ooze.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-ooze.nbt new file mode 100644 index 000000000..27df02e1a Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-ooze.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-pillar.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-pillar.nbt new file mode 100644 index 000000000..6b13b58f8 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-pillar.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-star.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-star.nbt new file mode 100644 index 000000000..336639b2c Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-star.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-statue.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-statue.nbt new file mode 100644 index 000000000..26b8e7fe3 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-statue.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-tesla.nbt b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-tesla.nbt new file mode 100644 index 000000000..b5e1c69a2 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/loot3x3/meteor-3-tesla.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/meteor-core.nbt b/src/main/resources/assets/hbm/structures/meteor/meteor-core.nbt new file mode 100644 index 000000000..9b5444901 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/meteor-core.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/meteor-corner.nbt b/src/main/resources/assets/hbm/structures/meteor/meteor-corner.nbt new file mode 100644 index 000000000..673b92235 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/meteor-corner.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/meteor-fallback.nbt b/src/main/resources/assets/hbm/structures/meteor/meteor-fallback.nbt new file mode 100644 index 000000000..fa3e955c7 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/meteor-fallback.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/meteor-spike.nbt b/src/main/resources/assets/hbm/structures/meteor/meteor-spike.nbt new file mode 100644 index 000000000..a28c2c309 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/meteor-spike.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/meteor-stairs.nbt b/src/main/resources/assets/hbm/structures/meteor/meteor-stairs.nbt new file mode 100644 index 000000000..fb4e8b865 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/meteor-stairs.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/meteor-t.nbt b/src/main/resources/assets/hbm/structures/meteor/meteor-t.nbt new file mode 100644 index 000000000..418d2c747 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/meteor-t.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-chest.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-chest.nbt new file mode 100644 index 000000000..b24269fca Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-chest.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-crate-crab.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-crate-crab.nbt new file mode 100644 index 000000000..cb5de6453 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-crate-crab.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-tesla.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-tesla.nbt new file mode 100644 index 000000000..5a4e4f802 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-tesla.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-trap.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-trap.nbt new file mode 100644 index 000000000..c8486d48e Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/headloot/loot-trap.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-balcony.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-balcony.nbt new file mode 100644 index 000000000..58664191f Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-balcony.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-base-end.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-base-end.nbt new file mode 100644 index 000000000..c77647792 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-base-end.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-base-thru.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-base-thru.nbt new file mode 100644 index 000000000..efa40eaab Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-base-thru.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-basic.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-basic.nbt new file mode 100644 index 000000000..0eb650e06 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-basic.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-dragon.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-dragon.nbt new file mode 100644 index 000000000..52e91cfe9 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-dragon.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-fallback.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-fallback.nbt new file mode 100644 index 000000000..6b0447906 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-fallback.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-ladder.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-ladder.nbt new file mode 100644 index 000000000..50bfc2523 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-ladder.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-ooze.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-ooze.nbt new file mode 100644 index 000000000..346cac917 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-ooze.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-split.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-split.nbt new file mode 100644 index 000000000..9ce05bb0f Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-split.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-stairs.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-stairs.nbt new file mode 100644 index 000000000..635f3d95e Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-stairs.nbt differ diff --git a/src/main/resources/assets/hbm/structures/meteor/room10/room-triple.nbt b/src/main/resources/assets/hbm/structures/meteor/room10/room-triple.nbt new file mode 100644 index 000000000..b1aa16ff4 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/meteor/room10/room-triple.nbt differ diff --git a/src/main/resources/assets/hbm/structures/test-jigsaw-core.nbt b/src/main/resources/assets/hbm/structures/test-jigsaw-core.nbt new file mode 100644 index 000000000..a73962172 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/test-jigsaw-core.nbt differ diff --git a/src/main/resources/assets/hbm/structures/test-jigsaw-hall.nbt b/src/main/resources/assets/hbm/structures/test-jigsaw-hall.nbt new file mode 100644 index 000000000..1676ffa91 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/test-jigsaw-hall.nbt differ diff --git a/src/main/resources/assets/hbm/structures/test-jigsaw.nbt b/src/main/resources/assets/hbm/structures/test-jigsaw.nbt new file mode 100644 index 000000000..aa2bdf7ea Binary files /dev/null and b/src/main/resources/assets/hbm/structures/test-jigsaw.nbt differ diff --git a/src/main/resources/assets/hbm/structures/test-rot.nbt b/src/main/resources/assets/hbm/structures/test-rot.nbt new file mode 100644 index 000000000..7150435df Binary files /dev/null and b/src/main/resources/assets/hbm/structures/test-rot.nbt differ diff --git a/src/main/resources/assets/hbm/structures/vertibird.nbt b/src/main/resources/assets/hbm/structures/vertibird.nbt new file mode 100644 index 000000000..da4bc38d9 Binary files /dev/null and b/src/main/resources/assets/hbm/structures/vertibird.nbt differ diff --git a/src/main/resources/assets/hbm/textures/blocks/wand_air.png b/src/main/resources/assets/hbm/textures/blocks/wand_air.png new file mode 100644 index 000000000..4e5efa1a4 Binary files /dev/null and b/src/main/resources/assets/hbm/textures/blocks/wand_air.png differ diff --git a/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw.png b/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw.png new file mode 100644 index 000000000..2e56150d8 Binary files /dev/null and b/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw.png differ diff --git a/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw_back.png b/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw_back.png new file mode 100644 index 000000000..6f202718b Binary files /dev/null and b/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw_back.png differ diff --git a/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw_side.png b/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw_side.png new file mode 100644 index 000000000..dc9a78ecb Binary files /dev/null and b/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw_side.png differ diff --git a/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw_top.png b/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw_top.png new file mode 100644 index 000000000..2c47fc86b Binary files /dev/null and b/src/main/resources/assets/hbm/textures/blocks/wand_jigsaw_top.png differ diff --git a/src/main/resources/assets/hbm/textures/blocks/wand_loot.png b/src/main/resources/assets/hbm/textures/blocks/wand_loot.png new file mode 100644 index 000000000..1dc8a297f Binary files /dev/null and b/src/main/resources/assets/hbm/textures/blocks/wand_loot.png differ diff --git a/src/main/resources/assets/hbm/textures/blocks/wand_loot_top.png b/src/main/resources/assets/hbm/textures/blocks/wand_loot_top.png new file mode 100644 index 000000000..5378ae691 Binary files /dev/null and b/src/main/resources/assets/hbm/textures/blocks/wand_loot_top.png differ