Preliminary BunkerComponents

This commit is contained in:
Vaern 2023-05-29 20:37:34 -07:00
parent 87a87738ba
commit cd4c976dd7
12 changed files with 1012 additions and 382 deletions

View File

@ -2,34 +2,15 @@ package com.hbm.items.tool;
import java.util.List;
import com.hbm.blocks.ModBlocks;
import com.hbm.blocks.rail.IRailNTM;
import com.hbm.blocks.rail.IRailNTM.RailContext;
import com.hbm.explosion.vanillant.ExplosionVNT;
import com.hbm.explosion.vanillant.standard.BlockAllocatorBulkie;
import com.hbm.explosion.vanillant.standard.BlockMutatorBulkie;
import com.hbm.explosion.vanillant.standard.BlockProcessorStandard;
import com.hbm.explosion.vanillant.standard.EntityProcessorStandard;
import com.hbm.explosion.vanillant.standard.ExplosionEffectStandard;
import com.hbm.explosion.vanillant.standard.PlayerProcessorStandard;
import com.hbm.lib.Library;
import com.hbm.packet.PacketDispatcher;
import com.hbm.packet.PlayerInformPacket;
import com.hbm.util.ParticleUtil;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.world.feature.OilSpot;
import com.hbm.world.gen.component.BunkerComponents;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.StructureBoundingBox;
public class ItemWandD extends Item {
@ -43,13 +24,13 @@ public class ItemWandD extends Item {
if(pos != null) {
ExplosionVNT vnt = new ExplosionVNT(world, pos.hitVec.xCoord, pos.hitVec.yCoord, pos.hitVec.zCoord, 7);
/*ExplosionVNT vnt = new ExplosionVNT(world, pos.hitVec.xCoord, pos.hitVec.yCoord, pos.hitVec.zCoord, 7);
vnt.setBlockAllocator(new BlockAllocatorBulkie(60));
vnt.setBlockProcessor(new BlockProcessorStandard().withBlockEffect(new BlockMutatorBulkie(ModBlocks.block_slag)).setNoDrop());
vnt.setEntityProcessor(new EntityProcessorStandard());
vnt.setPlayerProcessor(new PlayerProcessorStandard());
vnt.setSFX(new ExplosionEffectStandard());
vnt.explode();
vnt.explode();*/
/*TimeAnalyzer.startCount("setBlock");
world.setBlock(pos.blockX, pos.blockY, pos.blockZ, Blocks.dirt);
@ -71,20 +52,12 @@ public class ItemWandD extends Item {
tom.destructionRange = 600;
world.spawnEntityInWorld(tom);*/
/*ItemStack itemStack = new ItemStack(ModItems.book_lore);
BookLoreType.setTypeForStack(itemStack, BookLoreType.BOOK_IODINE);
player.inventory.addItemStackToInventory(itemStack);
player.inventoryContainer.detectAndSendChanges();*/
//use sparingly
/*int k = ((pos.blockX >> 4) << 4) + 8;
int k = ((pos.blockX >> 4) << 4) + 8;
int l = ((pos.blockZ >> 4) << 4) + 8;
MapGenBunker.Start start = new MapGenBunker.Start(world, world.rand, pos.blockX >> 4, pos.blockZ >> 4);
start.generateStructure(world, world.rand, new StructureBoundingBox(k - 124, l - 124, k + 15 + 124, l + 15 + 124));*/
//MapGenStronghold.Start startS = new MapGenStronghold.Start(world, world.rand, pos.blockX >> 4, pos.blockZ >> 4);
//startS.generateStructure(world, world.rand, new StructureBoundingBox(k - 124, l - 124, k + 15 + 124, l + 15 + 124));
BunkerComponents.BunkerStart start = new BunkerComponents.BunkerStart(world, world.rand, pos.blockX >> 4, pos.blockZ >> 4);
start.generateStructure(world, world.rand, new StructureBoundingBox(k - 124, l - 124, k + 15 + 124, l + 15 + 124));
/*EntityNukeTorex torex = new EntityNukeTorex(world);
torex.setPositionAndRotation(pos.blockX, pos.blockY + 1, pos.blockZ, 0, 0);

View File

@ -1,14 +1,16 @@
package com.hbm.lib;
import com.hbm.world.worldgen.MapGenNTMFeatures;
import com.hbm.world.worldgen.NTMWorldGenerator;
import com.hbm.world.worldgen.components.CivilianFeatures;
import com.hbm.world.worldgen.components.OfficeFeatures;
import com.hbm.world.worldgen.components.RuinFeatures;
import com.hbm.world.gen.MapGenNTMFeatures;
import com.hbm.world.gen.NTMWorldGenerator;
import com.hbm.world.gen.component.BunkerComponents;
import com.hbm.world.gen.component.CivilianFeatures;
import com.hbm.world.gen.component.OfficeFeatures;
import com.hbm.world.gen.component.RuinFeatures;
import cpw.mods.fml.common.IWorldGenerator;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.world.gen.structure.MapGenStructureIO;
import net.minecraftforge.common.MinecraftForge;
public class HbmWorld {
@ -24,7 +26,10 @@ public class HbmWorld {
registerNTMFeatures();
registerWorldGen(new HbmWorldGen(), 1);
registerWorldGen(new NTMWorldGenerator(), 1); //Ideally, move everything over from HbmWorldGen to NTMWorldGenerator
NTMWorldGenerator worldGenerator = new NTMWorldGenerator();
registerWorldGen(worldGenerator, 1); //Ideally, move everything over from HbmWorldGen to NTMWorldGenerator
MinecraftForge.EVENT_BUS.register(worldGenerator);
//registerWorldGen(new WorldGenTest(), 1);
}
@ -37,5 +42,6 @@ public class HbmWorld {
CivilianFeatures.registerComponents();
OfficeFeatures.registerComponents();
RuinFeatures.registerComponents();
BunkerComponents.registerComponents();
}
}

View File

@ -1,4 +1,4 @@
package com.hbm.world.worldgen;
package com.hbm.world.gen;
import java.util.Arrays;
import java.util.Iterator;
@ -7,9 +7,9 @@ import java.util.Random;
import com.hbm.config.GeneralConfig;
import com.hbm.config.StructureConfig;
import com.hbm.world.worldgen.components.CivilianFeatures.*;
import com.hbm.world.worldgen.components.OfficeFeatures.*;
import com.hbm.world.worldgen.components.RuinFeatures.*;
import com.hbm.world.gen.component.CivilianFeatures.*;
import com.hbm.world.gen.component.OfficeFeatures.*;
import com.hbm.world.gen.component.RuinFeatures.*;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
@ -99,10 +99,8 @@ public class MapGenNTMFeatures extends MapGenStructure {
public Start(World world, Random rand, int chunkX, int chunkZ) {
super(chunkX, chunkZ);
BiomeGenBase biome = world.getBiomeGenForCoords(chunkX * 16 + 8, chunkZ * 16 + 8);
int posY = world.getHeightValue(chunkX * 16 + 8, chunkZ * 16 + 8);
if(posY == 0)
posY = world.getTopSolidOrLiquidBlock(chunkX * 16 + 8, chunkZ * 16 + 8);
BiomeGenBase biome = world.getBiomeGenForCoords(chunkX * 16 + 8, chunkZ * 16 + 8); //Only gets the biome in the corner of the chunk.
final int posY = 64; // Terrain *does not exist* at this stage - at least, for vanilla. Here it has to be called after, but better safe than sorry.
/*
* Probably want to use nextInt() to increase the structures of rarity here. As a fallback, you could have generic stone brick/useless block ruins that will always be chosen if the

View File

@ -0,0 +1,126 @@
package com.hbm.world.gen;
import java.util.Random;
import com.hbm.blocks.ModBlocks;
import com.hbm.blocks.generic.BlockNTMFlower.EnumFlowerType;
import com.hbm.config.StructureConfig;
import cpw.mods.fml.common.IWorldGenerator;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
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.minecraftforge.event.terraingen.DecorateBiomeEvent.Decorate;
import net.minecraftforge.event.terraingen.InitMapGenEvent.EventType;
import net.minecraftforge.event.terraingen.PopulateChunkEvent;
import static net.minecraftforge.event.terraingen.TerrainGen.*;
import net.minecraftforge.event.world.WorldEvent;
public class NTMWorldGenerator implements IWorldGenerator {
private MapGenNTMFeatures scatteredFeatureGenerator = new MapGenNTMFeatures();
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) {
scatteredFeatureGenerator = (MapGenNTMFeatures) getModdedMapGen(new MapGenNTMFeatures(), 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());
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) return;
switch (event.world.provider.dimensionId) {
case -1:
break;
case 0:
generateOverworldStructures(event.world, event.chunkProvider, event.chunkX, event.chunkZ);
break;
case 1:
break;
}
}
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.scatteredFeatureGenerator.func_151539_a(chunkProvider, world, chunkX, chunkZ, ablock);
this.scatteredFeatureGenerator.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
if(StructureConfig.enableStructures) generateOverworldStructures(world, chunkGenerator, chunkX, chunkZ); //Do it through the post-population generation directly
}
final int posX = (chunkX << 4) + 8;
final int posZ = (chunkZ << 4) + 8;
BiomeGenBase biome = world.getBiomeGenForCoords(posX, posZ);
/* 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). */
}
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;
}
}

View File

@ -0,0 +1,247 @@
package com.hbm.world.gen;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraft.world.gen.structure.StructureComponent;
import net.minecraft.world.gen.structure.StructureStart;
/** This makes so much more sense! OOP wasn't confusing sometimes, you were just retarded! */
public class ProceduralStructureStart extends StructureStart {
/** List of queued components to call buildComponent on randomly. Iterated over until hard limits reached. */
public List<StructureComponent> queuedComponents = new ArrayList();
/** List of the component weights for this particular structure -- weights removed as components are 'used up.' */
protected List<Weight> componentWeightList; //Make sure to initialize the array list to the weight array size, since might as well
public ProceduralStructureStart() { }
public ProceduralStructureStart(int chunkX, int chunkZ) {
super(chunkX, chunkZ);
}
/** 'starter' is just the starting component, so like a village well. meant to be nice and convenient and not needing a super necessarily. */
public ProceduralStructureStart buildStart(World world, Random rand, StructureComponent starter, Weight...weights) {
prepareWeights(weights);
components.add(starter);
queuedComponents.add(starter);
while(!queuedComponents.isEmpty()) {
final int i = rand.nextInt(queuedComponents.size());
StructureComponent component = queuedComponents.remove(i);
if(component instanceof ProceduralComponent)
((ProceduralComponent) component).buildComponent(this, rand); //additional components are added to the list; the 'last component' is the caller already.
}
this.updateBoundingBox();
return this;
}
public void prepareWeights(Weight...weights) {
componentWeightList = new ArrayList(weights.length);
for(int i = 0; i < weights.length; i++) {
weights[i].instancesSpawned = 0;
componentWeightList.add(weights[i]);
}
}
/** Reads from NBT. */
@Override
public void func_143017_b(NBTTagCompound nbt) {
}
/** Writes to NBT. */
@Override
public void func_143022_a(NBTTagCompound nbt) {
}
protected int getTotalWeight() {
boolean flag = false;
int totalWeight = 0;
Weight weight;
for(Iterator iterator = componentWeightList.iterator(); iterator.hasNext(); totalWeight += weight.weight) { //Iterates over the entire list to find the total weight
weight = (Weight) iterator.next();
if(weight.instanceLimit >= 0 && weight.instancesSpawned < weight.instanceLimit) //can more structure pieces be added, in general?
flag = true;
}
return flag ? totalWeight : -1;
}
protected StructureComponent getWeightedComponent(StructureComponent last, Random rand, int minX, int minY, int minZ, int coordMode, int componentType) {
int totalWeight = getTotalWeight();
if(totalWeight < 0)
return null;
for(int i = 0; i < 5; i++) {
int value = rand.nextInt(totalWeight); //Pick a random value, based on how many parts there are already
Iterator iterator = componentWeightList.iterator();
while(iterator.hasNext()) {
Weight weight = (Weight)iterator.next();
value -= weight.weight; //Iterate over the list until the value is less than 0
if(value < 0) {
if(!weight.canSpawnStructure(componentType, coordMode, last)) //Additional checks based on game state info preventing spawn? start from beginning
break;
StructureComponent component = weight.lambda.findValidPlacement(components, rand, minX, minY, minZ, coordMode, componentType); //Construct the chosen component
if(component != null) { //If it has been constructed, add it
weight.instancesSpawned++;
if(!weight.canSpawnMoreStructures()) //Structure can no longer be spawned regardless of game state? remove as an option
componentWeightList.remove(weight);
return component;
}
}
}
}
return null;
}
//might remove these, add hard limits so subclasses can create their own implementations
protected int sizeLimit = 50;
protected int distanceLimit = 64;
/** Gets the next valid component based on the structure start's members */
protected StructureComponent getNextValidComponent(StructureComponent last, Random rand, int minX, int minY, int minZ, int coordMode, int componentType) {
if(components.size() > sizeLimit) //Hard limit on amount of components
return null;
if(Math.abs(minX - (func_143019_e() * 16 + 8)) <= distanceLimit && Math.abs(minZ - (func_143018_f() * 16 + 8)) <= distanceLimit) { //Hard limit on spread of structure
StructureComponent structure = getWeightedComponent(last, rand, minX, minY, minZ, coordMode, componentType + 1); //Returns null if all checks fail
if(structure != null) {
this.components.add(structure); //Adds component to structure start list
this.queuedComponents.add(structure); //Add it to the list of queued components waiting to be built
}
return structure;
}
return null;
}
/** Useful utility method to automatically construct the appropriate structure bounding box; based on the getNextComponents below!<br>
* posX, posY, posZ represent the original anchor point of the structurecomponent (minX, minY, minZ).<br>
* offsetX, offsetY, offsetZ all add onto that point, meaning that offsets <b>will always move that anchor towards +x, +y, +z (in terms of south).</b><br>
* maxX, maxY, maxZ additionally are added to get the maximum x, y, z (obviously) in terms of south. An offset of 1 is subtracted, so these do not start at 0, and
* <b>refer to the ACTUAL dimensions of the component.</b><br>
* The initial anchor point is kind of arbitrary based on where it is in the door, so what really matters is keeping it consistent.
*/
public static StructureBoundingBox getComponentToAddBoundingBox(int posX, int posY, int posZ, int offsetX, int offsetY, int offsetZ, int maxX, int maxY, int maxZ, int coordMode) {
switch(coordMode) {
default:
case 0: return new StructureBoundingBox(posX + offsetX, posY + offsetY, posZ + offsetZ, posX + maxX - 1 + offsetX, posY + maxY - 1 + offsetY, posZ + maxZ - 1 + offsetZ); //South
case 1: return new StructureBoundingBox(posX - maxZ + 1 - offsetZ, posY + offsetY, posZ + offsetX, posX - offsetZ, posY + maxY - 1 + offsetY, posZ + maxX - 1 + offsetX); //West
case 2: return new StructureBoundingBox(posX - maxX + 1 - offsetX, posY + offsetY, posZ - maxZ + 1 - offsetZ, posX - offsetX, posY + maxY - 1 + offsetY, posZ + offsetZ); //North
case 3: return new StructureBoundingBox(posX + offsetZ, posY + offsetY, posZ - maxX + 1 - offsetX, posX + maxZ - 1 + offsetZ, posY + maxY - 1 + offsetY, posZ - offsetX); //East
}
}
/** no class-based multiple inheritance? */
public static interface ProceduralComponent {
public default void buildComponent(ProceduralStructureStart start, Random rand) { } //no class-based multiple inheritance?
/** Gets next component in the direction this component is facing.<br>'original' refers to the initial starting component (hard distance limits), 'components' refers to the StructureStart list.<br>
* offset and offsetY are added to the <b>anchor point of the new component<br>, referring to the minX and minY respectively (in terms of south).<br>
* An offset of 1 is added to the minZ anchor point, relative to south.
*/
public default StructureComponent getNextComponentNormal(ProceduralStructureStart start, StructureComponent caller, int coordMode, Random rand, int offset, int offsetY) {
StructureBoundingBox box = caller.getBoundingBox();
switch(coordMode) {
case 0: return start.getNextValidComponent(caller, rand, box.minX + offset, box.minY + offsetY, box.maxZ + 1, coordMode, caller.getComponentType()); //South
case 1: return start.getNextValidComponent(caller, rand, box.minX - 1, box.minY + offsetY, box.minZ + offset, coordMode, caller.getComponentType()); //West
case 2: return start.getNextValidComponent(caller, rand, box.maxX - offset, box.minY + offsetY, box.minZ - 1, coordMode, caller.getComponentType()); //North
case 3: return start.getNextValidComponent(caller, rand, box.maxX + 1, box.minY + offsetY, box.maxZ - offset, coordMode, caller.getComponentType()); //East
default: return null;
}
}
/** Gets next component in the opposite direction this component is facing. */
public default StructureComponent getNextComponentAntiNormal(ProceduralStructureStart start, StructureComponent caller, int coordMode, Random rand, int offset, int offsetY) {
StructureBoundingBox box = caller.getBoundingBox();
switch(coordMode) {
case 0: return start.getNextValidComponent(caller, rand, box.maxX - offset, box.minY + offsetY, box.minZ - 1, 2, caller.getComponentType()); //South
case 1: return start.getNextValidComponent(caller, rand, box.maxX + 1, box.minY + offsetY, box.maxZ - offset, 3, caller.getComponentType()); //West
case 2: return start.getNextValidComponent(caller, rand, box.minX + offset, box.minY + offsetY, box.maxZ + 1, 0, caller.getComponentType()); //North
case 3: return start.getNextValidComponent(caller, rand, box.minX - 1, box.minY + offsetY, box.minZ + offset, 1, caller.getComponentType()); //East
default: return null;
}
}
//Keep in mind for these methods: a given room would have its *actual entrance* opposite the side it is facing.
/** Gets next component, to the West (-X) <i>relative to this component. */
public default StructureComponent getNextComponentWest(ProceduralStructureStart start, StructureComponent caller, int coordMode, Random rand, int offset, int offsetY) {
StructureBoundingBox box = caller.getBoundingBox();
switch(coordMode) {
case 0: return start.getNextValidComponent(caller, rand, box.minX - 1, box.minY + offsetY, box.minZ + offset, 1, caller.getComponentType()); //South
case 1: return start.getNextValidComponent(caller, rand, box.maxX - offset, box.minY + offsetY, box.minZ - 1, 2, caller.getComponentType()); //West
case 2: return start.getNextValidComponent(caller, rand, box.maxX + 1, box.minY + offsetY, box.maxZ - offset, 3, caller.getComponentType()); //North
case 3: return start.getNextValidComponent(caller, rand, box.minX + offset, box.minY + offsetY, box.maxZ + 1, 0, caller.getComponentType()); //East
default: return null;
}
}
/** Gets next component, to the East (+X) <i>relative to this component. */
public default StructureComponent getNextComponentEast(ProceduralStructureStart start, StructureComponent caller, int coordMode, Random rand, int offset, int offsetY) {
StructureBoundingBox box = caller.getBoundingBox();
switch(coordMode) {
case 0: return start.getNextValidComponent(caller, rand, box.maxX + 1, box.minY + offsetY, box.maxZ - offset, 3, caller.getComponentType()); //South
case 1: return start.getNextValidComponent(caller, rand, box.minX + offset, box.minY + offsetY, box.maxZ + 1, 0, caller.getComponentType()); //West
case 2: return start.getNextValidComponent(caller, rand, box.minX - 1, box.minY + offsetY, box.minZ + offset, 1, caller.getComponentType()); //North
case 3: return start.getNextValidComponent(caller, rand, box.maxX - offset, box.minY + offsetY, box.minZ - 1, 2, caller.getComponentType()); //East
default: return null;
}
}
}
/** Returns a new instance of this structureComponent, or null if not able to be placed.<br>Based on bounding box checks. Please use a method reference in the component. */
@FunctionalInterface
protected static interface instantiateStructure {
StructureComponent findValidPlacement(List components, Random rand, int minX, int minY, int minZ, int coordMode, int componentType);
}
protected static class Weight {
public final instantiateStructure lambda; //Read above
public final int weight; //Weight of this component
public int instancesSpawned; //How many components spawned?
public int instanceLimit; //Limit on amount of components: -1 for no limit
public Weight(int weight, int limit, instantiateStructure lambda) {
this.weight = weight;
this.instanceLimit = limit;
this.lambda = lambda;
}
//Checks if another structure can be spawned based on input data
public boolean canSpawnStructure(int componentAmount, int coordMode, StructureComponent component) {
return this.instanceLimit < 0 || this.instancesSpawned < this.instanceLimit;
}
//Checks if another structure can be spawned at all (used to flag for removal from the list)
public boolean canSpawnMoreStructures() {
return this.instanceLimit < 0 || this.instancesSpawned < this.instanceLimit;
}
}
}

View File

@ -0,0 +1,547 @@
package com.hbm.world.gen.component;
import java.util.List;
import java.util.Random;
import com.hbm.blocks.ModBlocks;
import com.hbm.lib.HbmChestContents;
import com.hbm.world.gen.ProceduralStructureStart;
import com.hbm.world.gen.ProceduralStructureStart.ProceduralComponent;
import com.hbm.world.gen.component.Component.ConcreteBricks;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
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;
public class BunkerComponents {
public static class BunkerStart extends ProceduralStructureStart {
public BunkerStart(World world, Random rand, int chunkX, int chunkZ) {
super(chunkX, chunkZ);
this.sizeLimit = 7 + rand.nextInt(6);
this.distanceLimit = 40;
final int x = chunkX * 16 + 8;
final int z = chunkZ * 16 + 8;
Weight[] weights = new Weight[] {
new Weight(6, 3, Corridor::findValidPlacement),
new Weight(7, 4, BedroomL::findValidPlacement),
new Weight(10, 3, FunJunction::findValidPlacement),
new Weight(5, 2, BathroomL::findValidPlacement),
};
StructureComponent starter = new StartingHub(rand, x, z);
buildStart(world, rand, starter, weights);
this.markAvailableHeight(world, rand, 20);
}
}
public static void registerComponents() {
MapGenStructureIO.func_143031_a(StartingHub.class, "NTMBStartingHub");
MapGenStructureIO.func_143031_a(Corridor.class, "NTMBCorridor");
MapGenStructureIO.func_143031_a(BedroomL.class, "NTMBBedroomL");
MapGenStructureIO.func_143031_a(FunJunction.class, "NTMBFunJunction");
MapGenStructureIO.func_143031_a(BathroomL.class, "NTMBBathroomL");
//TODO more rooms for more variety
}
//why are we still doing this?
private static ConcreteBricks ConcreteBricks = new ConcreteBricks();
public static class StartingHub extends Component implements ProceduralComponent {
private boolean[] paths = new boolean[3];
public StartingHub() { }
public StartingHub(Random rand, int x, int z) {
super(rand, x, 64, z, 7, 5, 7);
}
public StartingHub(int componentType, StructureBoundingBox box, int coordMode) {
super(componentType);
this.boundingBox = box;
this.coordBaseMode = coordMode;
}
/** write to nbt */
@Override
protected void func_143012_a(NBTTagCompound nbt) {
super.func_143012_a(nbt);
for(int i = 0; i < paths.length; i++)
nbt.setBoolean("p" + i, paths[i]);
}
/** read from nbt */
@Override
protected void func_143011_b(NBTTagCompound nbt) {
super.func_143011_b(nbt);
for(int i = 0; i < paths.length; i++)
paths[i] = nbt.getBoolean("p" + i);
}
@Override
public void buildComponent(ProceduralStructureStart start, Random rand) {
paths[0] = this.getNextComponentEast(start, this, coordBaseMode, rand, 5, 1) != null;
paths[1] = this.getNextComponentAntiNormal(start, this, coordBaseMode, rand, 4, 1) != null;
paths[2] = this.getNextComponentWest(start, this, coordBaseMode, rand, 3, 1) != null;
}
@Override
public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) {
fillWithAir(world, box, 1, 1, 1, 6, 3, 6);
//floor
fillWithMetadataBlocks(world, box, 1, 0, 1, 6, 0, 6, ModBlocks.vinyl_tile, 1);
//ceiling
fillWithBlocks(world, box, 1, 4, 1, 6, 4, 6, ModBlocks.vinyl_tile);
//upper shield
fillWithBlocks(world, box, 1, 4, 4, 3, 4, 6, ModBlocks.reinforced_stone);
fillWithBlocks(world, box, 0, 5, 0, 7, 5, 7, ModBlocks.reinforced_stone);
//walls
fillWithRandomizedBlocks(world, box, 0, 0, 0, 0, 4, 7, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 1, 0, 7, 6, 4, 7, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 7, 0, 0, 7, 4, 7, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 1, 0, 0, 6, 4, 0, rand, ConcreteBricks);
//meh, fix the area later
final int hpos = Component.getAverageHeight(world, boundingBox, box, componentType - boundingBox.minY);
//top hatch
placeBlockAtCurrentPosition(world, ModBlocks.concrete_slab, 1, 0, hpos, 5, box);
fillWithMetadataBlocks(world, box, 1, hpos, 4, 1, hpos, 6, ModBlocks.concrete_smooth_stairs, getStairMeta(0));
placeBlockAtCurrentPosition(world, ModBlocks.concrete_slab, 1, 2, hpos, 3, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, getStairMeta(2), 2, hpos, 4, box);
placeBlockAtCurrentPosition(world, Blocks.trapdoor, getDecoModelMeta(8) >> 2, 2, hpos, 5, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, getStairMeta(3), 2, hpos, 6, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_slab, 1, 2, hpos, 7, box);
fillWithMetadataBlocks(world, box, 3, hpos, 4, 3, hpos, 6, ModBlocks.concrete_smooth_stairs, getStairMeta(1));
placeBlockAtCurrentPosition(world, ModBlocks.concrete_slab, 1, 4, hpos, 5, box);
//tunnel downwards
fillWithBlocks(world, box, 1, 6, 4, 1, hpos - 1, 6, ModBlocks.reinforced_stone);
fillWithBlocks(world, box, 2, 1, 6, 2, hpos - 1, 6, ModBlocks.reinforced_stone);
fillWithBlocks(world, box, 3, 6, 4, 3, hpos - 1, 6, ModBlocks.reinforced_stone);
fillWithBlocks(world, box, 2, 6, 4, 2, hpos - 1, 4, ModBlocks.reinforced_stone);
fillWithMetadataBlocks(world, box, 2, 1, 5, 2, hpos - 1, 5, ModBlocks.ladder_sturdy, getDecoMeta(2)); //double check meta
/* DECO */
//lamps
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 2, 5, 2, box);
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 5, 5, 2, box);
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 5, 5, 5, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 2, 4, 2, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 5, 4, 2, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 5, 4, 5, box);
//machine
placeBlockAtCurrentPosition(world, ModBlocks.deco_tungsten, 0, 3, 1, 6, box);
generateInvContents(world, box, rand, Blocks.chest, getDecoMeta(2), 4, 1, 6, HbmChestContents.antenna/*TODO change */, 5);
placeBlockAtCurrentPosition(world, ModBlocks.deco_tungsten, 0, 5, 1, 6, box);
fillWithMetadataBlocks(world, box, 3, 2, 6, 5, 2, 6, ModBlocks.concrete_smooth_stairs, getStairMeta(2) | 4);
fillWithMetadataBlocks(world, box, 3, 3, 6, 5, 3, 6, ModBlocks.tape_recorder, getDecoMeta(2));
//desk
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, getStairMeta(1) | 4, 3, 1, 4, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, getStairMeta(3) | 4, 4, 1, 4, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, getStairMeta(0) | 4, 5, 1, 4, box);
placeBlockAtCurrentPosition(world, ModBlocks.deco_computer, getDecoModelMeta(0), 4, 2, 4, box);
//clear out entryways based on path
if(paths[0]) fillWithAir(world, box, 7, 1, 2, 7, 2, 3);
if(paths[1]) fillWithAir(world, box, 3, 1, 0, 4, 2, 0);
if(paths[2]) fillWithAir(world, box, 0, 1, 2, 0, 2, 3);
return true;
}
}
public static class Corridor extends Component implements ProceduralComponent {
private boolean path;
public Corridor() { }
public Corridor(int componentType, StructureBoundingBox box, int coordMode) {
super(componentType);
this.boundingBox = box;
this.coordBaseMode = coordMode;
}
/** write to nbt */
@Override
protected void func_143012_a(NBTTagCompound nbt) {
super.func_143012_a(nbt);
nbt.setBoolean("p", path);
}
/** read from nbt */
@Override
protected void func_143011_b(NBTTagCompound nbt) {
super.func_143011_b(nbt);
path = nbt.getBoolean("p");
}
@Override
public void buildComponent(ProceduralStructureStart start, Random rand) {
path = this.getNextComponentNormal(start, this, coordBaseMode, rand, 3, 1) != null;
}
@Override
public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) {
fillWithAir(world, box, 1, 1, 1, 4, 3, 5);
//floor
fillWithMetadataBlocks(world, box, 1, 0, 1, 4, 0, 5, ModBlocks.vinyl_tile, 1);
//ceiling
fillWithBlocks(world, box, 1, 4, 1, 4, 4, 5, ModBlocks.vinyl_tile);
//upper shield
fillWithBlocks(world, box, 0, 5, 0, 5, 5, 6, ModBlocks.reinforced_stone);
//walls
fillWithRandomizedBlocks(world, box, 0, 0, 0, 0, 4, 6, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 1, 0, 6, 4, 4, 6, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 5, 0, 0, 5, 4, 6, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 1, 0, 0, 4, 4, 0, rand, ConcreteBricks);
//TODO different deco types? maybe plants or vending machines?
//save it to nbt either way
/* DECO */
//lamps
fillWithBlocks(world, box, 2, 5, 3, 3, 5, 3, ModBlocks.reinforced_lamp_off);
fillWithBlocks(world, box, 2, 4, 3, 3, 4, 3, ModBlocks.fan);
//table w/ chairs
final int stairMetaS = getStairMeta(3);
final int stairMetaN = getStairMeta(2);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaS, 1, 1, 2, box);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaN, 1, 1, 4, box);
placeBlockAtCurrentPosition(world, Blocks.fence, 0, 1, 1, 3, box);
placeBlockAtCurrentPosition(world, Blocks.wooden_pressure_plate, 1, 1, 2, 3, box);
//desk w/ computer
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaS | 4, 4, 1, 2, box);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaN, 4, 1, 4, box);
placeBlockAtCurrentPosition(world, ModBlocks.deco_computer, getDecoModelMeta(1), 4, 2, 2, box);
//doors
placeDoor(world, box, ModBlocks.door_bunker, 1, true, rand.nextBoolean(), 2, 1, 0);
placeDoor(world, box, ModBlocks.door_bunker, 1, false, rand.nextBoolean(), 3, 1, 0);
if(path) fillWithAir(world, box, 2, 1, 6, 3, 2, 6);
return true;
}
public static StructureComponent findValidPlacement(List components, Random rand, int x, int y, int z, int coordMode, int type) {
StructureBoundingBox box = ProceduralStructureStart.getComponentToAddBoundingBox(x, y, z, -3, -1, 0, 6, 6, 7, coordMode);
return box.minY > 10 && StructureComponent.findIntersecting(components, box) == null ? new Corridor(type, box, coordMode) : null;
}
}
public static class BedroomL extends Component implements ProceduralComponent {
private boolean path;
public BedroomL() { }
public BedroomL(int componentType, StructureBoundingBox box, int coordMode) {
super(componentType);
this.boundingBox = box;
this.coordBaseMode = coordMode;
}
/** write to nbt */
@Override
protected void func_143012_a(NBTTagCompound nbt) {
super.func_143012_a(nbt);
nbt.setBoolean("p", path);
}
/** read from nbt */
@Override
protected void func_143011_b(NBTTagCompound nbt) {
super.func_143011_b(nbt);
path = nbt.getBoolean("p");
}
@Override
public void buildComponent(ProceduralStructureStart start, Random rand) {
path = this.getNextComponentWest(start, this, coordBaseMode, rand, 9, 1) != null;
}
@Override
public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) {
fillWithAir(world, box, 4, 1, 1, 8, 3, 4);
fillWithAir(world, box, 1, 1, 5, 8, 3, 9);
//floor
fillWithMetadataBlocks(world, box, 4, 0, 1, 8, 0, 4, ModBlocks.vinyl_tile, 1);
fillWithMetadataBlocks(world, box, 1, 0, 5, 8, 0, 9, ModBlocks.vinyl_tile, 1);
//ceiling
fillWithBlocks(world, box, 4, 4, 1, 8, 4, 4, ModBlocks.vinyl_tile);
fillWithBlocks(world, box, 1, 4, 5, 8, 4, 9, ModBlocks.vinyl_tile);
//upper shield
fillWithBlocks(world, box, 3, 5, 0, 9, 5, 3, ModBlocks.reinforced_stone);
fillWithBlocks(world, box, 0, 5, 4, 9, 5, 10, ModBlocks.reinforced_stone);
//walls
fillWithRandomizedBlocks(world, box, 0, 0, 4, 0, 4, 10, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 1, 0, 10, 8, 4, 10, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 9, 0, 0, 9, 4, 10, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 4, 0, 0, 8, 4, 0, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 3, 0, 0, 3, 4, 4, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 1, 0, 4, 2, 4, 4, rand, ConcreteBricks);
/* DECO */
//lamps
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 3, 5, 7, box);
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 6, 5, 7, box);
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 6, 5, 3, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 3, 4, 7, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 6, 4, 7, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 6, 4, 3, box);
//Beds w/ table
final int stairMetaW = getStairMeta(0);
final int stairMetaE = getStairMeta(1);
final int stairMetaN = getStairMeta(2);
final int stairMetaS = getStairMeta(3);
placeBed(world, box, 1, 5, 1, 1);
placeBed(world, box, 1, 5, 1, 3);
placeBed(world, box, 2, 3, 1, 6);
placeBed(world, box, 2, 1, 1, 6);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaE | 4, 4, 1, 2, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaE | 4, 4, 1, 4, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaS | 4, 4, 1, 5, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaS | 4, 2, 1, 5, box);
placeBlockAtCurrentPosition(world, ModBlocks.radiorec, getDecoMeta(4), 4, 2, 4, box);
//table w/ microwave
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaS | 4, 8, 1, 3, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaN | 4, 8, 1, 4, box);
placeBlockAtCurrentPosition(world, Blocks.noteblock, 0, 8, 1, 5, box);
placeBlockAtCurrentPosition(world, ModBlocks.machine_microwave, getDecoMeta(4), 8, 2, 4, box);
//desk w/ computer
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaW | 4, 6, 1, 9, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaN | 4, 5, 1, 9, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaE | 4, 4, 1, 9, box);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaS, 5, 1, 8, box);
placeBlockAtCurrentPosition(world, ModBlocks.deco_computer, getDecoModelMeta(0), 5, 2, 9, box);
generateInvContents(world, box, rand, ModBlocks.filing_cabinet, getDecoModelMeta(0), 3, 1, 9, HbmChestContents.antenna/*TODO change */, 5);
//lockers
generateInvContents(world, box, rand, Blocks.chest, getDecoMeta(4), 8, 1, 7, HbmChestContents.antenna/*TODO change */, 3);
generateInvContents(world, box, rand, Blocks.chest, getDecoMeta(4), 8, 2, 7, HbmChestContents.antenna/*TODO change */, 3);
fillWithBlocks(world, box, 8, 1, 8, 8, 2, 8, ModBlocks.deco_tungsten);
generateInvContents(world, box, rand, Blocks.chest, getDecoMeta(4), 8, 1, 9, HbmChestContents.antenna/*TODO change */, 3);
generateInvContents(world, box, rand, Blocks.chest, getDecoMeta(4), 8, 2, 9, HbmChestContents.antenna/*TODO change */, 3);
fillWithMetadataBlocks(world, box, 8, 3, 7, 8, 3, 9, Blocks.trapdoor, getDecoModelMeta(2) >> 2);
//doors
placeDoor(world, box, ModBlocks.door_bunker, 1, true, rand.nextBoolean(), 7, 1, 0);
placeDoor(world, box, ModBlocks.door_bunker, 1, false, rand.nextBoolean(), 8, 1, 0);
if(path) fillWithAir(world, box, 0, 1, 8, 0, 2, 9);
return true;
}
public static StructureComponent findValidPlacement(List components, Random rand, int x, int y, int z, int coordMode, int type) {
StructureBoundingBox box = ProceduralStructureStart.getComponentToAddBoundingBox(x, y, z, -8, -1, 0, 10, 6, 11, coordMode);
return box.minY > 10 && StructureComponent.findIntersecting(components, box) == null ? new BedroomL(type, box, coordMode) : null;
}
}
public static class FunJunction extends Component implements ProceduralComponent {
private boolean[] paths = new boolean[2];
public FunJunction() { }
public FunJunction(int componentType, StructureBoundingBox box, int coordMode) {
super(componentType);
this.boundingBox = box;
this.coordBaseMode = coordMode;
}
/** write to nbt */
@Override
protected void func_143012_a(NBTTagCompound nbt) {
super.func_143012_a(nbt);
for(int i = 0; i < paths.length; i++)
nbt.setBoolean("p" + i, paths[i]);
}
/** read from nbt */
@Override
protected void func_143011_b(NBTTagCompound nbt) {
super.func_143011_b(nbt);
for(int i = 0; i < paths.length; i++)
paths[i] = nbt.getBoolean("p" + i);
}
@Override
public void buildComponent(ProceduralStructureStart start, Random rand) {
paths[0] = this.getNextComponentEast(start, this, coordBaseMode, rand, 6, 1) != null;
paths[1] = this.getNextComponentNormal(start, this, coordBaseMode, rand, 5, 1) != null;
}
@Override
public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) {
fillWithAir(world, box, 1, 1, 1, 6, 3, 10);
//floor
fillWithMetadataBlocks(world, box, 1, 0, 1, 6, 0, 10, ModBlocks.vinyl_tile, 1);
//ceiling
fillWithBlocks(world, box, 1, 4, 1, 6, 4, 10, ModBlocks.vinyl_tile);
//upper shield
fillWithBlocks(world, box, 0, 5, 0, 7, 5, 11, ModBlocks.reinforced_stone);
//walls
fillWithRandomizedBlocks(world, box, 0, 0, 0, 0, 4, 11, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 1, 0, 11, 6, 4, 11, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 7, 0, 0, 7, 4, 11, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 1, 0, 0, 6, 4, 0, rand, ConcreteBricks);
/* DECO */
//lamps
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 2, 5, 3, box);
fillWithBlocks(world, box, 5, 5, 5, 5, 5, 6, ModBlocks.reinforced_lamp_off);
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 2, 5, 8, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 2, 4, 3, box);
fillWithBlocks(world, box, 5, 4, 5, 5, 4, 6, ModBlocks.fan);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 2, 4, 8, box);
//couches w/ tables
final int stairMetaW = getStairMeta(0);
final int stairMetaE = getStairMeta(1);
final int stairMetaN = getStairMeta(2);
final int stairMetaS = getStairMeta(3);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaE, 1, 1, 1, box);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaS, 2, 1, 1, box);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaW, 3, 1, 1, box);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaS, 1, 1, 4, box);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaE, 1, 1, 5, box);
fillWithMetadataBlocks(world, box, 1, 1, 6, 2, 1, 6, Blocks.oak_stairs, stairMetaN);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaW, 3, 1, 6, box);
placeBlockAtCurrentPosition(world, Blocks.fence, 0, 1, 1, 3, box);
placeBlockAtCurrentPosition(world, Blocks.wooden_pressure_plate, 0, 1, 2, 3, box);
placeBlockAtCurrentPosition(world, Blocks.fence, 0, 3, 1, 4, box);
placeBlockAtCurrentPosition(world, Blocks.wooden_pressure_plate, 0, 3, 2, 4, box);
//table & chest
placeBlockAtCurrentPosition(world, Blocks.fence, 0, 6, 1, 2, box);
placeBlockAtCurrentPosition(world, Blocks.wooden_pressure_plate, 0, 6, 2, 2, box);
generateInvContents(world, box, rand, Blocks.chest, getDecoMeta(4), 6, 1, 3, HbmChestContents.antenna/*TODO change */, 7);
//desk w/ computer + bobblehead
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaS | 4, 1, 1, 8, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaE | 4, 1, 1, 9, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_smooth_stairs, stairMetaN | 4, 1, 1, 10, box);
placeBlockAtCurrentPosition(world, Blocks.oak_stairs, stairMetaS, 2, 1, 8, box);
placeBlockAtCurrentPosition(world, ModBlocks.deco_computer, getDecoModelMeta(3), 1, 2, 9, box);
if(rand.nextBoolean()) placeRandomBobble(world, box, rand, 1, 2, 8);
//jukebox
fillWithBlocks(world, box, 6, 1, 8, 6, 2, 8, Blocks.noteblock);
placeBlockAtCurrentPosition(world, ModBlocks.deco_tungsten, 0, 6, 1, 9, box);
placeBlockAtCurrentPosition(world, ModBlocks.tape_recorder, getDecoMeta(4), 6, 2, 9, box);
fillWithBlocks(world, box, 6, 3, 8, 6, 3, 9, ModBlocks.concrete_slab);
placeBlockAtCurrentPosition(world, Blocks.lever, getDecoMeta(2), 5, 1, 9, box); //double-check meta
//doors
placeDoor(world, box, ModBlocks.door_bunker, 1, true, rand.nextBoolean(), 4, 1, 0);
placeDoor(world, box, ModBlocks.door_bunker, 1, false, rand.nextBoolean(), 5, 1, 0);
if(paths[0]) fillWithAir(world, box, 7, 1, 5, 7, 2, 6);
if(paths[1]) fillWithAir(world, box, 4, 1, 11, 5, 2, 11);
return true;
}
public static StructureComponent findValidPlacement(List components, Random rand, int x, int y, int z, int coordMode, int type) {
StructureBoundingBox box = ProceduralStructureStart.getComponentToAddBoundingBox(x, y, z, -5, -1, 0, 8, 6, 12, coordMode);
return box.minY > 10 && StructureComponent.findIntersecting(components, box) == null ? new FunJunction(type, box, coordMode) : null;
}
}
public static class BathroomL extends Component implements ProceduralComponent {
private boolean path;
public BathroomL() { }
public BathroomL(int componentType, StructureBoundingBox box, int coordMode) {
super(componentType);
this.boundingBox = box;
this.coordBaseMode = coordMode;
}
/** write to nbt */
@Override
protected void func_143012_a(NBTTagCompound nbt) {
super.func_143012_a(nbt);
nbt.setBoolean("p", path);
}
/** read from nbt */
@Override
protected void func_143011_b(NBTTagCompound nbt) {
super.func_143011_b(nbt);
path = nbt.getBoolean("p");
}
@Override
public void buildComponent(ProceduralStructureStart start, Random rand) {
path = this.getNextComponentEast(start, this, coordBaseMode, rand, 3, 1) != null;
}
@Override
public boolean addComponentParts(World world, Random rand, StructureBoundingBox box) {
fillWithAir(world, box, 1, 1, 1, 7, 3, 9);
//floor
fillWithMetadataBlocks(world, box, 1, 0, 1, 7, 0, 9, ModBlocks.vinyl_tile, 1);
//ceiling
fillWithBlocks(world, box, 1, 4, 1, 7, 4, 9, ModBlocks.vinyl_tile);
//upper shield
fillWithBlocks(world, box, 0, 5, 0, 8, 5, 10, ModBlocks.reinforced_stone);
//walls
fillWithRandomizedBlocks(world, box, 0, 0, 0, 0, 4, 10, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 1, 0, 10, 7, 4, 10, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 8, 0, 0, 8, 4, 10, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 1, 0, 0, 7, 4, 0, rand, ConcreteBricks);
/* DECO */
//lamps
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 2, 5, 3, box);
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 2, 5, 7, box);
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 5, 5, 7, box);
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_lamp_off, 0, 5, 5, 3, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 2, 4, 3, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 2, 4, 7, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 5, 4, 7, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, 0, 5, 4, 3, box);
//sinks
for(int i = 2; i <= 8; i += 2) {
placeBlockAtCurrentPosition(world, Blocks.cauldron, rand.nextInt(4), 1, 1, i, box);
placeBlockAtCurrentPosition(world, ModBlocks.concrete_slab, 8, 1, 1, i + 1, box);
placeBlockAtCurrentPosition(world, Blocks.tripwire_hook, getTripwireMeta(3), 1, 2, i, box);
}
//hand-dryers (industrial-strength)
placeBlockAtCurrentPosition(world, ModBlocks.steel_beam, 3, 4, 1, 9, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, getDecoMeta(2), 4, 2, 9, box);
placeBlockAtCurrentPosition(world, Blocks.stone_button, 2, 3, 2, 9, box); //TODO button meta
placeBlockAtCurrentPosition(world, ModBlocks.steel_beam, 3, 6, 1, 9, box);
placeBlockAtCurrentPosition(world, ModBlocks.fan, getDecoMeta(2), 6, 2, 9, box);
placeBlockAtCurrentPosition(world, Blocks.stone_button, 1, 7, 2, 9, box);
//stalls w/ toilets
for(int i = 1; i <= 5; i += 2) {
placeBlockAtCurrentPosition(world, ModBlocks.door_metal, 0, 5, 1, i, box);
placeDoor(world, box, ModBlocks.door_metal, 0, false, rand.nextBoolean(), 5, 1, i);
fillWithMetadataBlocks(world, box, 5, 1, i + 1, 5, 2, i + 1, ModBlocks.steel_corner, getDecoMeta(2));
fillWithMetadataBlocks(world, box, 6, 1, i + 1, 7, 2, i + 1, ModBlocks.steel_wall, getDecoMeta(2));
placeBlockAtCurrentPosition(world, ModBlocks.deco_pipe_rim, 0, 7, 1, i, box);
placeBlockAtCurrentPosition(world, Blocks.trapdoor, getDecoModelMeta(2) >> 2, 7, 2, i, box);
}
//doors
placeDoor(world, box, ModBlocks.door_bunker, 1, true, rand.nextBoolean(), 2, 1, 0);
placeDoor(world, box, ModBlocks.door_bunker, 1, false, rand.nextBoolean(), 3, 1, 0);
if(path) fillWithAir(world, box, 8, 1, 7, 8, 2, 8);
return true;
}
public static StructureComponent findValidPlacement(List components, Random rand, int x, int y, int z, int coordMode, int type) {
StructureBoundingBox box = ProceduralStructureStart.getComponentToAddBoundingBox(x, y, z, -3, -1, 0, 9, 6, 11, coordMode);
return box.minY > 10 && StructureComponent.findIntersecting(components, box) == null ? new BathroomL(type, box, coordMode) : null;
}
}
}

View File

@ -1,4 +1,4 @@
package com.hbm.world.worldgen.components;
package com.hbm.world.gen.component;
import java.util.Random;

View File

@ -1,4 +1,4 @@
package com.hbm.world.worldgen.components;
package com.hbm.world.gen.component;
import java.util.Random;
@ -108,6 +108,26 @@ abstract public class Component extends StructureComponent {
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)) {
total += Math.max(world.getTopSolidOrLiquidBlock(x, z), world.provider.getAverageGroundLevel());
iterations++;
}
}
}
if(iterations == 0)
return -1;
return total / iterations;
}
public int getCoordMode() {
return this.coordBaseMode;
}
@ -224,35 +244,41 @@ abstract public class Component extends StructureComponent {
return metadata;
}
/* For Later:
* 0/S: S->S; W->W; N->N; E->E
* 1/W: S->W; W->N; N->E; E->S
* 2/N: S->N; W->E; N->S; E->W
* 3/E: S->E; W->S; N->W; E->N
* 0/b00/W, 1/b01/N, 2/b10/E, 3/b11/S
*/
/**
* Places door at specified location with orientation-adjusted meta
* 0 = West, 1 = North, 2 = East, 3 = South
/*
* Assuming door is on opposite side of block from direction: East: 0, South: 1, West: 2, North: 3<br>
* 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.<br>
* <li>The 4th bit (0b1000 or 8) indicates whether it is the top block: on for yes, off for no.
* <li>When the 4th bit is on, the 1st bit indicates whether the door opens to the right or not: on (0b1001) for yes, off (0b1000) for no.
* <li>The bits 1 & 2 (0b0011 or 3) indicate the direction the door is facing.
* <li>When the 4th bit is off, the 3rd bit (0b0100 or 4) indicates whether the door is open or not: on for yes, off for no. Used for doors' interactions with redstone power.
* </li>
*/
protected void placeDoor(World world, StructureBoundingBox box, Block door, int meta, int featureX, int featureY, int featureZ) {
switch(this.coordBaseMode) {
default:
break;
case 1:
meta = (meta + 1) % 4; break;
case 2:
meta = meta ^ 2; break; //Flip second bit
case 3:
meta = (meta - 1) % 4; break;
}
protected void placeDoor(World world, StructureBoundingBox box, Block door, int dirMeta, boolean opensRight, boolean isOpen, int featureX, int featureY, int featureZ) { //isOpen for randomly opened doors
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);
if(!box.isVecInside(posX, posY, posZ)) return;
switch(this.coordBaseMode) {
default:
break;
case 1:
dirMeta = (dirMeta + 1) % 4; break;
case 2:
dirMeta ^= 2; break; //Flip second bit
case 3:
dirMeta = (dirMeta - 1) % 4; break;
}
//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);
}
}
/**N:0 W:1 S:2 E:3 */

View File

@ -1,4 +1,4 @@
package com.hbm.world.worldgen.components;
package com.hbm.world.gen.component;
import java.util.Random;
@ -200,9 +200,9 @@ public class OfficeFeatures {
randomlyFillWithBlocks(world, box, rand, 0.25F, 6, 3, 1, sizeX - 1, 3, 6, Blocks.web);
randomlyFillWithBlocks(world, box, rand, 0.25F, 10, 3, 7, sizeX - 1, 3, sizeZ - 1, Blocks.web);
//Doors
placeDoor(world, box, ModBlocks.door_office, 3, 2, 1, 7);
placeDoor(world, box, ModBlocks.door_office, 3, 3, 1, 7);
placeDoor(world, box, ModBlocks.door_office, 0, 5, 1, 6);
placeDoor(world, box, ModBlocks.door_office, 3, false, rand.nextBoolean(), 2, 1, 7);
placeDoor(world, box, ModBlocks.door_office, 3, false, rand.nextBoolean(), 3, 1, 7);
placeDoor(world, box, ModBlocks.door_office, 0, false, rand.nextBoolean(), 5, 1, 6);
//Woot
if(!this.hasPlacedLoot[0])
@ -427,16 +427,16 @@ public class OfficeFeatures {
fillWithRandomizedBlocks(world, box, 2, 11, 10, 3, 11, 10, rand, ConcreteBricks);
fillWithRandomizedBlocks(world, box, 2, 9, 10, 2, 10, 10, rand, ConcreteBricks);
//Doors
placeDoor(world, box, Blocks.wooden_door, 3, 1, 1, 14);
placeDoor(world, box, Blocks.wooden_door, 3, 2, 1, 14);
placeDoor(world, box, Blocks.wooden_door, 0, 0, 1, 12);
placeDoor(world, box, Blocks.wooden_door, 0, 0, 1, 13);
placeDoor(world, box, ModBlocks.door_office, 0, 6, 1, 3);
placeDoor(world, box, ModBlocks.door_office, 0, 5, 5, 3);
placeDoor(world, box, ModBlocks.door_office, 2, 4, 5, 11);
placeDoor(world, box, ModBlocks.door_office, 0, 10, 9, 3);
placeDoor(world, box, ModBlocks.door_office, 1, 3, 9, 10);
placeDoor(world, box, ModBlocks.door_metal, 0, 5, 13, 3);
placeDoor(world, box, Blocks.wooden_door, 3, false, rand.nextBoolean(), 1, 1, 14);
placeDoor(world, box, Blocks.wooden_door, 3, true, rand.nextBoolean(), 2, 1, 14);
placeDoor(world, box, Blocks.wooden_door, 0, false, rand.nextBoolean(), 0, 1, 12);
placeDoor(world, box, Blocks.wooden_door, 0, true, rand.nextBoolean(), 0, 1, 13);
placeDoor(world, box, ModBlocks.door_office, 0, false, rand.nextBoolean(), 6, 1, 3);
placeDoor(world, box, ModBlocks.door_office, 0, false, rand.nextBoolean(), 5, 5, 3);
placeDoor(world, box, ModBlocks.door_office, 2, false, rand.nextBoolean(), 4, 5, 11);
placeDoor(world, box, ModBlocks.door_office, 0, false, rand.nextBoolean(), 10, 9, 3);
placeDoor(world, box, ModBlocks.door_office, 1, false, rand.nextBoolean(), 3, 9, 10);
placeDoor(world, box, ModBlocks.door_metal, 0, false, rand.nextBoolean(), 5, 13, 3);
//Furniture
//Floor 1
int NorthStairMeta = getStairMeta(2);

View File

@ -1,4 +1,4 @@
package com.hbm.world.worldgen.components;
package com.hbm.world.gen.component;
import java.util.Random;

View File

@ -1,53 +0,0 @@
package com.hbm.world.worldgen;
import java.util.Random;
import com.hbm.config.StructureConfig;
import cpw.mods.fml.common.IWorldGenerator;
import net.minecraft.block.Block;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraftforge.event.terraingen.InitMapGenEvent.EventType;
import net.minecraftforge.event.terraingen.TerrainGen;
public class NTMWorldGenerator implements IWorldGenerator {
private MapGenNTMFeatures NTMFeatureGenerator = new MapGenNTMFeatures();
{
NTMFeatureGenerator = (MapGenNTMFeatures) TerrainGen.getModdedMapGen(NTMFeatureGenerator, EventType.CUSTOM);
}
@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, 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) { }
private void generateSurface(World world, Random rand, IChunkProvider chunkGenerator, int chunkX, int chunkZ) {
Block[] ablock = new Block[65536];
//WorldConfig.enableStructures
/** Spawns structure starts. Utilizes canSpawnStructureAtCoords() + if else checks in Start constructor */
if(StructureConfig.enableStructures) {
this.NTMFeatureGenerator.func_151539_a(chunkGenerator, world, chunkX, chunkZ, ablock);
}
/** Actually generates structures in a given chunk. */
if(StructureConfig.enableStructures) {
this.NTMFeatureGenerator.generateStructuresInChunk(world, rand, chunkX, chunkZ);
}
}
private void generateEnd(World world, Random rand, IChunkProvider chunkGenerator, int chunkX, int chunkZ) { }
}

View File

@ -1,240 +0,0 @@
package com.hbm.world.worldgen.components;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import net.minecraft.world.gen.structure.StructureBoundingBox;
public abstract class ProceduralComponents {
protected List componentWeightList;
protected static Weight[] weightArray = new Weight[] { };
public void prepareComponents() {
componentWeightList = new ArrayList();
for(int i = 0; i < weightArray.length; i++) {
weightArray[i].instancesSpawned = 0;
componentWeightList.add(weightArray[i]);
}
}
protected int getTotalWeight() {
boolean flag = false;
int totalWeight = 0;
Weight weight;
for(Iterator iterator = componentWeightList.iterator(); iterator.hasNext(); totalWeight += weight.weight) { //Iterates over the entire list to find the total weight
weight = (Weight) iterator.next();
if(weight.instanceLimit >= 0 && weight.instancesSpawned < weight.instanceLimit) //can more structure pieces be added, in general?
flag = true;
}
return flag ? totalWeight : -1;
}
protected ProceduralComponent getWeightedComponent(ControlComponent original, List components, Random rand, int minX, int minY, int minZ, int coordMode, int componentType) {
int totalWeight = getTotalWeight();
if(totalWeight < 0)
return null;
for(int i = 0; i < 5; i++) {
int value = rand.nextInt(totalWeight); //Pick a random value, based on how many parts there are already
Iterator iterator = componentWeightList.iterator();
while(iterator.hasNext()) {
Weight weight = (Weight)iterator.next();
value -= weight.weight; //Iterate over the list until the value is less than 0
if(value < 0) {
if(!weight.canSpawnStructure(componentType, coordMode, original.lastComponent)) //Additional checks based on game state info preventing spawn? start from beginning
break;
ProceduralComponent component = (ProceduralComponent) weight.lambda.findValidPlacement(components, rand, minX, minY, minZ, coordMode, componentType); //Construct the chosen component
if(component != null) { //If it has been constructed, add it
weight.instancesSpawned++;
if(!weight.canSpawnMoreStructures()) //Structure can no longer be spawned regardless of game state? remove as an option
componentWeightList.remove(weight);
return component;
}
}
}
}
return null;
}
protected int sizeLimit = 50;
protected int distanceLimit = 64;
protected ProceduralComponent getNextValidComponent(ControlComponent original, List components, Random rand, int minX, int minY, int minZ, int coordMode, int componentType) {
if(components.size() > sizeLimit) //Hard limit on amount of components
return null;
if(Math.abs(minX - original.getBoundingBox().minX) <= distanceLimit && Math.abs(minZ - original.getBoundingBox().minZ) <= distanceLimit) { //Hard limit on spread of structure
ProceduralComponent structure = getWeightedComponent(original, components, rand, minX, minY, minZ, coordMode, componentType + 1); //Returns null if all checks fail
if(structure != null) {
components.add(structure); //Adds component to structure start list
original.queuedComponents.add(structure); //Add it to the list of queued components waiting to be built
}
return structure;
}
return null;
}
public static StructureBoundingBox getComponentToAddBoundingBox(int posX, int posY, int posZ, int offsetX, int offsetY, int offsetZ, int maxX, int maxY, int maxZ, int coordMode) {
switch(coordMode) {
case 0: //South
return new StructureBoundingBox(posX + offsetX, posY + offsetY, posZ + offsetZ, posX + maxX - 1 + offsetX, posY + maxY - 1 + offsetY, posZ + maxZ - 1 + offsetZ);
case 1: //West
return new StructureBoundingBox(posX - maxZ + 1 - offsetZ, posY + offsetY, posZ + offsetX, posX - offsetZ, posY + maxY - 1 + offsetY, posZ + maxX - 1 + offsetX);
case 2: //North
return new StructureBoundingBox(posX - maxX + 1 - offsetX, posY + offsetY, posZ - maxZ + 1 - offsetZ, posX - offsetX, posY + maxY - 1 + offsetY, posZ + offsetZ);
case 3: //East
return new StructureBoundingBox(posX + offsetZ, posY + offsetY, posZ - maxX + 1 - offsetX, posX + maxZ - 1 + offsetZ, posY + maxY - 1 + offsetY, posZ - offsetX);
default:
return new StructureBoundingBox(posX + offsetX, posY + offsetY, posZ + offsetZ, posX + maxX - 1 + offsetX, posY + maxY - 1 + offsetY, posZ + maxZ - 1 + offsetZ);
}
}
/** StructureComponent that supports procedural generation */
public abstract static class ProceduralComponent extends Component {
public ProceduralComponent() { }
public ProceduralComponent(int componentType) {
super(componentType); //Important to carry over.
}
public void buildComponent(ProceduralComponents instance, ControlComponent original, List components, Random rand) { }
/** Gets next component in the direction this component is facing.<br>'original' refers to the initial starting component (hard distance limits), 'components' refers to the StructureStart list. */
protected ProceduralComponent getNextComponentNormal(ProceduralComponents instance, ControlComponent original, List components, Random rand, int offset, int offsetY) {
switch(this.coordBaseMode) {
case 0: //South
return instance.getNextValidComponent(original, components, rand, this.boundingBox.minX + offset, this.boundingBox.minY + offsetY, this.boundingBox.maxZ + 1, this.coordBaseMode, this.getComponentType());
case 1: //West
return instance.getNextValidComponent(original, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + offsetY, this.boundingBox.minZ + offset, this.coordBaseMode, this.getComponentType());
case 2: //North
return instance.getNextValidComponent(original, components, rand, this.boundingBox.maxX - offset, this.boundingBox.minY + offsetY, this.boundingBox.minZ - 1, this.coordBaseMode, this.getComponentType());
case 3: //East
return instance.getNextValidComponent(original, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + offsetY, this.boundingBox.maxZ - offset, this.coordBaseMode, this.getComponentType());
default:
return null;
}
}
/** Gets next component in the opposite direction this component is facing. */
protected ProceduralComponent getNextComponentAntiNormal(ProceduralComponents instance, ControlComponent original, List components, Random rand, int offset, int offsetY) {
switch(this.coordBaseMode) {
case 0: //South
return instance.getNextValidComponent(original, components, rand, this.boundingBox.maxX - offset, this.boundingBox.minY + offsetY, this.boundingBox.minZ - 1, 2, this.getComponentType());
case 1: //West
return instance.getNextValidComponent(original, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + offsetY, this.boundingBox.maxZ - offset, 3, this.getComponentType());
case 2: //North
return instance.getNextValidComponent(original, components, rand, this.boundingBox.minX + offset, this.boundingBox.minY + offsetY, this.boundingBox.maxZ + 1, 0, this.getComponentType());
case 3: //East
return instance.getNextValidComponent(original, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + offsetY, this.boundingBox.minZ + offset, 1, this.getComponentType());
default:
return null;
}
}
//Keep in mind for these methods: a given room would have its *actual entrance* opposite the side it is facing.
/** Gets next component, to the West (-X) <i>relative to this component. */
protected ProceduralComponent getNextComponentNX(ProceduralComponents instance, ControlComponent original, List components, Random rand, int offset, int offsetY) {
switch(this.coordBaseMode) {
case 0: //South
return instance.getNextValidComponent(original, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + offsetY, this.boundingBox.minZ + offset, 1, this.getComponentType());
case 1: //West
return instance.getNextValidComponent(original, components, rand, this.boundingBox.maxX - offset, this.boundingBox.minY + offsetY, this.boundingBox.minZ - 1, 2, this.getComponentType());
case 2: //North
return instance.getNextValidComponent(original, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + offsetY, this.boundingBox.maxZ - offset, 3, this.getComponentType());
case 3: //East
return instance.getNextValidComponent(original, components, rand, this.boundingBox.minX + offset, this.boundingBox.minY + offsetY, this.boundingBox.maxZ + 1, 0, this.getComponentType());
default:
return null;
}
}
/** Gets next component, to the East (+X) <i>relative to this component. */
protected ProceduralComponent getNextComponentPX(ProceduralComponents instance, ControlComponent original, List components, Random rand, int offset, int offsetY) {
switch(this.coordBaseMode) {
case 0: //South
return instance.getNextValidComponent(original, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + offsetY, this.boundingBox.maxZ - offset, 3, this.getComponentType() + 1);
case 1: //West
return instance.getNextValidComponent(original, components, rand, this.boundingBox.minX + offset, this.boundingBox.minY + offsetY, this.boundingBox.maxZ + 1, 0, this.getComponentType() + 1);
case 2: //North
return instance.getNextValidComponent(original, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + offsetY, this.boundingBox.minZ + offset, 1, this.getComponentType() + 1);
case 3: //East
return instance.getNextValidComponent(original, components, rand, this.boundingBox.maxX - offset, this.boundingBox.minY + offsetY, this.boundingBox.minZ - 1, 2, this.getComponentType() + 1);
default:
return null;
}
}
/** Finds valid placement, using input information. Should be passed as a method reference to its respective Weight. */
//Static so no override (cringe!)
//public static ProceduralComponent findValidPlacement(List components, Random rand, int minX, int minY, int minZ, int coordMode, int componentType) { return null; }
}
/** ProceduralComponent that can serve as a master "control component" for procedural generation and building of components. */
public abstract static class ControlComponent extends ProceduralComponent {
public List queuedComponents = new ArrayList(); //List of all queued ProceduralComponents waiting to be built. Randomly iterated over until limits like component amt or dist are reached.
public ProceduralComponent lastComponent = this; //Last component to be built. Used as input for the random selection's checks for specific components.
public ControlComponent() { }
public ControlComponent(int componentType) {
super(componentType);
}
}
/** Returns a new instance of this structureComponent, or null if not able to be placed.<br>Based on bounding box checks. */
@FunctionalInterface
interface instantiateStructure {
ProceduralComponent findValidPlacement(List components, Random rand, int minX, int minY, int minZ, int coordMode, int componentType);
}
protected static class Weight {
public final instantiateStructure lambda; //Read above
public final int weight; //Weight of this component
public int instancesSpawned; //How many components spawned?
public int instanceLimit; //Limit on amount of components: -1 for no limit
public Weight(int weight, int limit, instantiateStructure lambda) {
this.weight = weight;
this.instanceLimit = limit;
this.lambda = lambda;
}
//Checks if another structure can be spawned based on input data
public boolean canSpawnStructure(int componentAmount, int coordMode, ProceduralComponent component) {
return this.instanceLimit < 0 || this.instancesSpawned < this.instanceLimit;
}
//Checks if another structure can be spawned at all (used to flag for removal from the list)
public boolean canSpawnMoreStructures() {
return this.instanceLimit < 0 || this.instancesSpawned < this.instanceLimit;
}
}
}