Major refactoring, some fixes

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
This commit is contained in:
Vaern 2022-10-08 15:15:41 -07:00
parent 697752c839
commit 7edbf615b6
8 changed files with 283 additions and 227 deletions

View File

@ -1,10 +1,12 @@
package com.hbm.world.worldgen;
import java.util.List;
import java.util.Random;
import com.hbm.config.GeneralConfig;
import com.hbm.world.worldgen.components.BunkerComponents;
import com.hbm.world.worldgen.components.BunkerComponents.Atrium;
import com.hbm.world.worldgen.components.ProceduralComponents.ProceduralComponent;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.MapGenStructure;
@ -41,12 +43,13 @@ public class MapGenBunker extends MapGenStructure {
this.components.add(atrium);
atrium.buildComponent(atrium, components, rand);
/*List list = atrium.componentsToBuild;
List list = atrium.queuedComponents;
while(!list.isEmpty()) {
int k = rand.nextInt(list.size());
Bunker component = (Bunker)list.remove(k);
component.buildComponent(atrium, list, rand);
}*/
ProceduralComponent component = (ProceduralComponent)list.remove(k);
atrium.lastComponent = component;
component.buildComponent(atrium, this.components, rand);
}
if(GeneralConfig.enableDebugMode) {
System.out.print("[Debug] StructureStart at " + (chunkX * 16 + 8) + ", idfk lmao, " + (chunkZ * 16 + 8) + "\n[Debug] Components: ");

View File

@ -14,23 +14,20 @@ import net.minecraft.world.World;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraft.world.gen.structure.StructureComponent;
public class BunkerComponents {
public class BunkerComponents extends ProceduralComponents {
private static final Weight[] weightArray = new Weight[] {
new Weight(1, 50, (list, rand, x, y, z, mode, type) -> { StructureBoundingBox box = Bunker.getComponentToAddBoundingBox(x, y, z, -1, -1, 0, 5, 6, 15, mode);
protected static final Weight[] weightArray = new Weight[] {
new Weight(1, 50, (list, rand, x, y, z, mode, type) -> { StructureBoundingBox box = ProceduralComponent.getComponentToAddBoundingBox(x, y, z, -1, -1, 0, 5, 6, 15, mode);
return box.minY > 10 && StructureComponent.findIntersecting(list, box) == null ? new Corridor(type, rand, box, mode) : null; }),
new Weight(2, -1, (list, rand, x, y, z, mode, type) -> { StructureBoundingBox box = Bunker.getComponentToAddBoundingBox(x, y, z, -1, -1, 0, 5, 6, 15, mode);
return box.minY > 10 && StructureComponent.findIntersecting(list, box) == null ? new Corridor(type, rand, box, mode) : null; }),
new Weight(1, -1, (list, rand, x, y, z, mode, type) -> { StructureBoundingBox box = Bunker.getComponentToAddBoundingBox(x, y, z, -1, -1, 0, 5, 6, 5, mode);
new Weight(2, -1, (list, rand, x, y, z, mode, type) -> { StructureBoundingBox box = ProceduralComponent.getComponentToAddBoundingBox(x, y, z, -1, -1, 0, 5, 6, 15, mode);
return box.minY > 10 && StructureComponent.findIntersecting(list, box) == null ? new Corridor(type, rand, box, mode) : null; }),
new Weight(1, -1, (list, rand, x, y, z, mode, type) -> { StructureBoundingBox box = ProceduralComponent.getComponentToAddBoundingBox(x, y, z, -1, -1, 0, 5, 6, 5, mode);
return box.minY > 10 && StructureComponent.findIntersecting(list, box) == null ? new Intersection(type, rand, box, mode) : null; }),
new Weight(8, -1, (list, rand, x, y, z, mode, type) -> { StructureBoundingBox box = Bunker.getComponentToAddBoundingBox(x, y, z, -3, -1, 0, 9, 6, 17, mode);
new Weight(8, -1, (list, rand, x, y, z, mode, type) -> { StructureBoundingBox box = ProceduralComponent.getComponentToAddBoundingBox(x, y, z, -3, -1, 0, 9, 6, 17, mode);
return box.minY > 10 && StructureComponent.findIntersecting(list, box) == null ? new WideCorridor(type, rand, box, mode) : null; }),
};
private static List componentWeightList;
static int totalWeight;
public static void prepareComponents() {
componentWeightList = new ArrayList();
@ -40,198 +37,21 @@ public class BunkerComponents {
}
}
private static boolean canAddStructurePieces() {
boolean flag = false;
totalWeight = 0;
Weight weight;
for(Iterator iterator = componentWeightList.iterator(); iterator.hasNext(); totalWeight += weight.weight) {
weight = (Weight) iterator.next();
if(weight.instanceLimit >= 0 && weight.instancesSpawned < weight.instanceLimit)
flag = true;
}
return flag;
}
private static Bunker getWeightedComponent(StructureComponent original, List components, Random rand, int minX, int minY, int minZ, int coordMode, int componentType) {
if(!canAddStructurePieces())
return null;
for(int i = 0; i < 5; i++) {
int value = rand.nextInt(totalWeight);
Iterator iterator = componentWeightList.iterator();
while(iterator.hasNext()) {
Weight weight = (Weight)iterator.next();
value -= weight.weight;
if(value < 0) {
if(!weight.canSpawnStructure(componentType))
break;
Bunker component = (Bunker) weight.lambda.findValidPlacement(components, rand, minX, minY, minZ, coordMode, componentType);
if(component != null) {
weight.instancesSpawned++;
if(!weight.canSpawnMoreStructures())
componentWeightList.remove(weight);
return component;
}
}
}
}
return null;
}
private static StructureComponent getNextValidComponent(StructureComponent original, List components, Random rand, int minX, int minY, int minZ, int coordMode, int componentType) {
if(components.size() > 50)
return null;
if(Math.abs(minX - original.getBoundingBox().minX) <= 64 && Math.abs(minZ - original.getBoundingBox().minZ) <= 64) {
StructureComponent structure = getWeightedComponent(original, components, rand, minX, minY, minZ, coordMode, componentType);
if(structure != null) {
components.add(structure); //Adds component to structure start list
structure.buildComponent(original, components, rand); //no fucking clue why but doing it how mojang does it didn't work at all
}
return structure;
}
return null;
}
static class Weight {
public final instantiateStructure lambda; //i refuse to use some 🤓 ass method for getting the class from each PieceWeight
//here, we overengineer shit like real developers
public final int weight;
public int instancesSpawned;
public int instanceLimit;
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) {
return this.instanceLimit < 0 || this.instanceLimit < 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;
}
}
/** Returns a new instance of this structureComponent, or null if not able to be placed. */
@FunctionalInterface
interface instantiateStructure {
StructureComponent findValidPlacement(List components, Random rand, int minX, int minY, int minZ, int coordMode, int componentType);
}
public abstract static class Bunker extends Feature {
public Bunker() { }
public Bunker(int componentType) {
super(componentType); //important to carry over, as it allows for hard limits on the amount of components. increment once for each new component.
}
/** 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 StructureComponent getNextComponentNormal(StructureComponent original, List components, Random rand, int offset, int offsetY) {
switch(this.coordBaseMode) {
case 0: //South
return getNextValidComponent(original, components, rand, this.boundingBox.minX + offset, this.boundingBox.minY + offsetY, this.boundingBox.maxZ + 1, this.coordBaseMode, this.getComponentType() + 1);
case 1: //West
return getNextValidComponent(original, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + offsetY, this.boundingBox.minZ + offset, this.coordBaseMode, this.getComponentType() + 1);
case 2: //North
return getNextValidComponent(original, components, rand, this.boundingBox.maxX - offset, this.boundingBox.minY + offsetY, this.boundingBox.minZ - 1, this.coordBaseMode, this.getComponentType() + 1);
case 3: //East
return getNextValidComponent(original, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + offsetY, this.boundingBox.maxZ - offset, this.coordBaseMode, this.getComponentType() + 1);
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 StructureComponent getNextComponentNX(StructureComponent original, List components, Random rand, int offset, int offsetY) {
switch(this.coordBaseMode) {
case 0: //South
return getNextValidComponent(original, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + offsetY, this.boundingBox.minZ + offset, 1, this.getComponentType() + 1);
case 1: //West
return getNextValidComponent(original, components, rand, this.boundingBox.maxX - offset, this.boundingBox.minY + offsetY, this.boundingBox.minZ - 1, 2, this.getComponentType() + 1);
case 2: //North
return getNextValidComponent(original, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + offsetY, this.boundingBox.maxZ - offset, 3, this.getComponentType() + 1);
case 3: //East
return getNextValidComponent(original, components, rand, this.boundingBox.minX + offset, this.boundingBox.minY + offsetY, this.boundingBox.maxZ + 1, 0, this.getComponentType() + 1);
default:
return null;
}
}
/** Gets next component, to the East (+X) <i>relative to this component. */
protected StructureComponent getNextComponentPX(StructureComponent original, List components, Random rand, int offset, int offsetY) {
switch(this.coordBaseMode) {
case 0: //South
return getNextValidComponent(original, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + offsetY, this.boundingBox.maxZ - offset, 1, this.getComponentType() + 1);
case 1: //West
return getNextValidComponent(original, components, rand, this.boundingBox.minZ + offset, this.boundingBox.minY + offsetY, this.boundingBox.maxZ + 1, 2, this.getComponentType() + 1);
case 2: //North
return getNextValidComponent(original, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + offsetY, this.boundingBox.minZ + offset, 3, this.getComponentType() + 1);
case 3: //East
return getNextValidComponent(original, components, rand, this.boundingBox.maxX - offset, this.boundingBox.minY + offsetY, this.boundingBox.minZ - 1, 0, this.getComponentType() + 1);
default:
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) {
System.out.print(posX + ", " + posY + ", " + posZ + ", CBM: " + coordMode);
switch(coordMode) { //fixed
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);
}
}
}
public static class Atrium extends Bunker {
public static class Atrium extends ControlComponent {
public Atrium() { }
public Atrium(int componentType, Random rand, int posX, int posZ) { //TODO: change basically everything about this component
super(componentType);
this.coordBaseMode = rand.nextInt(4);
this.boundingBox = new StructureBoundingBox(posX, 64, posZ, posX + 4, 68, posZ + 4);
this.boundingBox = new StructureBoundingBox(posX, 64, posZ, posX + 8, 68, posZ + 8);
}
@Override
public void buildComponent(StructureComponent original, List components, Random rand) {
getNextComponentNormal(original, components, rand, 1, 1);
getNextComponentNX(original, components, rand, 1, 1);
getNextComponentPX(original, components, rand, 1, 1);
public void buildComponent(ControlComponent original, List components, Random rand) {
getNextComponentNormal(original, components, rand, 3, 1);
getNextComponentNX(original, components, rand, 3, 1);
getNextComponentPX(original, components, rand, 3, 1);
}
@Override
@ -240,7 +60,7 @@ public class BunkerComponents {
}
}
public static class Corridor extends Bunker {
public static class Corridor extends ProceduralComponent {
boolean expandsNX = false;
boolean expandsPX = false;
@ -270,7 +90,7 @@ public class BunkerComponents {
}
@Override
public void buildComponent(StructureComponent original, List components, Random rand) {
public void buildComponent(ControlComponent original, List components, Random rand) {
StructureComponent component = getNextComponentNormal(original, components, rand, 1, 1);
extendsPZ = component != null;
@ -375,7 +195,7 @@ public class BunkerComponents {
}
@Override
public void buildComponent(StructureComponent original, List components, Random rand) {
public void buildComponent(ControlComponent original, List components, Random rand) {
StructureComponent component = getNextComponentNormal(original, components, rand, 3, 1);
extendsPZ = component != null;
@ -511,7 +331,7 @@ public class BunkerComponents {
}
}
public static class Turn extends Bunker {
public static class Turn extends ProceduralComponent {
public Turn() { }
@ -542,7 +362,7 @@ public class BunkerComponents {
}
}
public static class Intersection extends Bunker {
public static class Intersection extends ProceduralComponent {
boolean opensNX = false;
boolean opensPX = false;
@ -558,7 +378,7 @@ public class BunkerComponents {
}
@Override
public void buildComponent(StructureComponent original, List components, Random rand) {
public void buildComponent(ControlComponent original, List components, Random rand) {
if(rand.nextInt(3) != 0) {
StructureComponent component = getNextComponentNormal(original, components, rand, 1, 1);
opensPZ = component != null;
@ -595,6 +415,7 @@ public class BunkerComponents {
//Floor
fillWithBlocks(world, box, 1, 0, 0, 3, 0, 3, ModBlocks.deco_titanium);
//Ceiling
int pillarMetaWE = getPillarMeta(4);
int pillarMetaNS = getPillarMeta(8);
fillWithBlocks(world, box, 3, 4, 0, 3, 4, 1, ModBlocks.reinforced_brick);
@ -610,7 +431,7 @@ public class BunkerComponents {
if(opensPZ) {
fillWithBlocks(world, box, 1, 0, 4, 3, 0, 4, ModBlocks.deco_titanium); //Floor
fillWithBlocks(world, box, 1, 4, 3, 1, 4, 4, ModBlocks.reinforced_brick); //Ceiling
fillWithMetadataBlocks(world, box, 2, 4, 3, 2, 4, 4, ModBlocks.concrete_pillar, 8);
fillWithMetadataBlocks(world, box, 2, 4, 3, 2, 4, 4, ModBlocks.concrete_pillar, pillarMetaNS);
fillWithBlocks(world, box, 3, 4, 3, 3, 4, 4, ModBlocks.reinforced_brick);
fillWithAir(world, box, 1, 1, 4, 3, 3, 4); //Opening
} else {
@ -623,7 +444,7 @@ public class BunkerComponents {
if(opensNX) {
fillWithBlocks(world, box, 0, 0, 1, 0, 0, 3, ModBlocks.deco_titanium); //Floor
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_brick, 0, 0, 4, 1, box); //Ceiling
fillWithMetadataBlocks(world, box, 0, 4, 2, 1, 4, 2, ModBlocks.concrete_pillar, 4);
fillWithMetadataBlocks(world, box, 0, 4, 2, 1, 4, 2, ModBlocks.concrete_pillar, pillarMetaWE);
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_brick, 0, 0, 4, 3, box);
fillWithAir(world, box, 0, 1, 1, 0, 3, 3); //Opening
} else {
@ -636,7 +457,7 @@ public class BunkerComponents {
if(opensPX) {
fillWithBlocks(world, box, 4, 0, 1, 4, 0, 3, ModBlocks.deco_titanium); //Floor
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_brick, 0, 4, 4, 1, box); //Ceiling
fillWithMetadataBlocks(world, box, 3, 4, 2, 4, 4, 2, ModBlocks.concrete_pillar, 4);
fillWithMetadataBlocks(world, box, 3, 4, 2, 4, 4, 2, ModBlocks.concrete_pillar, pillarMetaWE);
placeBlockAtCurrentPosition(world, ModBlocks.reinforced_brick, 0, 4, 4, 3, box);
fillWithAir(world, box, 4, 1, 1, 4, 3, 3); //Opening
} else {

View File

@ -22,7 +22,7 @@ import net.minecraft.world.gen.structure.StructureBoundingBox;
public class CivilianFeatures {
/** Sandstone Ruin 1 */
public static class NTMHouse1 extends Feature {
public static class NTMHouse1 extends Component {
private boolean hasPlacedChest;
@ -120,7 +120,7 @@ public class CivilianFeatures {
}
public static class NTMHouse2 extends Feature {
public static class NTMHouse2 extends Component {
private static Sandstone RandomSandstone = new Sandstone();
@ -264,7 +264,7 @@ public class CivilianFeatures {
}
}
public static class NTMLab1 extends Feature {
public static class NTMLab1 extends Component {
private static ConcreteBricks RandomConcreteBricks = new ConcreteBricks();
private static LabTiles RandomLabTiles = new LabTiles();
@ -391,7 +391,7 @@ public class CivilianFeatures {
}
}
public static class NTMLab2 extends Feature {
public static class NTMLab2 extends Component {
private static SuperConcrete RandomSuperConcrete = new SuperConcrete();
private static ConcreteBricks RandomConcreteBricks = new ConcreteBricks();
@ -565,7 +565,7 @@ public class CivilianFeatures {
}
}
public static class NTMWorkshop1 extends Feature {
public static class NTMWorkshop1 extends Component {
private static SuperConcrete RandomSuperConcrete = new SuperConcrete();

View File

@ -23,7 +23,7 @@ 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 {
abstract public class Component 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 */
@ -33,15 +33,15 @@ abstract public class Feature extends StructureComponent {
/** Average height (Presumably stands for height position) */
protected int hpos = -1;
protected Feature() {
protected Component() {
super(0);
}
protected Feature(int componentType) {
protected Component(int componentType) {
super(componentType);
}
protected Feature(Random rand, int minX, int minY, int minZ, int maxX, int maxY, int maxZ ) {
protected Component(Random rand, int minX, int minY, int minZ, int maxX, int maxY, int maxZ ) {
super(0);
this.sizeX = maxX;
this.sizeY = maxY;
@ -105,6 +105,10 @@ abstract public class Feature extends StructureComponent {
return true;
}
public int getCoordMode() {
return this.coordBaseMode;
}
/** Metadata for Decoration Methods **/
/**
@ -689,11 +693,11 @@ abstract public class Feature extends StructureComponent {
public void selectBlocks(Random rand, int posX, int posY, int posZ, boolean p_75062_5_) {
float chance = rand.nextFloat();
if(chance < 0.2F) {
if(chance < 0.4F) {
this.field_151562_a = ModBlocks.brick_concrete;
} else if (chance < 0.55F) {
} else if (chance < 0.7F) {
this.field_151562_a = ModBlocks.brick_concrete_mossy;
} else if (chance < 0.75F) {
} else if (chance < 0.9F) {
this.field_151562_a = ModBlocks.brick_concrete_cracked;
} else {
this.field_151562_a = ModBlocks.brick_concrete_broken;

View File

@ -48,7 +48,7 @@ public class MilitaryBaseFeatures {
return chunkPos;
}
public static class BasicHelipad extends Feature {
public static class BasicHelipad extends Component {
public BasicHelipad() { super(); }
@ -100,7 +100,7 @@ public class MilitaryBaseFeatures {
}
public static class RadioShack extends Feature {
public static class RadioShack extends Component {
private static LabTiles RandomLabTiles = new LabTiles();
private static ConcreteBricks ConcreteBricks = new ConcreteBricks();

View File

@ -5,7 +5,7 @@ import java.util.Random;
import com.hbm.blocks.ModBlocks;
import com.hbm.lib.HbmChestContents;
import com.hbm.util.LootGenerator;
import com.hbm.world.worldgen.components.Feature.ConcreteBricks;
import com.hbm.world.worldgen.components.Component.ConcreteBricks;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
@ -15,7 +15,7 @@ import net.minecraft.world.gen.structure.StructureBoundingBox;
//Oh my fucking god TM
public class OfficeFeatures {
public static class LargeOffice extends Feature {
public static class LargeOffice extends Component {
private static ConcreteBricks ConcreteBricks = new ConcreteBricks();
@ -216,7 +216,7 @@ public class OfficeFeatures {
}
//bob i could kiss you
public static class LargeOfficeCorner extends Feature {
public static class LargeOfficeCorner extends Component {
private static ConcreteBricks ConcreteBricks = new ConcreteBricks();

View File

@ -0,0 +1,228 @@
package com.hbm.world.worldgen.components;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import com.hbm.world.worldgen.components.ProceduralComponents.ControlComponent;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraft.world.gen.structure.StructureComponent;
public abstract class ProceduralComponents {
protected static List componentWeightList;
static int totalWeight;
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* The two methods/fields below *must* be recreated in the subclasses.
* Due to poor language design, Java does not allow the overriding/creation of static abstract methods;
* due to reasonable language design, Java does not allow overriding abstract fields.
* getWeightArray() should contain an array with Weight(s) for your components.
*/
//protected static final Weight[] weightArray = new Weight[] { };
/*public static void prepareComponents() {
componentWeightList = new ArrayList();
for(int i = 0; i < weightArray.length; i++) {
weightArray[i].instancesSpawned = 0;
componentWeightList.add(weightArray[i]);
}
}*/
protected static boolean canAddStructurePieces() {
boolean flag = false;
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;
}
protected static ProceduralComponent getWeightedComponent(ControlComponent original, List components, Random rand, int minX, int minY, int minZ, int coordMode, int componentType) {
if(!canAddStructurePieces())
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 static ProceduralComponent getNextValidComponent(ControlComponent original, List components, Random rand, int minX, int minY, int minZ, int coordMode, int componentType) {
if(components.size() > 50) //Hard limit on amount of components
return null;
if(Math.abs(minX - original.getBoundingBox().minX) <= 64 && Math.abs(minZ - original.getBoundingBox().minZ) <= 64) { //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;
}
/** 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(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(ControlComponent original, List components, Random rand, int offset, int offsetY) {
switch(this.coordBaseMode) {
case 0: //South
return getNextValidComponent(original, components, rand, this.boundingBox.minX + offset, this.boundingBox.minY + offsetY, this.boundingBox.maxZ + 1, this.coordBaseMode, this.getComponentType());
case 1: //West
return getNextValidComponent(original, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + offsetY, this.boundingBox.minZ + offset, this.coordBaseMode, this.getComponentType());
case 2: //North
return getNextValidComponent(original, components, rand, this.boundingBox.maxX - offset, this.boundingBox.minY + offsetY, this.boundingBox.minZ - 1, this.coordBaseMode, this.getComponentType());
case 3: //East
return getNextValidComponent(original, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + offsetY, this.boundingBox.maxZ - offset, this.coordBaseMode, 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(ControlComponent original, List components, Random rand, int offset, int offsetY) {
switch(this.coordBaseMode) {
case 0: //South
return getNextValidComponent(original, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + offsetY, this.boundingBox.minZ + offset, 1, this.getComponentType());
case 1: //West
return getNextValidComponent(original, components, rand, this.boundingBox.maxX - offset, this.boundingBox.minY + offsetY, this.boundingBox.minZ - 1, 2, this.getComponentType());
case 2: //North
return getNextValidComponent(original, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + offsetY, this.boundingBox.maxZ - offset, 3, this.getComponentType());
case 3: //East
return 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(ControlComponent original, List components, Random rand, int offset, int offsetY) {
switch(this.coordBaseMode) {
case 0: //South
return getNextValidComponent(original, components, rand, this.boundingBox.maxX + 1, this.boundingBox.minY + offsetY, this.boundingBox.maxZ - offset, 1, this.getComponentType() + 1);
case 1: //West
return getNextValidComponent(original, components, rand, this.boundingBox.minZ + offset, this.boundingBox.minY + offsetY, this.boundingBox.maxZ + 1, 2, this.getComponentType() + 1);
case 2: //North
return getNextValidComponent(original, components, rand, this.boundingBox.minX - 1, this.boundingBox.minY + offsetY, this.boundingBox.minZ + offset, 3, this.getComponentType() + 1);
case 3: //East
return getNextValidComponent(original, components, rand, this.boundingBox.maxX - offset, this.boundingBox.minY + offsetY, this.boundingBox.minZ - 1, 0, this.getComponentType() + 1);
default:
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);
}
}
}
/** 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.instanceLimit < 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

@ -10,7 +10,7 @@ import net.minecraft.world.gen.structure.StructureBoundingBox;
public class RuinFeatures {
public static class NTMRuin1 extends Feature {
public static class NTMRuin1 extends Component {
private static ConcreteBricks RandomConcreteBricks = new ConcreteBricks();
@ -82,7 +82,7 @@ public class RuinFeatures {
}
}
public static class NTMRuin2 extends Feature {
public static class NTMRuin2 extends Component {
private static ConcreteBricks RandomConcreteBricks = new ConcreteBricks();
@ -145,7 +145,7 @@ public class RuinFeatures {
}
}
public static class NTMRuin3 extends Feature {
public static class NTMRuin3 extends Component {
private static ConcreteBricks RandomConcreteBricks = new ConcreteBricks();
@ -202,7 +202,7 @@ public class RuinFeatures {
}
}
public static class NTMRuin4 extends Feature {
public static class NTMRuin4 extends Component {
private static ConcreteBricks RandomConcreteBricks = new ConcreteBricks();