/*
* This file is part of Matter Overdrive
* Copyright (c) 2015., Simeon Radivoev, All rights reserved.
*
* Matter Overdrive is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Matter Overdrive is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Matter Overdrive. If not, see <http://www.gnu.org/licenses>.
*/
package matteroverdrive.world;
import cpw.mods.fml.common.IWorldGenerator;
import cpw.mods.fml.common.gameevent.TickEvent;
import matteroverdrive.Reference;
import matteroverdrive.data.world.GenPositionWorldData;
import matteroverdrive.handler.ConfigurationHandler;
import matteroverdrive.init.MatterOverdriveBlocks;
import matteroverdrive.util.IConfigSubscriber;
import net.minecraft.block.Block;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.feature.WorldGenMinable;
import net.minecraftforge.common.config.Property;
import java.util.*;
/**
* Created by Simeon on 3/23/2015.
*/
public class MOWorldGen implements IWorldGenerator, IConfigSubscriber
{
Random oreRandom;
Random anomaliesRandom;
Random buildingsRandom;
public static WorldGenMinable dilithiumGen;
public static WorldGenMinable tritaniumGen;
public static MOAndroidHouseBuilding androidHouse;
public static WorldGenGravitationalAnomaly anomalyGen;
public static MOSandPit sandPit;
public static MOWorldGenCrashedSpaceShip crashedSpaceShip;
public static float BUILDING_SPAWN_CHANCE = 0.01f;
public static final int TRITANIUM_VEINS_PER_CHUNK = 10;
public static final int TRITANIUM_VEIN_SIZE = 6;
public static final int DILITHIUM_VEINS_PER_CHUNK = 6;
public static final int DILITHIUM_VEIN_SIZE = 5;
public List<WeightedRandomMOWorldGenBuilding> buildings;
public Queue<MOWorldGenBuilding.WorldGenBuildingWorker> worldGenBuildingQueue;
HashSet<Integer> oreDimentionsBlacklist;
boolean generateTritanium;
boolean generateDilithium;
boolean generateAnomalies;
boolean generateBuildings;
public MOWorldGen(ConfigurationHandler configurationHandler)
{
oreRandom = new Random();
anomaliesRandom = new Random();
buildingsRandom = new Random();
buildings = new ArrayList<>();
worldGenBuildingQueue = new ArrayDeque<>();
tritaniumGen = new WorldGenMinable(MatterOverdriveBlocks.tritaniumOre,TRITANIUM_VEIN_SIZE);
dilithiumGen = new WorldGenMinable(MatterOverdriveBlocks.dilithium_ore,DILITHIUM_VEIN_SIZE);
buildings.add(new WeightedRandomMOWorldGenBuilding(new MOAndroidHouseBuilding("android_house"),20));
buildings.add(new WeightedRandomMOWorldGenBuilding(new MOSandPit("sand_pit_house",3),100));
buildings.add(new WeightedRandomMOWorldGenBuilding(new MOWorldGenCrashedSpaceShip("crashed_ship"),60));
buildings.add(new WeightedRandomMOWorldGenBuilding(new MOWorldGenUnderwaterBase("underwater_base"),20));
buildings.add(new WeightedRandomMOWorldGenBuilding(new MOWorldGenCargoShip("cargo_ship"),5));
anomalyGen = new WorldGenGravitationalAnomaly("gravitational_anomaly",0.005f,2048,2048 + 8192);
oreDimentionsBlacklist = new HashSet<>();
configurationHandler.subscribe(anomalyGen);
}
@Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
switch (world.provider.dimensionId)
{
case -1:
generateNether(world,random,chunkX * 16,chunkZ * 16);
break;
case 0:
generateOverworld(world, random, chunkX * 16, chunkZ * 16);
break;
case 2:
generateEnd(world, random, chunkX * 16, chunkZ * 16);
break;
default:
generateOther(world,random,chunkX * 16,chunkZ * 16);
}
long worldSeed = world.getSeed();
Random moRandom = new Random(worldSeed);
long xSeed = moRandom.nextLong() >> 2 + 1L;
long zSeed = moRandom.nextLong() >> 2 + 1L;
long chunkSeed = (xSeed * chunkX + zSeed * chunkZ) ^ worldSeed;
oreRandom.setSeed(chunkSeed);
anomaliesRandom.setSeed(chunkSeed);
buildingsRandom.setSeed(chunkSeed);
generateGravitationalAnomalies(world, anomaliesRandom, chunkX * 16, chunkZ * 16, world.provider.dimensionId);
generateOres(world, oreRandom, chunkX * 16, chunkZ * 16, world.provider.dimensionId);
startGenerateBuildings(world,buildingsRandom,chunkX,chunkZ,chunkGenerator,chunkProvider);
}
public void generateOverworld(World world,Random random,int chunkX, int chunkZ)
{
}
public void generateNether(World world,Random random,int chunkX, int chunkZ)
{
}
public void generateEnd(World world,Random random,int chunkX, int chunkZ)
{
}
public void generateOther(World world,Random random,int chunkX, int chunkZ)
{
}
public void generateOres(World world,Random random,int chunkX,int chunkZ,int dimentionID)
{
if (!oreDimentionsBlacklist.contains(dimentionID))
{
if (generateDilithium) {
for (int i = 0; i < DILITHIUM_VEINS_PER_CHUNK; i++) {
int x = chunkX + random.nextInt(16);
int z = chunkZ + random.nextInt(16);
int y = random.nextInt(28) + 4;
if (dilithiumGen.generate(world, random, x, y, z)) {
}
}
}
if (generateTritanium) {
for (int i = 0; i < TRITANIUM_VEINS_PER_CHUNK; i++) {
int x = chunkX + random.nextInt(16);
int z = chunkZ + random.nextInt(16);
int y = random.nextInt(60) + 4;
if (tritaniumGen.generate(world, random, x, y, z)) {
}
}
}
}
}
private void generateGravitationalAnomalies(World world,Random random,int chunkX, int chunkZ,int dimention)
{
if (generateAnomalies)
{
int x = chunkX + random.nextInt(16);
int z = chunkZ + random.nextInt(16);
int y = random.nextInt(60) + 4;
if (anomalyGen.generate(world, random, x, y, z)) {
}
}
}
private boolean shouldGenerate(Block block,ConfigurationHandler config)
{
Property p = config.config.get(ConfigurationHandler.CATEGORY_WORLD_GEN, ConfigurationHandler.CATEGORY_WORLD_SPAWN + "." + block.getUnlocalizedName(), true);
p.setLanguageKey(block.getUnlocalizedName() + ".name");
return p.getBoolean(true);
}
private void startGenerateBuildings(World world, Random random, int chunkX, int chunkZ, IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
{
if (generateBuildings && random.nextDouble() < BUILDING_SPAWN_CHANCE)
{
int XCoord = chunkX*16 + random.nextInt(16);
int ZCoord = chunkZ*16 + random.nextInt(16);
int YCoord = world.getHeightValue(XCoord,ZCoord)-2;
WeightedRandomMOWorldGenBuilding building = getRandomBuilding(world,XCoord,YCoord,ZCoord,random);
if (building != null)
startBuildingGeneration(building.worldGenBuilding,XCoord,YCoord,ZCoord,random,world,chunkGenerator,chunkProvider,false);
}
}
public MOWorldGenBuilding.WorldGenBuildingWorker startBuildingGeneration(MOWorldGenBuilding building, int x, int y, int z, Random random, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider, boolean forceGeneration)
{
if (building != null && (forceGeneration || (building.shouldGenerate(random,world,x,y,z) && building.isLocationValid(world,x,y,z))))
{
MOWorldGenBuilding.WorldGenBuildingWorker worker = building.createWorker(random, x, y, z, world, chunkGenerator, chunkProvider);
worldGenBuildingQueue.add(worker);
return worker;
}
return null;
}
public void manageBuildingGeneration(TickEvent.WorldTickEvent worldTickEvent)
{
MOWorldGenBuilding.WorldGenBuildingWorker worker = worldGenBuildingQueue.peek();
if (worker != null)
{
if(worker.generate())
{
worldGenBuildingQueue.remove();
return;
}
}
}
public WeightedRandomMOWorldGenBuilding getRandomBuilding(World world,int x,int y,int z,Random random)
{
return getBuilding(random,world,x,y,z,buildings,random.nextInt(getTotalBuildingsWeight(random,world,x,y,z,buildings)));
}
public int getTotalBuildingsWeight(Random random,World world,int x,int y,int z,Collection p_76272_0_)
{
int i = 0;
WeightedRandomMOWorldGenBuilding building;
for (Iterator iterator = p_76272_0_.iterator(); iterator.hasNext(); i += building.getWeight(random,world,x,y,z))
{
building = (WeightedRandomMOWorldGenBuilding)iterator.next();
}
return i;
}
public WeightedRandomMOWorldGenBuilding getBuilding(Random random,World world,int x,int y,int z,Collection par1Collection, int weight)
{
int j = weight;
Iterator iterator = par1Collection.iterator();
WeightedRandomMOWorldGenBuilding building;
do
{
if (!iterator.hasNext())
{
return null;
}
building = (WeightedRandomMOWorldGenBuilding)iterator.next();
j -= building.getWeight(random,world,x,y,z);
}
while (j >= 0);
return building;
}
@Override
public void onConfigChanged(ConfigurationHandler config)
{
Property shouldGenerateOres = config.config.get(ConfigurationHandler.CATEGORY_WORLD_GEN, ConfigurationHandler.CATEGORY_WORLD_SPAWN_ORES, true);
shouldGenerateOres.comment = "Should Matter Overdrive Ore Blocks be Generated ?";
generateTritanium = shouldGenerate(MatterOverdriveBlocks.tritaniumOre, config) && shouldGenerateOres.getBoolean(true);
generateDilithium = shouldGenerate(MatterOverdriveBlocks.dilithium_ore, config) && shouldGenerateOres.getBoolean(true);
Property shouldGenerateOthers = config.config.get(ConfigurationHandler.CATEGORY_WORLD_GEN, ConfigurationHandler.CATEGORY_WORLD_SPAWN_OTHER, true);
shouldGenerateOthers.comment = "Should other Matter Overdrive World Blocks be Generated?";
generateAnomalies = shouldGenerate(MatterOverdriveBlocks.gravitational_anomaly, config) && shouldGenerateOthers.getBoolean(true);
this.oreDimentionsBlacklist.clear();
Property oreDimentionBlacklistProp = config.config.get(config.CATEGORY_WORLD_GEN,"ore_gen_blacklist",new int[]{-1,2});
oreDimentionBlacklistProp.comment = "A blacklist of all the Dimensions ores shouldn't spawn in";
oreDimentionBlacklistProp.setLanguageKey("config.ore_gen_blacklist.name");
int[] oreDimentionBlacklist = oreDimentionBlacklistProp.getIntList();
for (int i = 0;i < oreDimentionBlacklist.length;i++)
{
this.oreDimentionsBlacklist.add(oreDimentionBlacklist[i]);
}
generateBuildings = config.getBool("generate buildings",ConfigurationHandler.CATEGORY_WORLD_GEN,true,"Should Matter Overdrive Buildings Generate aka ImageGen");
}
public static GenPositionWorldData getWorldPositionData(World world)
{
GenPositionWorldData data = (GenPositionWorldData)world.loadItemData(GenPositionWorldData.class,Reference.WORLD_DATA_MO_GEN_POSITIONS);
if (data == null)
{
data = new GenPositionWorldData(Reference.WORLD_DATA_MO_GEN_POSITIONS);
world.setItemData(Reference.WORLD_DATA_MO_GEN_POSITIONS,data);
}
return data;
}
}