add basic cave world structure

This commit is contained in:
Ellpeck 2017-03-07 17:59:02 +01:00
parent 911caed6d2
commit ab816a52d4
9 changed files with 367 additions and 15 deletions

View file

@ -14,6 +14,7 @@ import de.ellpeck.actuallyadditions.api.ActuallyAdditionsAPI;
import de.ellpeck.actuallyadditions.mod.achievement.InitAchievements;
import de.ellpeck.actuallyadditions.mod.blocks.InitBlocks;
import de.ellpeck.actuallyadditions.mod.booklet.InitBooklet;
import de.ellpeck.actuallyadditions.mod.cave.WorldTypeCave;
import de.ellpeck.actuallyadditions.mod.config.ConfigurationHandler;
import de.ellpeck.actuallyadditions.mod.crafting.CrusherCrafting;
import de.ellpeck.actuallyadditions.mod.crafting.InitCrafting;
@ -70,6 +71,8 @@ public class ActuallyAdditions{
public static boolean teslaLoaded;
public static boolean commonCapsLoaded;
public static boolean isCaveMode = true;
static{
//For some reason, this has to be done here
FluidRegistry.enableUniversalBucket();
@ -100,6 +103,10 @@ public class ActuallyAdditions{
new UpdateChecker();
proxy.preInit(event);
if(isCaveMode){
new WorldTypeCave();
}
ModUtil.LOGGER.info("PreInitialization Finished.");
}

View file

@ -0,0 +1,125 @@
/*
* This file ("CaveEvents.java") is part of the Actually Additions mod for Minecraft.
* It is created and owned by Ellpeck and distributed
* under the Actually Additions License to be found at
* http://ellpeck.de/actaddlicense
* View the source code at https://github.com/Ellpeck/ActuallyAdditions
*
* © 2015-2017 Ellpeck
*/
package de.ellpeck.actuallyadditions.mod.cave;
import de.ellpeck.actuallyadditions.mod.blocks.InitBlocks;
import de.ellpeck.actuallyadditions.mod.data.PlayerData;
import de.ellpeck.actuallyadditions.mod.data.PlayerData.PlayerSave;
import de.ellpeck.actuallyadditions.mod.data.WorldData;
import de.ellpeck.actuallyadditions.mod.gen.WorldGenLushCaves;
import de.ellpeck.actuallyadditions.mod.items.InitItems;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.MobEffects;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.PotionEffect;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent.PlayerTickEvent;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
public class CaveEvents{
private static final int TRIES_BEFORE_FAILURE = 500;
private static final int DISTANCE_INBETWEEN = 1000;
private static final int CAVE_SPAWN_SPREAD = 50000;
@SubscribeEvent
public void onPlayerUpdate(PlayerTickEvent event){
EntityPlayer player = event.player;
if(!player.world.isRemote){
if(WorldTypeCave.is(player.world)){
WorldData data = WorldData.get(player.world);
if(data != null){
BlockPos spawn = data.generatedCaves.get(player.getUniqueID());
if(spawn == null){
BlockPos cavePos = generateCave(player, data.generatedCaves);
data.generatedCaves.put(player.getUniqueID(), cavePos);
data.markDirty();
}
else{
if(player.posY >= player.world.getHeight()){
putPlayerInCave(player, spawn);
}
}
}
}
}
}
private static BlockPos generateCave(EntityPlayer player, Map<UUID, BlockPos> generatedCaves){
BlockPos worldSpawn = player.world.getSpawnPoint();
Random rand = new Random(player.world.getSeed());
BlockPos spawn = null;
tries:
for(int i = 0; i < TRIES_BEFORE_FAILURE; i++){
int randX = MathHelper.getInt(rand, -CAVE_SPAWN_SPREAD, CAVE_SPAWN_SPREAD);
int randY = MathHelper.getInt(rand, 56, 200);
int randZ = MathHelper.getInt(rand, -CAVE_SPAWN_SPREAD, CAVE_SPAWN_SPREAD);
spawn = new BlockPos(worldSpawn.getX()+randX, randY, worldSpawn.getZ()+randZ);
for(BlockPos pos : generatedCaves.values()){
if(pos.distanceSq(spawn) <= DISTANCE_INBETWEEN*DISTANCE_INBETWEEN){
continue tries;
}
}
break;
}
int chunkX = spawn.getX() >> 4;
int chunkZ = spawn.getZ() >> 4;
for(int x = -12; x <= 12; x++){
for(int z = -12; z <= 12; z++){
player.world.getChunkProvider().provideChunk(chunkX+x, chunkZ+z);
}
}
StructureBoundingBox box = new StructureBoundingBox(spawn.getX()-7, 0, spawn.getZ()-7, spawn.getX()+7, player.world.getHeight(), spawn.getZ()+7);
new WorldGenLushCaves().generate(player.world, rand, spawn, box);
putPlayerInCave(player, spawn);
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
server.saveAllWorlds(false);
return spawn;
}
private static void putPlayerInCave(EntityPlayer player, BlockPos spawn){
if(!player.isSpectator() && player instanceof EntityPlayerMP){
player.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, 400, 4));
player.addPotionEffect(new PotionEffect(MobEffects.FIRE_RESISTANCE, 400));
player.addPotionEffect(new PotionEffect(MobEffects.NIGHT_VISION, 400));
PlayerSave save = PlayerData.getDataFromPlayer(player);
if(save != null && !save.bookGottenAlready){
player.inventory.addItemStackToInventory(new ItemStack(InitItems.itemBooklet));
player.inventory.addItemStackToInventory(new ItemStack(InitBlocks.blockTinyTorch, 2));
save.bookGottenAlready = true;
WorldData.get(player.world).markDirty();
}
((EntityPlayerMP)player).connection.setPlayerLocation(spawn.getX()+0.5, spawn.getY()+1, spawn.getZ()+0.5, 0F, 0F);
}
}
}

View file

@ -0,0 +1,125 @@
/*
* This file ("ChunkProviderCaves.java") is part of the Actually Additions mod for Minecraft.
* It is created and owned by Ellpeck and distributed
* under the Actually Additions License to be found at
* http://ellpeck.de/actaddlicense
* View the source code at https://github.com/Ellpeck/ActuallyAdditions
*
* © 2015-2017 Ellpeck
*/
package de.ellpeck.actuallyadditions.mod.cave;
import net.minecraft.block.BlockStone;
import net.minecraft.block.BlockStone.EnumType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.init.Biomes;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.IChunkGenerator;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class ChunkProviderCave implements IChunkGenerator{
private final World world;
private final Random rand;
public ChunkProviderCave(World world){
this.world = world;
this.rand = new Random(world.getSeed());
}
@Override
public Chunk provideChunk(int chunkX, int chunkZ){
ChunkPrimer primer = new ChunkPrimer();
int height = this.world.getHeight();
for(int y = 0; y < height; y++){
boolean isTopOrBottom = y == 0 || y == height-1;
for(int x = 0; x < 16; ++x){
for(int z = 0; z < 16; ++z){
if(isTopOrBottom){
primer.setBlockState(x, y, z, Blocks.BEDROCK.getDefaultState());
}
else{
IBlockState state;
int rand = this.rand.nextInt(485);
if(rand <= 250){
state = Blocks.STONE.getDefaultState();
}
else if(rand <= 350){
state = Blocks.COBBLESTONE.getDefaultState();
}
else if(rand <= 360){
state = Blocks.STONE.getDefaultState().withProperty(BlockStone.VARIANT, EnumType.ANDESITE);
}
else if(rand <= 370){
state = Blocks.STONE.getDefaultState().withProperty(BlockStone.VARIANT, EnumType.DIORITE);
}
else if(rand <= 380){
state = Blocks.STONE.getDefaultState().withProperty(BlockStone.VARIANT, EnumType.GRANITE);
}
else if(rand <= 430){
state = Blocks.DIRT.getDefaultState();
}
else if(rand <= 450){
state = Blocks.CLAY.getDefaultState();
}
else if(rand <= 480){
state = Blocks.GRAVEL.getDefaultState();
}
else{
state = Blocks.MOSSY_COBBLESTONE.getDefaultState();
}
primer.setBlockState(x, y, z, state);
}
}
}
}
Chunk chunk = new Chunk(this.world, primer, chunkX, chunkZ);
byte[] biomes = chunk.getBiomeArray();
Arrays.fill(biomes, (byte)Biome.getIdForBiome(Biomes.FOREST));
chunk.generateSkylightMap();
return chunk;
}
@Override
public void populate(int x, int z){
}
@Override
public boolean generateStructures(Chunk chunkIn, int x, int z){
return false;
}
@Override
public List<Biome.SpawnListEntry> getPossibleCreatures(EnumCreatureType creatureType, BlockPos pos){
Biome biome = this.world.getBiome(pos);
return biome.getSpawnableList(creatureType);
}
@Override
public BlockPos getStrongholdGen(World worldIn, String structureName, BlockPos position, boolean bool){
return null;
}
@Override
public void recreateStructures(Chunk chunkIn, int x, int z){
}
}

View file

@ -0,0 +1,56 @@
/*
* This file ("WorldTypeCave.java") is part of the Actually Additions mod for Minecraft.
* It is created and owned by Ellpeck and distributed
* under the Actually Additions License to be found at
* http://ellpeck.de/actaddlicense
* View the source code at https://github.com/Ellpeck/ActuallyAdditions
*
* © 2015-2017 Ellpeck
*/
package de.ellpeck.actuallyadditions.mod.cave;
import de.ellpeck.actuallyadditions.mod.ActuallyAdditions;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.world.WorldType;
import net.minecraft.world.chunk.IChunkGenerator;
import java.util.Random;
public class WorldTypeCave extends WorldType{
public WorldTypeCave(){
super("actaddcaves");
}
@Override
public float getCloudHeight(){
return 1024F;
}
@Override
public boolean showWorldInfoNotice(){
return true;
}
@Override
public boolean handleSlimeSpawnReduction(Random random, World world){
return true;
}
@Override
public int getSpawnFuzz(WorldServer world, MinecraftServer server){
return 1;
}
@Override
public IChunkGenerator getChunkGenerator(World world, String generatorOptions){
return new ChunkProviderCave(world);
}
public static boolean is(World world){
return ActuallyAdditions.isCaveMode && world.getWorldType() instanceof WorldTypeCave;
}
}

View file

@ -23,17 +23,15 @@ import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public final class PlayerData{
public static PlayerSave getDataFromPlayer(EntityPlayer player){
WorldData worldData = WorldData.get(player.getEntityWorld());
ConcurrentHashMap<UUID, PlayerSave> data = worldData.playerSaveData;
WorldData data = WorldData.get(player.getEntityWorld());
UUID id = player.getUniqueID();
if(data.containsKey(id)){
PlayerSave save = data.get(id);
if(data.playerSaveData.containsKey(id)){
PlayerSave save = data.playerSaveData.get(id);
if(save != null && save.id != null && save.id.equals(id)){
return save;
}
@ -41,8 +39,8 @@ public final class PlayerData{
//Add Data if none is existant
PlayerSave save = new PlayerSave(id);
data.put(id, save);
worldData.markDirty();
data.playerSaveData.put(id, save);
data.markDirty();
return save;
}

View file

@ -11,6 +11,7 @@
package de.ellpeck.actuallyadditions.mod.data;
import de.ellpeck.actuallyadditions.api.laser.Network;
import de.ellpeck.actuallyadditions.mod.ActuallyAdditions;
import de.ellpeck.actuallyadditions.mod.data.PlayerData.PlayerSave;
import de.ellpeck.actuallyadditions.mod.misc.apiimpl.LaserRelayConnectionHandler;
import de.ellpeck.actuallyadditions.mod.util.ModUtil;
@ -18,6 +19,7 @@ import io.netty.util.internal.ConcurrentSet;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.WorldSavedData;
import net.minecraft.world.WorldServer;
@ -26,9 +28,7 @@ import net.minecraftforge.common.WorldSpecificSaveHandler;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class WorldData extends WorldSavedData{
@ -37,8 +37,9 @@ public class WorldData extends WorldSavedData{
//TODO Remove this as well
public static List<File> legacyLoadWorlds = new ArrayList<File>();
private static WorldData data;
public final ConcurrentSet<Network> laserRelayNetworks = new ConcurrentSet<Network>();
public final ConcurrentHashMap<UUID, PlayerSave> playerSaveData = new ConcurrentHashMap<UUID, PlayerSave>();
public final Set<Network> laserRelayNetworks = new ConcurrentSet<Network>();
public final Map<UUID, PlayerSave> playerSaveData = new ConcurrentHashMap<UUID, PlayerSave>();
public final Map<UUID, BlockPos> generatedCaves = new ConcurrentHashMap<UUID, BlockPos>();
public WorldData(String name){
super(name);
@ -149,6 +150,20 @@ public class WorldData extends WorldSavedData{
save.readFromNBT(data, true);
this.playerSaveData.put(id, save);
}
this.generatedCaves.clear();
if(ActuallyAdditions.isCaveMode){
NBTTagList caveList = compound.getTagList("GeneratedCaves", 10);
for(int i = 0; i < caveList.tagCount(); i++){
NBTTagCompound cave = caveList.getCompoundTagAt(i);
UUID id = cave.getUniqueId("UUID");
BlockPos pos = new BlockPos(cave.getInteger("X"), cave.getInteger("Y"), cave.getInteger("Z"));
this.generatedCaves.put(id, pos);
}
}
}
@Override
@ -179,6 +194,22 @@ public class WorldData extends WorldSavedData{
}
compound.setTag("PlayerData", playerList);
if(ActuallyAdditions.isCaveMode){
NBTTagList caveList = new NBTTagList();
for(Map.Entry<UUID, BlockPos> entry : this.generatedCaves.entrySet()){
NBTTagCompound cave = new NBTTagCompound();
cave.setUniqueId("UUID", entry.getKey());
BlockPos pos = entry.getValue();
cave.setInteger("X", pos.getX());
cave.setInteger("Y", pos.getY());
cave.setInteger("Z", pos.getZ());
caveList.appendTag(cave);
}
compound.setTag("GeneratedCaves", caveList);
}
return compound;
}
}

View file

@ -10,8 +10,10 @@
package de.ellpeck.actuallyadditions.mod.event;
import de.ellpeck.actuallyadditions.mod.ActuallyAdditions;
import de.ellpeck.actuallyadditions.mod.achievement.InitAchievements;
import de.ellpeck.actuallyadditions.mod.achievement.TheAchievements;
import de.ellpeck.actuallyadditions.mod.cave.CaveEvents;
import de.ellpeck.actuallyadditions.mod.config.values.ConfigBoolValues;
import de.ellpeck.actuallyadditions.mod.data.PlayerData;
import de.ellpeck.actuallyadditions.mod.data.WorldData;
@ -41,6 +43,10 @@ public class CommonEvents{
public CommonEvents(){
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(new DungeonLoot());
if(ActuallyAdditions.isCaveMode){
MinecraftForge.EVENT_BUS.register(new CaveEvents());
}
}
public static void checkAchievements(ItemStack gotten, EntityPlayer player, InitAchievements.Type type){

View file

@ -13,6 +13,7 @@ package de.ellpeck.actuallyadditions.mod.gen;
import de.ellpeck.actuallyadditions.mod.blocks.InitBlocks;
import de.ellpeck.actuallyadditions.mod.blocks.metalists.TheMiscBlocks;
import de.ellpeck.actuallyadditions.mod.blocks.metalists.TheWildPlants;
import de.ellpeck.actuallyadditions.mod.cave.WorldTypeCave;
import de.ellpeck.actuallyadditions.mod.config.values.ConfigBoolValues;
import de.ellpeck.actuallyadditions.mod.config.values.ConfigIntListValues;
import de.ellpeck.actuallyadditions.mod.config.values.ConfigIntValues;
@ -57,9 +58,9 @@ public class OreGen implements IWorldGenerator{
@Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider){
int dimension = world.provider.getDimension();
if(dimension != -1 && dimension != 1){
if(world.getWorldType() != WorldType.FLAT && !ArrayUtils.contains(ConfigIntListValues.ORE_GEN_DIMENSION_BLACKLIST.getValue(), world.provider.getDimension())){
if(world.getWorldType() != WorldType.FLAT && !WorldTypeCave.is(world)){
int dimension = world.provider.getDimension();
if(dimension != -1 && dimension != 1 && !ArrayUtils.contains(ConfigIntListValues.ORE_GEN_DIMENSION_BLACKLIST.getValue(), dimension)){
this.generateDefault(world, random, chunkX, chunkZ);
}
}

View file

@ -663,6 +663,9 @@ info.actuallyadditions.laserRelay.mode.both=Both Directions
info.actuallyadditions.laserRelay.mode.outputOnly=Only into adjacent Blocks
info.actuallyadditions.laserRelay.mode.inputOnly=Only out of adjacent Blocks
info.actuallyadditions.laserRelay.mode.noCompasss=Hold a %s to modify!
info.actuallyadditions.cave.generating=Generating cave for player %s, server might lag for a bit...
info.actuallyadditions.cave.generated=Finished generating cave for player %s.
info.actuallyadditions.cave.generatingScreen=Generating cave...
#Container Names
container.actuallyadditions.inputter.name=ESD