From 7d156d9ff974fb604cb2a1502c78d47366cdcfea Mon Sep 17 00:00:00 2001 From: Vaern Date: Tue, 23 Aug 2022 20:11:34 -0700 Subject: [PATCH] argh this shit needs to be sorted out --- .../world/worldgen/ComponentNTMFeatures.java | 149 ++++++-- .../hbm/world/worldgen/MapGenNTMFeatures.java | 18 +- .../world/worldgen/components/Feature.java | 326 ++++++++++++++++++ .../components/MilitaryBaseFeatures.java | 186 ++++++++++ 4 files changed, 645 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/hbm/world/worldgen/components/Feature.java create mode 100644 src/main/java/com/hbm/world/worldgen/components/MilitaryBaseFeatures.java diff --git a/src/main/java/com/hbm/world/worldgen/ComponentNTMFeatures.java b/src/main/java/com/hbm/world/worldgen/ComponentNTMFeatures.java index b98219729..49b292dbd 100644 --- a/src/main/java/com/hbm/world/worldgen/ComponentNTMFeatures.java +++ b/src/main/java/com/hbm/world/worldgen/ComponentNTMFeatures.java @@ -8,7 +8,10 @@ import com.hbm.blocks.generic.BlockBobble.TileEntityBobble; import com.hbm.lib.HbmChestContents; import com.hbm.tileentity.machine.storage.TileEntityCrateIron; import com.hbm.util.LootGenerator; +import com.hbm.world.worldgen.components.MilitaryBaseFeatures; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; import net.minecraft.init.Blocks; import net.minecraft.item.ItemDoor; import net.minecraft.nbt.NBTTagCompound; @@ -18,7 +21,10 @@ import net.minecraft.world.World; import net.minecraft.world.gen.structure.MapGenStructureIO; import net.minecraft.world.gen.structure.StructureBoundingBox; import net.minecraft.world.gen.structure.StructureComponent; +import scala.reflect.internal.Trees.This; +//TODO: +//KILL! //Probably one of the more difficult parts. /** Base component file. For structure generation under 32x32 blocks, as Minecraft generates 2x2 chunks for structures. * Larger non-procedural structures should be split up into several bounding boxes, which check if they intersect the chunk bounding box currently being loaded. Doing so will prevent @@ -38,6 +44,9 @@ public class ComponentNTMFeatures { MapGenStructureIO.func_143031_a(ComponentNTMFeatures.NTMRuin2.class, "NTMRuin2"); MapGenStructureIO.func_143031_a(ComponentNTMFeatures.NTMRuin3.class, "NTMRuin3"); MapGenStructureIO.func_143031_a(ComponentNTMFeatures.NTMRuin4.class, "NTMRuin4"); + //aggggggggggg + MapGenStructureIO.func_143031_a(MilitaryBaseFeatures.BasicHelipad.class, "NTMBasicHelipad"); + MapGenStructureIO.func_143031_a(MilitaryBaseFeatures.RadioShack.class, "NTMRadioShack"); } /** Sandstone Ruin 1 */ @@ -93,7 +102,7 @@ public class ComponentNTMFeatures { */ //System.out.println(this.coordBaseMode); - if(!this.func_74935_a(world, box, this.boundingBox.minY)) { + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { return false; } //System.out.println("" + this.boundingBox.minX + ", " + this.boundingBox.minY + ", " + this.boundingBox.minZ); @@ -177,7 +186,7 @@ public class ComponentNTMFeatures { public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { //System.out.print(this.coordBaseMode); - if(!this.func_74935_a(world, box, this.boundingBox.minY)) { + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { return false; } //System.out.println("" + this.boundingBox.minX + ", " + this.boundingBox.minY + ", " + this.boundingBox.minZ); @@ -257,7 +266,7 @@ public class ComponentNTMFeatures { //Loot & Decorations //House 1 - int eastMeta = this.getMetadataForRotatableDeco(4); + int eastMeta = this.getDecoMeta(4); this.placeBlockAtCurrentPosition(world, ModBlocks.machine_boiler_off, 4, 1, 1, 1, box); this.fillWithBlocks(world, box, 1, 2, 1, 1, 3, 1, ModBlocks.deco_pipe_quad_rusted, Blocks.air, false); this.placeBlockAtCurrentPosition(world, ModBlocks.deco_pipe_rim_rusted, 0, 1, featureSizeY, 1, box); @@ -332,7 +341,7 @@ public class ComponentNTMFeatures { public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { //System.out.println(this.coordBaseMode); - if(!this.func_74935_a(world, box, this.boundingBox.minY)) { + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { return false; } //System.out.println("" + this.boundingBox.minX + ", " + this.boundingBox.minY + ", " + this.boundingBox.minZ); @@ -360,7 +369,7 @@ public class ComponentNTMFeatures { this.fillWithAir(world, box, 4, 0, 4, featureSizeX - 1, featureSizeY, featureSizeZ - 1); this.fillWithAir(world, box, 3, 1, featureSizeZ - 1, 3, 2, featureSizeZ - 1); - int pillarMeta = this.getMetadataForRotatablePillar(8); + int pillarMeta = this.getPillarMeta(8); //Pillars this.fillWithBlocks(world, box, 0, 0, 0, 0, 3, 0, ModBlocks.concrete_pillar, Blocks.air, false); @@ -398,7 +407,7 @@ public class ComponentNTMFeatures { //Decorations & Loot this.fillWithMetadataBlocks(world, box, 1, 1, 1, 1, 1, 4, Blocks.dirt, 2, Blocks.air, 0, false); - int westDecoMeta = this.getMetadataForRotatableDeco(5); + int westDecoMeta = this.getDecoMeta(5); this.fillWithMetadataBlocks(world, box, 2, 1, 1, 2, 1, 4, ModBlocks.steel_wall, westDecoMeta, Blocks.air, 0, false); this.fillWithMetadataBlocks(world, box, 2, featureSizeY - 1, 1, 2, featureSizeY - 1, 4, ModBlocks.steel_wall, westDecoMeta, Blocks.air, 0, false); for(byte i = 0; i < 4; i++) { @@ -409,7 +418,7 @@ public class ComponentNTMFeatures { this.placeBlockAtCurrentPosition(world, ModBlocks.door_office, doorMeta, 3, 1, featureSizeZ - 1, box); ItemDoor.placeDoorBlock(world, this.getXWithOffset(3, featureSizeZ - 1), this.getYWithOffset(1), this.getZWithOffset(3, featureSizeZ - 1), doorMeta, ModBlocks.door_office); - int northDecoMeta = this.getMetadataForRotatableDeco(3); + int northDecoMeta = this.getDecoMeta(3); this.fillWithMetadataBlocks(world, box, 5, featureSizeY - 1, 1, featureSizeX - 1, featureSizeY - 1, 1, ModBlocks.steel_scaffold, westDecoMeta, Blocks.air, 0, false); this.fillWithMetadataBlocks(world, box, 5, featureSizeY - 1, 2, featureSizeX - 1, featureSizeY - 1, 2, ModBlocks.steel_wall, northDecoMeta, Blocks.air, 0, false); this.placeBlockAtCurrentPosition(world, ModBlocks.machine_electric_furnace_off, northDecoMeta, 5, 1, 1, box); @@ -469,7 +478,7 @@ public class ComponentNTMFeatures { public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { //System.out.println(this.coordBaseMode); - if(!this.func_74935_a(world, box, this.boundingBox.minY)) { + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { return false; } this.boundingBox.offset(0, -7, 0); @@ -566,10 +575,10 @@ public class ComponentNTMFeatures { this.fillWithRandomizedBlocks(world, box, 1, 4, 1, featureSizeX - 1, 4, featureSizeZ - 1, false, rand, RandomConcreteBricks); //Ceiling //Decorations & Loot - int eastMeta = this.getMetadataForRotatableDeco(4); - int westMeta = this.getMetadataForRotatableDeco(5); - int northMeta = this.getMetadataForRotatableDeco(3); - int southMeta = this.getMetadataForRotatableDeco(2); + int eastMeta = this.getDecoMeta(4); + int westMeta = this.getDecoMeta(5); + int northMeta = this.getDecoMeta(3); + int southMeta = this.getDecoMeta(2); this.placeBlockAtCurrentPosition(world, ModBlocks.crashed_balefire, southMeta, 6, featureSizeY - 2, 3, box); int doorMeta = this.getMetadataWithOffset(Blocks.wooden_door, 1); @@ -648,7 +657,7 @@ public class ComponentNTMFeatures { public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { ////System.out.println(this.coordBaseMode); - if(!this.func_74935_a(world, box, this.boundingBox.minY)) { + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { return false; } //System.out.println("" + this.boundingBox.minX + ", " + this.boundingBox.minY + ", " + this.boundingBox.minZ); @@ -681,8 +690,8 @@ public class ComponentNTMFeatures { } //Walls - int pillarMetaWE = this.getMetadataForRotatablePillar(4); - int pillarMetaNS = this.getMetadataForRotatablePillar(8); + int pillarMetaWE = this.getPillarMeta(4); + int pillarMetaNS = this.getPillarMeta(8); this.fillWithBlocks(world, box, 1, 0, 0, 1, 3, 0, ModBlocks.concrete_pillar, Blocks.air, false); //Back Wall this.placeBlockAtCurrentPosition(world, ModBlocks.concrete, 0, 1, 4, 0, box); this.fillWithMetadataBlocks(world, box, 2, 4, 0, featureSizeX - 4, 4, 0, ModBlocks.concrete_pillar, pillarMetaWE, Blocks.air, 0, false); @@ -713,8 +722,8 @@ public class ComponentNTMFeatures { this.fillWithMetadataBlocks(world, box, featureSizeX - 3, 4, 1, featureSizeX - 3, 4, featureSizeZ - 1, ModBlocks.concrete_pillar, pillarMetaNS, Blocks.air, 0, false); //Right Wall this.fillWithRandomizedBlocks(world, box, featureSizeX - 3, 0, 1, featureSizeX - 3, 3, featureSizeZ - 1, false, rand, RandomSuperConcrete); - pillarMetaWE = this.getMetadataForRotatablePillar(5); - pillarMetaNS = this.getMetadataForRotatablePillar(9); + pillarMetaWE = this.getPillarMeta(5); + pillarMetaNS = this.getPillarMeta(9); this.fillWithMetadataBlocks(world, box, featureSizeX - 2, 2, 1, featureSizeX - 1, 2, 1, Blocks.log, pillarMetaWE, Blocks.air, 0, false); //Back Wall this.fillWithMetadataBlocks(world, box, featureSizeX, 0, 1, featureSizeX, 2, 1, Blocks.log, 1, Blocks.air, 0, false); this.fillWithMetadataBlocks(world, box, featureSizeX - 2, 0, 1, featureSizeX - 1, 1, 1, Blocks.planks, 1, Blocks.air, 0, false); @@ -735,8 +744,8 @@ public class ComponentNTMFeatures { this.fillWithBlocks(world, box, featureSizeX - 2, 2, 2, featureSizeX - 1, 2, 5, ModBlocks.deco_steel, Blocks.air, false); //Loot & Decorations - int southMeta = this.getMetadataForRotatableDeco(2); - int eastMeta = this.getMetadataForRotatableDeco(5); + int southMeta = this.getDecoMeta(2); + int eastMeta = this.getDecoMeta(5); this.placeBlockAtCurrentPosition(world, ModBlocks.pole_satellite_receiver, eastMeta, 2, featureSizeY - 1, 1, box); this.fillWithBlocks(world, box, 3, featureSizeY - 1, 1, 4, featureSizeY - 1, 1, ModBlocks.deco_steel, Blocks.air, false); this.fillWithBlocks(world, box, 2, featureSizeY - 1, 2, 4, featureSizeY - 1, 2, ModBlocks.deco_steel, Blocks.air, false); @@ -793,7 +802,7 @@ public class ComponentNTMFeatures { public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { //System.out.println(this.coordBaseMode); - if(!this.func_74935_a(world, box, this.boundingBox.minY)) { + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { return false; } //System.out.println("" + this.boundingBox.minX + ", " + this.boundingBox.minY + ", " + this.boundingBox.minZ); @@ -804,8 +813,8 @@ public class ComponentNTMFeatures { } } - int pillarMetaWE = this.getMetadataForRotatablePillar(4); - int pillarMetaNS = this.getMetadataForRotatablePillar(8); + int pillarMetaWE = this.getPillarMeta(4); + int pillarMetaNS = this.getPillarMeta(8); this.fillWithBlocks(world, box, 0, 0, 0, 0, featureSizeY, 0, ModBlocks.concrete_pillar, Blocks.air, false); //Back Wall this.fillWithMetadataBlocks(world, box, 1, 3, 0, 3, 3, 0, ModBlocks.concrete_pillar, pillarMetaWE, Blocks.air, 0, false); @@ -869,7 +878,7 @@ public class ComponentNTMFeatures { public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { //System.out.println(this.coordBaseMode); - if(!this.func_74935_a(world, box, this.boundingBox.minY)) { + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { return false; } //System.out.println("" + this.boundingBox.minX + ", " + this.boundingBox.minY + ", " + this.boundingBox.minZ); @@ -880,8 +889,8 @@ public class ComponentNTMFeatures { } } - int pillarMetaWE = this.getMetadataForRotatablePillar(4); - int pillarMetaNS = this.getMetadataForRotatablePillar(8); + int pillarMetaWE = this.getPillarMeta(4); + int pillarMetaNS = this.getPillarMeta(8); this.fillWithBlocks(world, box, 0, 0, 0, 0, 3, 0, ModBlocks.concrete_pillar, Blocks.air, false); //Back Wall this.fillWithMetadataBlocks(world, box, 1, 3, 0, featureSizeX - 1, 3, 0, ModBlocks.concrete_pillar, pillarMetaWE, Blocks.air, 0, false); @@ -936,7 +945,7 @@ public class ComponentNTMFeatures { public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { //System.out.println(this.coordBaseMode); - if(!this.func_74935_a(world, box, this.boundingBox.minY)) { + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { return false; } //System.out.println("" + this.boundingBox.minX + ", " + this.boundingBox.minY + ", " + this.boundingBox.minZ); @@ -997,7 +1006,7 @@ public class ComponentNTMFeatures { public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { //System.out.println(this.coordBaseMode); - if(!this.func_74935_a(world, box, this.boundingBox.minY)) { + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { return false; } //System.out.println("" + this.boundingBox.minX + ", " + this.boundingBox.minY + ", " + this.boundingBox.minZ); @@ -1043,6 +1052,8 @@ public class ComponentNTMFeatures { } } + /*Worrying: StructureStart checks for not addComponentParts to remove structure components from iterator, but here successful builds return true. + may be issue with multiple components.*/ abstract static class Feature extends StructureComponent { /** The size of the bounding box for this feature in the X axis */ protected int featureSizeX; @@ -1101,7 +1112,7 @@ public class ComponentNTMFeatures { this.hpos = nbt.getInteger("HPos"); } - protected boolean func_74935_a(World world, StructureBoundingBox box, int y) { + protected boolean setAverageHeight(World world, StructureBoundingBox box, int y) { int j = 0; int k = 0; @@ -1128,7 +1139,7 @@ public class ComponentNTMFeatures { * @param metadata (First two digits are equal to block metadata, other two are equal to orientation * @return metadata adjusted for random orientation */ - protected int getMetadataForRotatablePillar(int metadata) { + protected int getPillarMeta(int metadata) { int blockMeta = metadata & 3; int rotationMeta = metadata >> 2; @@ -1163,7 +1174,7 @@ public class ComponentNTMFeatures { * @param metadata (2 for facing South, 3 for facing North, 4 for facing East, 5 for facing West * @return metadata adjusted for random orientation */ - protected int getMetadataForRotatableDeco(int metadata) { + protected int getDecoMeta(int metadata) { switch(this.coordBaseMode) { case 0: //South switch(metadata) { @@ -1213,6 +1224,40 @@ public class ComponentNTMFeatures { return 0; } + //TODO: Make a lot of these orientation/rotation methods much more transparent about what + //direction they will actually face + + /** + * Places door at specified location with orientation-adjusted meta + * don't ask me which directions are what + */ + protected void placeDoor(World world, StructureBoundingBox box, Block door, int direction, int featureX, int featureY, int featureZ) { + int meta = getMetadataWithOffset(Blocks.wooden_door, direction); + int posX = this.getXWithOffset(featureX, featureZ); + int posY = this.getYWithOffset(featureY); + int posZ = this.getZWithOffset(featureX, featureZ); + + this.placeBlockAtCurrentPosition(world, door, meta, featureX, featureY, featureZ, box); + ItemDoor.placeDoorBlock(world, posX, posY, posZ, meta, door); + } + + /** + * Places random bobblehead with a randomized orientation at specified location + */ + protected void placeRandomBobble(World world, StructureBoundingBox box, Random rand, int featureX, int featureY, int featureZ) { + 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(); + } + } + /** * it feels disgusting to make a method with this many parameters but fuck it, it's easier * @return iron crate with generated content @@ -1232,6 +1277,47 @@ public class ComponentNTMFeatures { return false; } + + @Override + protected void func_151554_b(World world, Block placeBlock, int meta, int featureX, int featureY, int featureZ, StructureBoundingBox box) { + 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); + + while ((world.isAirBlock(posX, posY, posZ) || !block.getMaterial().isSolid() || (block.isFoliage(world, posX, posY, posZ) || block.getMaterial() == Material.leaves)) && posY > 1) { + world.setBlock(posX, posY, posZ, placeBlock, meta, 2); + block = world.getBlock(posX, --posY, posZ); + } + } + } + + /** + * 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); + } + } + } + } + } + } //Block Selectors @@ -1276,6 +1362,7 @@ public class ComponentNTMFeatures { } } + //ag static class LabTiles extends StructureComponent.BlockSelector { LabTiles() { } @@ -1305,8 +1392,6 @@ public class ComponentNTMFeatures { @Override public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean p_75062_5_) { this.selectedBlockMetaData = rand.nextInt(6) + 10; - - } } } diff --git a/src/main/java/com/hbm/world/worldgen/MapGenNTMFeatures.java b/src/main/java/com/hbm/world/worldgen/MapGenNTMFeatures.java index 9f26946be..666f892a3 100644 --- a/src/main/java/com/hbm/world/worldgen/MapGenNTMFeatures.java +++ b/src/main/java/com/hbm/world/worldgen/MapGenNTMFeatures.java @@ -2,19 +2,25 @@ package com.hbm.world.worldgen; import java.util.Arrays; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Random; import com.hbm.config.GeneralConfig; +import com.hbm.world.worldgen.components.MilitaryBaseFeatures; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeGenBase; +import net.minecraft.world.biome.BiomeGenBeach; import net.minecraft.world.biome.BiomeGenMesa; import net.minecraft.world.gen.structure.MapGenStructure; +import net.minecraft.world.gen.structure.MapGenStructureIO; +import net.minecraft.world.gen.structure.StructureComponent; import net.minecraft.world.gen.structure.StructureStart; public class MapGenNTMFeatures extends MapGenStructure { + //BiomeDictionary could be /very/ useful, since it automatically sorts *all* biomes into predefined categories private static List biomelist = Arrays.asList(new BiomeGenBase[] {BiomeGenBase.ocean, BiomeGenBase.river, BiomeGenBase.frozenOcean, BiomeGenBase.frozenRiver, BiomeGenBase.deepOcean}); /** Maximum distance between structures */ private int maxDistanceBetweenScatteredFeatures; @@ -130,6 +136,8 @@ public class MapGenNTMFeatures extends MapGenStructure { ComponentNTMFeatures.NTMWorkshop1 workshop1 = new ComponentNTMFeatures.NTMWorkshop1(rand, chunkX * 16 + 8, posY, chunkZ * 16 + 8); this.components.add(workshop1); } + } else if(biome.heightVariation <= 0.2 && biome.rainfall <= 0.5 && !(biome instanceof BiomeGenBeach) && rand.nextBoolean()) { + MilitaryBaseFeatures.smallHelipad(components, chunkX, posY, chunkZ, rand); //agggggggg } else { //Everything else if(rand.nextBoolean()) { ComponentNTMFeatures.NTMLab2 lab2 = new ComponentNTMFeatures.NTMLab2(rand, chunkX * 16 + 8, posY, chunkZ * 16 + 8); @@ -140,8 +148,14 @@ public class MapGenNTMFeatures extends MapGenStructure { } } - if(GeneralConfig.enableDebugMode) - System.out.print("[Debug] StructureStart at " + (chunkX * 16 + 8) + ", " + posY + ", " + (chunkZ * 16 + 8) + "\n"); + if(GeneralConfig.enableDebugMode) { + System.out.print("[Debug] StructureStart at " + (chunkX * 16 + 8) + ", " + posY + ", " + (chunkZ * 16 + 8) + "\n[Debug] Components: "); + this.components.forEach((component) -> { + System.out.print(MapGenStructureIO.func_143036_a((StructureComponent) component) + " "); + }); + + System.out.print("\n"); + } this.updateBoundingBox(); } diff --git a/src/main/java/com/hbm/world/worldgen/components/Feature.java b/src/main/java/com/hbm/world/worldgen/components/Feature.java new file mode 100644 index 000000000..0ffce977c --- /dev/null +++ b/src/main/java/com/hbm/world/worldgen/components/Feature.java @@ -0,0 +1,326 @@ +package com.hbm.world.worldgen.components; + +import java.util.Random; + +import com.hbm.blocks.ModBlocks; +import com.hbm.blocks.generic.BlockBobble.BobbleType; +import com.hbm.blocks.generic.BlockBobble.TileEntityBobble; +import com.hbm.tileentity.machine.storage.TileEntityCrateIron; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemDoor; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.WeightedRandomChestContent; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.StructureBoundingBox; +import net.minecraft.world.gen.structure.StructureComponent; + +abstract public class Feature extends StructureComponent { + /** The size of the bounding box for this feature in the X axis */ + protected int sizeX; + /** The size of the bounding box for this feature in the Y axis */ + protected int sizeY; + /** The size of the bounding box for this feature in the Z axis */ + protected int sizeZ; + /** Average height (Presumably stands for height position) */ + protected int hpos = -1; + + protected Feature() { + super(0); + } + + protected Feature(Random rand, int minX, int minY, int minZ, int maxX, int maxY, int maxZ ) { + super(0); + this.sizeX = maxX; + this.sizeY = maxY; + this.sizeZ = maxZ; + this.coordBaseMode = rand.nextInt(4); + + switch(this.coordBaseMode) { + case 0: + this.boundingBox = new StructureBoundingBox(minX, minY, minZ, minX + maxX, minY + maxY, minZ + maxZ); + break; + case 1: + this.boundingBox = new StructureBoundingBox(minX, minY, minZ, minX + maxZ, minY + maxY, minZ + maxX); + break; + case 2: + //North (2) and East (3) will result in mirrored structures. Not an issue, but keep in mind. + this.boundingBox = new StructureBoundingBox(minX, minY, minZ, minX + maxX, minY + maxY, minZ + maxZ); + break; + case 3: + this.boundingBox = new StructureBoundingBox(minX, minY, minZ, minX + maxX, minY + maxY, minZ + maxZ); + 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("Width", this.sizeX); + nbt.setInteger("Height", this.sizeY); + nbt.setInteger("Depth", this.sizeZ); + nbt.setInteger("HPos", this.hpos); + } + + /** Get from NBT */ + protected void func_143011_b(NBTTagCompound nbt) { + this.sizeX = nbt.getInteger("Width"); + this.sizeY = nbt.getInteger("Height"); + this.sizeZ = nbt.getInteger("Depth"); + 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)) { + total += Math.max(world.getTopSolidOrLiquidBlock(x, z), world.provider.getAverageGroundLevel()); + iterations++; + } + } + } + + 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; + } + + /** 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 + * @return metadata adjusted for random orientation + */ + 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 + * seriously, 3 fucking bits for 4 orientations when you can do it easily with 2? + * @param metadata (2 for facing South, 3 for facing North, 4 for facing East, 5 for facing West + */ + protected int getDecoMeta(int metadata) { + switch(this.coordBaseMode) { + case 0: //South + switch(metadata) { + case 2: return 2; + case 3: return 3; + case 4: return 4; + case 5: return 5; + } + case 1: //West + switch(metadata) { + case 2: return 5; + case 3: return 4; + case 4: return 2; + case 5: return 3; + } + case 2: //North + switch(metadata) { + case 2: return 3; + case 3: return 2; + case 4: return 4; + case 5: return 5; + } + case 3: //East + switch(metadata) { + case 2: return 4; + case 3: return 5; + case 4: return 2; + case 5: return 3; + } + } + return 0; + } + + /** + * Places door at specified location with orientation-adjusted meta + * don't ask me which directions are what (take direction such as South/0 and add 1) + */ + protected void placeDoor(World world, StructureBoundingBox box, Block door, int direction, int featureX, int featureY, int featureZ) { + int meta = getMetadataWithOffset(Blocks.wooden_door, direction); + int posX = this.getXWithOffset(featureX, featureZ); + int posY = this.getYWithOffset(featureY); + int posZ = this.getZWithOffset(featureX, featureZ); + + this.placeBlockAtCurrentPosition(world, door, meta, featureX, featureY, featureZ, box); + ItemDoor.placeDoorBlock(world, posX, posY, posZ, meta, door); + } + + /** 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 + */ + protected boolean generateInvContents(World world, StructureBoundingBox box, Random rand, Block block, 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); + + this.placeBlockAtCurrentPosition(world, block, 0, featureX, featureY, featureZ, box); + IInventory inventory = (IInventory)world.getTileEntity(posX, posY, posZ); + + if(inventory != null) { + WeightedRandomChestContent.generateChestContents(rand, content, inventory, amount); + return true; + } + + return false; + } + + /** + * Places random bobblehead with a randomized orientation at specified location + */ + protected void placeRandomBobble(World world, StructureBoundingBox box, Random rand, int featureX, int featureY, int featureZ) { + 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 featureX, int featureY, int featureZ, StructureBoundingBox box) { + 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); + + while ((world.isAirBlock(posX, posY, posZ) || !block.getMaterial().isSolid() || (block.isFoliage(world, posX, posY, posZ) || block.getMaterial() == Material.leaves)) && posY > 1) { + world.setBlock(posX, posY, posZ, placeBlock, meta, 2); + block = world.getBlock(posX, --posY, posZ); + } + } + } + + /** + * 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); + } + } + } + } + } + + /** Block Selectors **/ + + static class Sandstone extends StructureComponent.BlockSelector { + + Sandstone() { } + + /** Selects blocks */ + @Override + public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean p_75062_5_) { + float chance = rand.nextFloat(); + + if(chance > 0.6F) { + this.field_151562_a = Blocks.sandstone; + } else if (chance < 0.5F ) { + this.field_151562_a = ModBlocks.reinforced_sand; + } else { + this.field_151562_a = Blocks.sand; + } + } + } + + static class ConcreteBricks extends StructureComponent.BlockSelector { + + ConcreteBricks() { } + + /** Selects blocks */ + @Override + public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean p_75062_5_) { + float chance = rand.nextFloat(); + + if(chance < 0.2F) { + this.field_151562_a = ModBlocks.brick_concrete; + } else if (chance < 0.55F) { + this.field_151562_a = ModBlocks.brick_concrete_mossy; + } else if (chance < 0.75F) { + this.field_151562_a = ModBlocks.brick_concrete_cracked; + } else { + this.field_151562_a = ModBlocks.brick_concrete_broken; + } + } + } + + //ag + static class LabTiles extends StructureComponent.BlockSelector { + + LabTiles() { } + + /** Selects blocks */ + @Override + public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean p_75062_5_) { + float chance = rand.nextFloat(); + + if(chance < 0.5F) { + this.field_151562_a = ModBlocks.tile_lab; + } else if (chance < 0.9F) { + this.field_151562_a = ModBlocks.tile_lab_cracked; + } else { + this.field_151562_a = ModBlocks.tile_lab_broken; + } + } + } + + 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 p_75062_5_) { + this.selectedBlockMetaData = rand.nextInt(6) + 10; + } + } + +} diff --git a/src/main/java/com/hbm/world/worldgen/components/MilitaryBaseFeatures.java b/src/main/java/com/hbm/world/worldgen/components/MilitaryBaseFeatures.java new file mode 100644 index 000000000..49bf2cad6 --- /dev/null +++ b/src/main/java/com/hbm/world/worldgen/components/MilitaryBaseFeatures.java @@ -0,0 +1,186 @@ +package com.hbm.world.worldgen.components; + +import java.util.LinkedList; +import java.util.Random; + +import com.hbm.blocks.ModBlocks; +import com.hbm.world.worldgen.ComponentNTMFeatures; + +import net.minecraft.init.Blocks; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.StructureBoundingBox; + +public class MilitaryBaseFeatures { + + //stop-gap methods until this entire mess can be organized into proper classes/structure groups + public static void smallHelipad(LinkedList components, int chunkX, int posY, int chunkZ, Random rand) { + BasicHelipad helipad = new BasicHelipad(rand, chunkX * 16 + 8, posY, chunkZ * 16 + 8); + int[] chunkPos = getAdjacentChunk(chunkX, chunkZ, rand); + + RadioShack radio = new RadioShack(rand, chunkPos[0] * 16 + 8, posY, chunkPos[1] * 16 + 8); + components.add(helipad); + components.add(radio); + } + + public static int[] getAdjacentChunk(int chunkX, int chunkZ, Random rand) { + int[] chunkPos = new int[2]; + + switch(rand.nextInt(4)) { + case 0: + chunkPos[0] = chunkX; + chunkPos[1] = chunkZ + 1; + break; + case 1: + chunkPos[0] = chunkX - 1; + chunkPos[1] = chunkZ; + break; + case 2: + chunkPos[0] = chunkX; + chunkPos[1] = chunkZ - 1; + break; + case 3: + chunkPos[0] = chunkX + 1; + chunkPos[1] = chunkZ; + break; + } + + return chunkPos; + } + + public static class BasicHelipad extends Feature { + + public BasicHelipad() { super(); } + + protected BasicHelipad(Random rand, int minX, int minY, int minZ) { + super(rand, minX, minY, minZ, 12, 0, 12); + } + + @Override + public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { + + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { + return true; + } + + this.boundingBox.offset(0, -1, 0); + + for(int i = 1; i < sizeX; i++) { + for(int j = 1; j < sizeZ; j++) { + func_151554_b(world, Blocks.stonebrick, 0, i, -1, j, box); + clearCurrentPositionBlocksUpwards(world, i, 1, j, box); + } + } + + for(int i = 0; i <= sizeX; i++) { + for(int j = 0; j <= sizeZ; j++) { + if(i == 0 || i == sizeX || j == 0 || j == sizeX) + func_151554_b(world, Blocks.stonebrick, 0, i, 0, j, box); + } + } + + //Helipad + fillWithBlocks(world, box, 1, 0, 1, 11, 0, 1, ModBlocks.concrete, Blocks.air, false); //this entire time, the second block was actually for anything not at min/max x's, y's, and z's. useful! + fillWithBlocks(world, box, 11, 0, 2, 11, 0, 11, ModBlocks.concrete, Blocks.air, false); + fillWithBlocks(world, box, 1, 0, 11, 10, 0, 11, ModBlocks.concrete, Blocks.air, false); + fillWithBlocks(world, box, 1, 0, 2, 1, 0, 10, ModBlocks.concrete, Blocks.air, false); + + fillWithBlocks(world, box, 2, 0, 2, 10, 0, 10, ModBlocks.concrete_smooth, Blocks.air, false); //i'm not carefully carving out the white H lmao fuck that + fillWithBlocks(world, box, 4, 0, 4, 4, 0, 8, ModBlocks.concrete_colored, Blocks.air, false); //white is 0 + fillWithBlocks(world, box, 8, 0, 4, 8, 0, 8, ModBlocks.concrete_colored, Blocks.air, false); + fillWithBlocks(world, box, 5, 0, 6, 7, 0, 6, ModBlocks.concrete_colored, Blocks.air, false); + + //Surrounding Fences + placeBlocksOnTop(world, box, ModBlocks.fence_metal, 0, 0, sizeX, 0, 1); + placeBlocksOnTop(world, box, ModBlocks.fence_metal, sizeX, 1, sizeX, sizeZ, 1); + placeBlocksOnTop(world, box, ModBlocks.fence_metal, 0, sizeZ, sizeX - 1, sizeZ, 1); + placeBlocksOnTop(world, box, ModBlocks.fence_metal, 0, 1, 0, sizeZ - 1, 1); + + return false; + } + + } + + public static class RadioShack extends Feature { + + private static LabTiles RandomLabTiles = new LabTiles(); + private static ConcreteBricks ConcreteBricks = new ConcreteBricks(); + + public RadioShack() { super(); } + + protected RadioShack(Random rand, int minX, int minY, int minZ) { + super(rand, minX, minY, minZ, 6, 4, 5); + } + + @Override + public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) { + + if(!this.setAverageHeight(world, box, this.boundingBox.minY)) { + return true; + } + + this.boundingBox.offset(0, -1, 0); + + for(int i = 1; i <= sizeX; i++) { + for(int j = 1; j <= sizeZ; j++) { + func_151554_b(world, Blocks.stonebrick, 0, i, -1, j, box); + } + } + + func_151554_b(world, Blocks.stonebrick, 0, 0, 0, 2, box); + + //Floor & Foundation + fillWithRandomizedBlocks(world, box, 2, 0, 1, 5, 0, 4, false, rand, RandomLabTiles); + placeBlockAtCurrentPosition(world, ModBlocks.concrete_pillar, 0, 1, 0, 1, box); + placeBlockAtCurrentPosition(world, ModBlocks.concrete_pillar, 0, sizeX, 0, 1, box); + placeBlockAtCurrentPosition(world, ModBlocks.concrete_pillar, 0, 1, 0, sizeZ, box); + placeBlockAtCurrentPosition(world, ModBlocks.concrete_pillar, 0, sizeX, 0, sizeZ, box); + fillWithBlocks(world, box, 2, 0, 1, sizeX - 1, 0, 1, ModBlocks.concrete_smooth, Blocks.air, false); + fillWithBlocks(world, box, 2, 0, 0, sizeX - 1, 0, 0, ModBlocks.concrete_smooth, Blocks.air, false); + fillWithBlocks(world, box, sizeX, 0, 2, sizeX, 0, sizeZ - 1, ModBlocks.concrete_smooth, Blocks.air, false); + fillWithBlocks(world, box, 2, 0, sizeZ, sizeX - 1, 0, sizeZ, ModBlocks.concrete_smooth, Blocks.air, false); + fillWithBlocks(world, box, 1, 0, 2, 1, 0, sizeZ - 1, ModBlocks.concrete_smooth, Blocks.air, false); + + //Back Wall + fillWithRandomizedBlocks(world, box, 1, 1, 1, 2, sizeY - 1, 1, false, rand, ConcreteBricks); + fillWithRandomizedBlocks(world, box, 2, 1, 0, 5, sizeY - 1, 0, false, rand, ConcreteBricks); + fillWithRandomizedBlocks(world, box, 5, 1, 1, sizeX, sizeY - 1, 1, false, rand, ConcreteBricks); + //Front Wall + fillWithRandomizedBlocks(world, box, 1, 1, sizeZ, 2, sizeY - 1, sizeZ, false, rand, ConcreteBricks); + placeBlockAtCurrentPosition(world, ModBlocks.brick_concrete, 0, 3, sizeY - 1, sizeZ, box); + fillWithRandomizedBlocks(world, box, 4, 1, sizeZ, sizeX, sizeY - 1, sizeZ, false, rand, ConcreteBricks); + placeDoor(world, box, ModBlocks.door_metal, 3, 3, 1, sizeZ); + //Left & Right Wall + fillWithRandomizedBlocks(world, box, 1, 1, 2, 1, sizeY - 1, sizeZ - 1, false, rand, ConcreteBricks); + fillWithRandomizedBlocks(world, box, sizeX, 1, 2, sizeX, sizeY - 1, sizeZ - 1, false, rand, ConcreteBricks); + placeBlockAtCurrentPosition(world, ModBlocks.reinforced_glass, 0, 1, 2, 3, box); + placeBlockAtCurrentPosition(world, ModBlocks.reinforced_glass, 0, sizeX, 2, 2, box); + placeBlockAtCurrentPosition(world, ModBlocks.reinforced_glass, 0, sizeX, 2, 4, box); + //Ceiling + fillWithBlocks(world, box, 3, sizeY - 1, 1, 4, sizeY - 1, 1, ModBlocks.concrete_smooth, Blocks.air, false); + fillWithBlocks(world, box, 2, sizeY - 1, 2, sizeX - 1, sizeY - 1, sizeZ - 1, ModBlocks.concrete_smooth, Blocks.air, false); + + fillWithAir(world, box, 2, 1, 2, sizeX - 1, 2, sizeZ - 1); + + //Decoration + int southMeta = getDecoMeta(2); + int northMeta = getDecoMeta(3); //all of these deco blocks are so inconsistent about what their directions actually are + int eastMeta = getDecoMeta(4); + fillWithMetadataBlocks(world, box, 2, 1, 2, 5, 1, 2, ModBlocks.steel_grate, 7, null, 0, false); //null should be okay here + fillWithBlocks(world, box, 3, 1, 1, 4, 1, 1, ModBlocks.deco_tungsten, null, false); + fillWithMetadataBlocks(world, box, 3, 2, 1, 4, 2, 1, ModBlocks.tape_recorder, northMeta, null, 0, false); + placeBlockAtCurrentPosition(world, ModBlocks.radiorec, southMeta, 2, 2, 2, box); + placeRandomBobble(world, box, rand, sizeX - 1, 2, 2); + fillWithMetadataBlocks(world, box, sizeX - 1, 1, 3, sizeX - 1, 2, 3, ModBlocks.tape_recorder, eastMeta, null, 0, false); + //OutsideDeco + fillWithMetadataBlocks(world, box, 0, 1, 2, 0, 2, 2, ModBlocks.steel_poles, eastMeta, null, 0, false); + placeBlockAtCurrentPosition(world, ModBlocks.pole_satellite_receiver, eastMeta, 0, sizeY - 1, 2, box); + fillWithBlocks(world, box, 0, sizeY, 2, sizeX - 1, sizeY, 2, ModBlocks.steel_roof, null, false); + placeBlockAtCurrentPosition(world, ModBlocks.steel_roof, 0, sizeX - 1, sizeY, 3, box); + + return false; + } + + } + + +}