diff options
Diffstat (limited to 'src/main/java/galacticgreg/WorldGeneratorSpace.java')
-rw-r--r-- | src/main/java/galacticgreg/WorldGeneratorSpace.java | 564 |
1 files changed, 564 insertions, 0 deletions
diff --git a/src/main/java/galacticgreg/WorldGeneratorSpace.java b/src/main/java/galacticgreg/WorldGeneratorSpace.java new file mode 100644 index 0000000000..336900326c --- /dev/null +++ b/src/main/java/galacticgreg/WorldGeneratorSpace.java @@ -0,0 +1,564 @@ +package galacticgreg; + +import java.util.Random; + +import net.minecraft.block.Block; +import net.minecraft.inventory.IInventory; +import net.minecraft.util.Vec3; +import net.minecraft.util.WeightedRandomChestContent; +import net.minecraft.world.World; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraftforge.common.ChestGenHooks; + +import cpw.mods.fml.common.IWorldGenerator; +import cpw.mods.fml.common.eventhandler.EventBus; +import cpw.mods.fml.common.registry.GameRegistry; +import galacticgreg.api.AsteroidBlockComb; +import galacticgreg.api.BlockMetaComb; +import galacticgreg.api.Enums; +import galacticgreg.api.GTOreTypes; +import galacticgreg.api.ISpaceObjectGenerator; +import galacticgreg.api.ModDimensionDef; +import galacticgreg.api.SpecialBlockComb; +import galacticgreg.api.StructureInformation; +import galacticgreg.auxiliary.GTOreGroup; +import galacticgreg.dynconfig.DynamicDimensionConfig; +import galacticgreg.registry.GalacticGregRegistry; +import gregtech.api.util.GTLog; +import gregtech.api.world.GTWorldgen; +import gregtech.common.GTWorldgenerator; + +public class WorldGeneratorSpace implements IWorldGenerator { + + public static boolean sAsteroids = true; + private final EventBus eventBus = new EventBus(); + private World worldObj; + + private int chunkX; + private int chunkZ; + private int mSize = 100; + + private long mProfilingStart; + private long mProfilingEnd; + + public WorldGeneratorSpace() { + GameRegistry.registerWorldGenerator(this, Integer.MAX_VALUE); + } + + public void generate(Random pRandom, int pX, int pZ, World pWorld, IChunkProvider pChunkGenerator, + IChunkProvider pChunkProvider) { + pX *= 16; + pZ *= 16; + + String tBiome = pWorld.getBiomeGenForCoords(pX + 8, pZ + 8).biomeName; + pRandom = new Random(pRandom.nextInt()); + if (tBiome == null) { + tBiome = BiomeGenBase.plains.biomeName; + } + GalacticGreg.Logger + .trace("Triggered generate: [ChunkGenerator %s] [Biome %s]", pChunkGenerator.toString(), tBiome); + + ModDimensionDef tDimDef = GalacticGregRegistry.getDimensionTypeByChunkGenerator(pChunkGenerator); + + if (tDimDef == null) { + GalacticGreg.Logger.trace( + "Ignoring ChunkGenerator type %s as there is no definition for it in the registry", + pChunkGenerator.toString()); + return; + } else { + GalacticGreg.Logger.trace("Selected DimDef: [%s]", tDimDef.getDimIdentifier()); + } + + /* + * In some later addons maybe, not for now. Ignoring Biome-based worldgen String tBiome = + * pWorld.getBiomeGenForCoords(pX + 8, pZ + 8).biomeName; pRandom = new Random(pRandom.nextInt()); if (tBiome == + * null) { tBiome = BiomeGenBase.plains.biomeName; } + */ + + if (tDimDef.getDimensionType() != Enums.DimensionType.Planet) { + if (tDimDef.getRandomAsteroidMaterial() == null) GalacticGreg.Logger.error( + "Dimension [%s] is set to Asteroids, but no asteroid material is specified! Nothing will generate", + tDimDef.getDimensionName()); + else Generate_Asteroids(tDimDef, pRandom, pWorld, pX, pZ); + } else if (tDimDef.getDimensionType() != Enums.DimensionType.Asteroid) { + Generate_OreVeins(tDimDef, pRandom, pWorld, pX, pZ, "", pChunkGenerator, pChunkProvider); + } + + Chunk tChunk = pWorld.getChunkFromBlockCoords(pX, pZ); + if (tChunk != null) { + tChunk.isModified = true; + } + } + + private void Generate_Asteroids(ModDimensionDef pDimensionDef, Random pRandom, World pWorld, int pX, int pZ) { + GalacticGreg.Logger.trace("Running asteroid-gen in Dim %s", pDimensionDef.getDimIdentifier()); + + DynamicDimensionConfig.AsteroidConfig tAConf = DynamicDimensionConfig.getAsteroidConfig(pDimensionDef); + if (tAConf == null) { + GalacticGreg.Logger.error( + "Dimension %s is set to asteroid, but no config object can be found. Skipping!", + pDimensionDef.getDimIdentifier()); + return; + } else { + GalacticGreg.Logger.trace("Asteroid probability: %d", tAConf.Probability); + } + + if ((tAConf.Probability <= 1) || (pRandom.nextInt(tAConf.Probability) == 0)) { + GalacticGreg.Logger.trace("Generating asteroid NOW"); + // --------------------------- + if (GalacticGreg.GalacticConfig.ProfileOreGen) mProfilingStart = System.currentTimeMillis(); + // ----------------------------- + + // Get Random position + int tX = pX + pRandom.nextInt(16); + int tY = 50 + pRandom.nextInt(200 - 50); + int tZ = pZ + pRandom.nextInt(16); + + // Check if position is free + if ((pWorld.getBlock(tX, tY, tZ) + .isAir(pWorld, tX, tY, tZ))) { + + int tCustomAsteroidOffset = -1; + int tGraniteMeta = 0; + + // Select Random OreGroup and Asteroid Material + GTOreGroup tOreGroup = WorldgenOreLayerSpace.getRandomOreGroup(pDimensionDef, pRandom, true); + AsteroidBlockComb tABComb = pDimensionDef.getRandomAsteroidMaterial(); + if (tABComb == null) return; + + // Fill Vars for random Asteroid + Block tFinalAsteroidBlock = tABComb.getBlock(); + int tFinalAsteroidBlockMeta = tABComb.getMeta(); + int tFinalOreOffset = tABComb.getOreMaterial() + .getOffset(); + int tFinalUpdateMode = tABComb.getOreMaterial() + .getUpdateMode(); + GalacticGreg.Logger.debug( + "Asteroid will be build with: Block: [%s] OreType: [%s]", + Block.blockRegistry.getNameForObject(tABComb.getBlock()), + tABComb.getOreMaterial() + .toString()); + + // get random Ore-asteroid generator from the list of registered generators + ISpaceObjectGenerator aGen = pDimensionDef.getRandomSOGenerator(Enums.SpaceObjectType.OreAsteroid); + if (aGen == null) { + GalacticGreg.Logger.ot_error( + "GalacticGreg.Generate_Asteroids.NoSOGenFound", + "No SpaceObjectGenerator has been registered for type ORE_ASTEROID in Dimension %s. Nothing will generate", + pDimensionDef.getDimensionName()); + return; + } + + aGen.reset(); + aGen.setCenterPoint(tX, tY, tZ); + aGen.randomize(tAConf.MinSize, tAConf.MaxSize); // Initialize random values and set size + aGen.calculate(); // Calculate structure + + // Random loot-chest somewhere in the asteroid + Vec3 tChestPosition = Vec3.createVectorHelper(0, 0, 0); + boolean tDoLootChest = false; + int tNumLootItems = 0; + if (tAConf.LootChestChance > 0) { + GalacticGreg.Logger.trace("Random loot chest enabled, flipping the coin"); + int tChance = pRandom.nextInt(100); // Loot chest is 1 in 100 (Was: 1:1000 which actually never + // happend) + if (tAConf.LootChestChance >= tChance) { + GalacticGreg.Logger.debug("We got a match. Preparing to generate the loot chest"); + // Get amount of items for the loot chests, randomize it (1-num) if enabled + if (tAConf.RandomizeNumLootItems) tNumLootItems = pRandom.nextInt(tAConf.NumLootItems - 1) + 1; + else tNumLootItems = tAConf.NumLootItems; + + GalacticGreg.Logger + .debug(String.format("Loot chest random item count will be: %d", tNumLootItems)); + + // try to find any block that is not on the asteroids outer-shell + GalacticGreg.Logger.trace("Starting lookup for valid asteroid-block for the chest"); + for (int x = 0; x < 64; x++) // 64 enough? Should be + { + int tRndBlock = pRandom.nextInt( + aGen.getStructure() + .size()); + StructureInformation tChestSI = aGen.getStructure() + .get(tRndBlock); + if (tChestSI.getBlockPosition() != Enums.TargetBlockPosition.AsteroidShell) { + GalacticGreg.Logger.debug( + String.format( + "Chest position found [x:%d y:%d z:%d]", + tChestSI.getX(), + tChestSI.getY(), + tChestSI.getZ())); + // Found valid position "Somewhere" in the asteroid, set position... + tChestPosition = Vec3 + .createVectorHelper(tChestSI.getX(), tChestSI.getY(), tChestSI.getZ()); + // .. and set CreateFlag to true + tDoLootChest = true; + break; + } + } + } + } + + // Now build the structure + GalacticGreg.Logger.trace("Now generating Space-Structure"); + for (StructureInformation si : aGen.getStructure()) { + // Only replace airblocks + if (pWorld.isAirBlock(si.getX(), si.getY(), si.getZ())) { + // === Loot-chest generator >> + if (tDoLootChest) // If gen-lootchest enabled... + { + // Check if current x/y/z is the location where the chest shall be created + if ((int) tChestPosition.xCoord == si.getX() && (int) tChestPosition.yCoord == si.getY() + && (int) tChestPosition.zCoord == si.getZ()) { + GalacticGreg.Logger.trace("Now generating LootChest and contents"); + // Get items for the configured loot-table + WeightedRandomChestContent[] tRandomLoot = ChestGenHooks + .getItems(DynamicDimensionConfig.getLootChestTable(tAConf), pRandom); + + // Get chest-block to spawn + BlockMetaComb tTargetChestType = GalacticGreg.GalacticConfig.CustomLootChest; + + // Place down the chest + if (tTargetChestType.getMeta() > 0) pWorld.setBlock( + si.getX(), + si.getY(), + si.getZ(), + tTargetChestType.getBlock(), + tTargetChestType.getMeta(), + 2); + else pWorld.setBlock(si.getX(), si.getY(), si.getZ(), tTargetChestType.getBlock()); + + // Retrieve the TEs IInventory that should've been created + IInventory entityChestInventory = (IInventory) pWorld + .getTileEntity(si.getX(), si.getY(), si.getZ()); + // If it's not null... + if (entityChestInventory != null) { + // and if we're on the server... + if (!pWorld.isRemote) { + // Fill the chest with stuffz! + WeightedRandomChestContent.generateChestContents( + pRandom, + tRandomLoot, + entityChestInventory, + tNumLootItems); + GalacticGreg.Logger.trace("Loot chest successfully generated"); + } + } else { + // Something made a boo.. + GalacticGreg.Logger.warn( + "Could not create lootchest at X[%d] Y[%d] Z[%d]. getTileEntity() returned null", + si.getX(), + si.getY(), + si.getZ()); + } + // Make sure we never compare coordinates again (for this asteroid/Structure) + tDoLootChest = false; + // Do some debug logging + GalacticGreg.Logger + .debug("Generated LootChest at X[%d] Y[%d] Z[%d]", si.getX(), si.getY(), si.getZ()); + // And skip the rest of this function + continue; + } + } + // << Loot-chest generator === + + // === Ore generator >> + boolean tPlacedOreBlock = false; + // If a valid oregroup has been selected (more than 0 ore-veins are enabled for this dim) + if (tOreGroup != null) { + // GalacticGreg.Logger.trace("tOreGoup is populated, continuing"); + // Choose a number between 0 and 100 + int ranOre = pRandom.nextInt(100); + int tFinalOreMeta = 0; + + // If choosen number is below the configured orechance, do random between and sporadic + if (ranOre < tAConf.OreChance) { + if (pRandom.nextBoolean()) { + // Only take as final value if meta is not zero + if (tOreGroup.SporadicBetweenMeta > 0) + tFinalOreMeta = tOreGroup.SporadicBetweenMeta; + } else { + // Only take as final value if meta is not zero + if (tOreGroup.SporadicAroundMeta > 0) tFinalOreMeta = tOreGroup.SporadicAroundMeta; + } + } + // If choosen number is below the configured orechance, do random primary and secondary + // We use an offset here, so this part is always higher than the first check. + else if (ranOre < tAConf.OreChance + tAConf.OrePrimaryOffset) { + if (pRandom.nextBoolean()) { + // Only take as final value if meta is not zero + if (tOreGroup.PrimaryMeta > 0) tFinalOreMeta = tOreGroup.PrimaryMeta; + } else { + // Only take as final value if meta is not zero + if (tOreGroup.SecondaryMeta > 0) tFinalOreMeta = tOreGroup.SecondaryMeta; + } + } + + // if the final oreMeta has been found... + // GalacticGreg.Logger.info("tFinalOreMeta is %d", tFinalOreMeta); + if (tFinalOreMeta > 0) { + // make sure we obey the configured "HiddenOres" setting (No ores on the shell) + if (tAConf.HiddenOres + && (si.getBlockPosition() == Enums.TargetBlockPosition.AsteroidShell)) { + // Ore would be placed around the shell, which is disabled (hiddenores) + GalacticGreg.Logger.trace( + "Skipping ore-placement event (HiddenOres=true; TargetBlockPosition=AsteroidShell)"); + } else { + // try to place the ore block. The result is stored in tPlacedOreBlock + tPlacedOreBlock = TileEntitySpaceOres.setOuterSpaceOreBlock( + pDimensionDef, + pWorld, + si.getX(), + si.getY(), + si.getZ(), + tOreGroup.SecondaryMeta, + true, + tFinalOreOffset); + } + } + } + // << Ore generator === + + // === Additional special blocks >> + // If no ore-block has been placed yet... + if (!tPlacedOreBlock) { + // try to spawn special blocks + boolean tFlag = doGenerateSpecialBlocks( + pDimensionDef, + pRandom, + pWorld, + tAConf, + si.getX(), + si.getY(), + si.getZ(), + si.getBlockPosition()); + + // No special block placed? Try smallores + if (tFlag) tFlag = doGenerateSmallOreBlock( + pDimensionDef, + pRandom, + pWorld, + tAConf, + si.getX(), + si.getY(), + si.getZ(), + tFinalOreOffset); + + // no smallores either? do normal block + if (tFlag) pWorld.setBlock( + si.getX(), + si.getY(), + si.getZ(), + tFinalAsteroidBlock, + tFinalAsteroidBlockMeta, + tFinalUpdateMode); + + } + // << Additional special blocks === + } + } + } + // --------------------------- + // OreGen profiler stuff + if (GalacticGreg.GalacticConfig.ProfileOreGen) { + try { + mProfilingEnd = System.currentTimeMillis(); + long tTotalTime = mProfilingEnd - mProfilingStart; + GalacticGreg.Profiler.AddTimeToList(pDimensionDef, tTotalTime); + GalacticGreg.Logger.debug( + "Done with Asteroid-Worldgen in DimensionType %s. Generation took %d ms", + pDimensionDef.getDimensionName(), + tTotalTime); + } catch (Exception ignored) {} // Silently ignore errors + } + // --------------------------- + } + GalacticGreg.Logger.trace("Leaving asteroid-gen for Dim %s", pDimensionDef.getDimIdentifier()); + } + + /** + * Generate Special Blocks in asteroids if enabled + * + * @param pDimensionDef + * @param pRandom + * @param pWorld + * @param tAConf + * @param eX + * @param eY + * @param eZ + * @return + */ + private boolean doGenerateSpecialBlocks(ModDimensionDef pDimensionDef, Random pRandom, World pWorld, + DynamicDimensionConfig.AsteroidConfig tAConf, int eX, int eY, int eZ, + Enums.TargetBlockPosition pBlockPosition) { + + boolean tFlag = true; + // Handler to generate special BlockTypes randomly if activated + if (tAConf.SpecialBlockChance > 0) { + if (pRandom.nextInt(100) < tAConf.SpecialBlockChance) { + SpecialBlockComb bmc = pDimensionDef.getRandomSpecialAsteroidBlock(); + if (bmc != null) { + boolean tIsAllowed = false; + + switch (bmc.getBlockPosition()) { + case AsteroidCore: + if (pBlockPosition == Enums.TargetBlockPosition.AsteroidCore) tIsAllowed = true; + break; + case AsteroidCoreAndShell: + if (pBlockPosition == Enums.TargetBlockPosition.AsteroidCore + || pBlockPosition == Enums.TargetBlockPosition.AsteroidShell) tIsAllowed = true; + break; + case AsteroidShell: + if (pBlockPosition == Enums.TargetBlockPosition.AsteroidShell) tIsAllowed = true; + break; + case AsteroidInnerCore: + if (pBlockPosition == Enums.TargetBlockPosition.AsteroidInnerCore) tIsAllowed = true; + break; + default: + break; + } + + if (tIsAllowed) { + pWorld.setBlock(eX, eY, eZ, bmc.getBlock(), bmc.getMeta(), 2); + tFlag = false; + } + } + } + } + return tFlag; + } + + /** + * Pick a random small-ore block from the list of enabled small ores for this dim + * + * @param pDimDef + * @param pRandom + * @return + */ + private boolean doGenerateSmallOreBlock(ModDimensionDef pDimDef, Random pRandom, World pWorld, + DynamicDimensionConfig.AsteroidConfig pAConf, int pX, int pY, int pZ, int pTargetBlockOffset) { + boolean tFlag = true; + // If smallores are enabled... + if (pAConf.SmallOreChance > 0) { + // ... and we hit the random-chance ... + if (pRandom.nextInt(100) < pAConf.SmallOreChance) { + // Do small ores. + int tRandomWeight; + boolean continueSearch = true; + int tFoundOreMeta = -1; + // First find a small ore... + for (int i = 0; (i < 256) && (continueSearch); i++) { + tRandomWeight = pRandom.nextInt(WorldgenOreLayerSpace.sWeight); + for (GTWorldgen tWorldGen : GalacticGreg.smallOreWorldgenList) { + + if (!(tWorldGen instanceof WorldgenOreSmallSpace)) { + continue; + } + // That is enabled for *this* dim... + if (!((WorldgenOreSmallSpace) tWorldGen).isEnabledForDim(pDimDef)) continue; + + // And in the correct y-level, of ObeyLimits is true... + if (pAConf.ObeyHeightLimits && !((WorldgenOreSmallSpace) tWorldGen).isAllowedForHeight(pY)) + continue; + + // Care about weight + tRandomWeight -= ((WorldgenOreSmallSpace) tWorldGen).mAmount; + if (tRandomWeight <= 0) { + // And return found ore meta + tFoundOreMeta = ((WorldgenOreSmallSpace) tWorldGen).mMeta; + continueSearch = false; + } + } + } + if (tFoundOreMeta > -1) { + // Make the oreID a small ore with correct type + int tCustomOffset = (GTOreTypes.SmallOres.getOffset() + pTargetBlockOffset); + + // Set the smallOre block + TileEntitySpaceOres + .setOuterSpaceOreBlock(pDimDef, pWorld, pX, pY, pZ, tFoundOreMeta, true, tCustomOffset); + tFlag = false; + } + } + } + return tFlag; + } + + /** + * Untested! But should work... Comments are todo + * + * @param pDimensionDef + * @param pRandom + * @param pWorld + * @param pX + * @param pZ + * @param pBiome + * @param pChunkGenerator + * @param pChunkProvider + */ + private void Generate_OreVeins(ModDimensionDef pDimensionDef, Random pRandom, World pWorld, int pX, int pZ, + String pBiome, IChunkProvider pChunkGenerator, IChunkProvider pChunkProvider) { + GalacticGreg.Logger.trace("Running orevein-gen in Dim %s", pDimensionDef.getDimIdentifier()); + + if (GTWorldgenerator.isOreChunk(pX / 16, pZ / 16)) { + if ((WorldgenOreLayerSpace.sWeight > 0) && (GalacticGreg.oreVeinWorldgenList.size() > 0)) { + + boolean temp = true; + int tRandomWeight; + for (int i = 0; (i < 256) && (temp); i++) { + tRandomWeight = pRandom.nextInt(WorldgenOreLayerSpace.sWeight); + for (GTWorldgen tWorldGen : GalacticGreg.oreVeinWorldgenList) { + if (tWorldGen instanceof WorldgenOreLayerSpace) + tRandomWeight -= ((WorldgenOreLayerSpace) tWorldGen).mWeight; + + if (tRandomWeight <= 0) { + try { + if (tWorldGen.executeWorldgen( + pWorld, + pRandom, + pBiome, + Integer.MIN_VALUE, + pX, + pZ, + pChunkGenerator, + pChunkProvider)) { + temp = false; + } + } catch (Throwable e) { + e.printStackTrace(GTLog.err); + } + break; + } + } + } + } + // Generate Small Ores + + int i = 0; + for (int tX = pX - 16; i < 3; tX += 16) { + int j = 0; + for (int tZ = pZ - 16; j < 3; tZ += 16) { + for (GTWorldgen tWorldGen : GalacticGreg.smallOreWorldgenList) { + try { + tWorldGen.executeWorldgen( + pWorld, + pRandom, + "", + Integer.MIN_VALUE, + tX, + tZ, + pChunkGenerator, + pChunkProvider); + } catch (Throwable e) { + e.printStackTrace(GTLog.err); + } + } + j++; + } + i++; + } + } + GalacticGreg.Logger.trace("Leaving orevein-gen for Dim %s", pDimensionDef.getDimIdentifier()); + } +} |