package blusunrize.immersiveengineering.common.world;
import blusunrize.immersiveengineering.common.Config.IEConfig;
import blusunrize.immersiveengineering.common.util.IELogger;
import com.google.common.collect.ArrayListMultimap;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.state.pattern.BlockMatcher;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkGenerator;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.feature.WorldGenMinable;
import net.minecraftforge.event.world.ChunkDataEvent;
import net.minecraftforge.fml.common.IWorldGenerator;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.relauncher.Side;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
public class IEWorldGen implements IWorldGenerator
{
public static class OreGen
{
String name;
WorldGenMinable mineableGen;
int minY;
int maxY;
int chunkOccurence;
int weight;
public OreGen(String name, IBlockState state, int maxVeinSize, Block replaceTarget, int minY, int maxY,int chunkOccurence, int weight)
{
this.name = name;
this.mineableGen = new WorldGenMinable(state, maxVeinSize, BlockMatcher.forBlock(replaceTarget));
this.minY=minY;
this.maxY=maxY;
this.chunkOccurence=chunkOccurence;
this.weight=weight;
}
public void generate(World world, Random rand, int x, int z)
{
BlockPos pos;
for(int i=0; i<chunkOccurence; i++)
if(rand.nextInt(100)<weight)
{
pos = new BlockPos(x + rand.nextInt(16), minY + rand.nextInt(maxY - minY), z + rand.nextInt(16));
mineableGen.generate(world, rand, pos);
}
}
}
public static ArrayList<OreGen> orespawnList = new ArrayList();
public static ArrayList<Integer> oreDimBlacklist = new ArrayList();
public static HashMap<String, Boolean> retrogenMap = new HashMap();
public static OreGen addOreGen(String name, IBlockState state, int maxVeinSize, int minY, int maxY,int chunkOccurence,int weight)
{
OreGen gen = new OreGen(name, state, maxVeinSize, Blocks.STONE, minY, maxY, chunkOccurence, weight);
orespawnList.add(gen);
return gen;
}
@Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider)
{
this.generateOres(random, chunkX, chunkZ, world, true);
}
public void generateOres(Random random, int chunkX, int chunkZ, World world, boolean newGeneration)
{
if(!oreDimBlacklist.contains(world.provider.getDimension()))
for(OreGen gen : orespawnList)
if(newGeneration || retrogenMap.get("retrogen_"+gen.name))
gen.generate(world, random, chunkX*16, chunkZ*16);
}
@SubscribeEvent
public void chunkSave(ChunkDataEvent.Save event)
{
NBTTagCompound nbt = new NBTTagCompound();
event.getData().setTag("ImmersiveEngineering", nbt);
nbt.setBoolean(IEConfig.Ores.retrogen_key, true);
}
@SubscribeEvent
public void chunkLoad(ChunkDataEvent.Load event)
{
int dimension = event.getWorld().provider.getDimension();
if((!event.getData().getCompoundTag("ImmersiveEngineering").hasKey(IEConfig.Ores.retrogen_key)) && (IEConfig.Ores.retrogen_copper|| IEConfig.Ores.retrogen_bauxite|| IEConfig.Ores.retrogen_lead|| IEConfig.Ores.retrogen_silver|| IEConfig.Ores.retrogen_nickel|| IEConfig.Ores.retrogen_uranium))
{
if(IEConfig.Ores.retrogen_log_flagChunk)
IELogger.info("Chunk "+event.getChunk().getChunkCoordIntPair()+" has been flagged for Ore RetroGeneration by IE.");
retrogenChunks.put(dimension, event.getChunk().getChunkCoordIntPair());
}
}
public static ArrayListMultimap<Integer, ChunkPos> retrogenChunks = ArrayListMultimap.create();
@SubscribeEvent
public void serverWorldTick(TickEvent.WorldTickEvent event)
{
if(event.side==Side.CLIENT || event.phase==TickEvent.Phase.START)
return;
int dimension = event.world.provider.getDimension();
int counter = 0;
List<ChunkPos> chunks = retrogenChunks.get(dimension);
if(chunks!=null && chunks.size()>0)
for(int i=0; i<2; i++)
{
chunks = retrogenChunks.get(dimension);
if(chunks == null || chunks.size()<= 0)
break;
counter++;
ChunkPos loc = chunks.get(0);
long worldSeed = event.world.getSeed();
Random fmlRandom = new Random(worldSeed);
long xSeed = (fmlRandom.nextLong()>>3);
long zSeed = (fmlRandom.nextLong()>>3);
fmlRandom.setSeed(xSeed * loc.chunkXPos + zSeed * loc.chunkZPos ^ worldSeed);
this.generateOres(fmlRandom, loc.chunkXPos, loc.chunkZPos, event.world, false);
chunks.remove(0);
}
if(counter>0 && IEConfig.Ores.retrogen_log_remaining)
IELogger.info("Retrogen was performed on "+counter+" Chunks, "+Math.max(0,chunks.size())+" chunks remaining");
}
}