diff --git a/src/main/java/com/minelittlepony/unicopia/Unicopia.java b/src/main/java/com/minelittlepony/unicopia/Unicopia.java index 57e5400e..efa7586a 100644 --- a/src/main/java/com/minelittlepony/unicopia/Unicopia.java +++ b/src/main/java/com/minelittlepony/unicopia/Unicopia.java @@ -15,6 +15,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.structure.MapGenStructureIO; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.entity.ProjectileImpactEvent; import net.minecraftforge.event.entity.item.ItemTossEvent; @@ -22,6 +23,8 @@ import net.minecraftforge.event.entity.living.LivingEntityUseItemEvent; import net.minecraftforge.event.entity.player.PlayerDropsEvent; import net.minecraftforge.event.entity.player.PlayerFlyableFallEvent; import net.minecraftforge.event.entity.player.UseHoeEvent; +import net.minecraftforge.event.terraingen.PopulateChunkEvent; +import net.minecraftforge.event.terraingen.PopulateChunkEvent.Populate.EventType; import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -60,7 +63,9 @@ import com.minelittlepony.unicopia.network.MsgRequestCapabilities; import com.minelittlepony.unicopia.player.PlayerSpeciesList; import com.minelittlepony.unicopia.power.PowersRegistry; import com.minelittlepony.unicopia.spell.SpellRegistry; +import com.minelittlepony.unicopia.structure.CloudDungeon; import com.minelittlepony.unicopia.util.crafting.CraftingManager; +import com.minelittlepony.unicopia.world.CloudGen; import com.minelittlepony.unicopia.world.UWorld; @Mod( @@ -122,6 +127,16 @@ public class Unicopia implements IGuiHandler { UClient.instance().posInit(event); UItems.fixRecipes(); + + MapGenStructureIO.registerStructure(CloudGen.Start.class, "unicopia:clouds"); + MapGenStructureIO.registerStructureComponent(CloudDungeon.class, "unicopia:cloud_dungeon"); + } + + @EventHandler + public static void onStructureGen(PopulateChunkEvent.Populate event) { + if (event.getType() == EventType.DUNGEON) { + UWorld.instance().generateStructures(event.getWorld(), event.getChunkX(), event.getChunkZ(), event.getGen()); + } } public static CraftingManager getCraftingManager() { diff --git a/src/main/java/com/minelittlepony/unicopia/structure/AbstractFeature.java b/src/main/java/com/minelittlepony/unicopia/structure/AbstractFeature.java new file mode 100644 index 00000000..59faa502 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/structure/AbstractFeature.java @@ -0,0 +1,114 @@ +package com.minelittlepony.unicopia.structure; + +import java.util.Random; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockPos.MutableBlockPos; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.structure.StructureBoundingBox; +import net.minecraft.world.gen.structure.StructureComponent; +import net.minecraft.world.gen.structure.StructureStart; +import net.minecraft.world.gen.structure.template.TemplateManager; + +public abstract class AbstractFeature extends StructureComponent { + + protected int width; + + protected int height; + + protected int depth; + + protected int horizontalPos = -1; + + public AbstractFeature() { + } + + protected AbstractFeature(Random rand, int x, int y, int z, int sizeX, int sizeY, int sizeZ) { + super(0); + + width = sizeX; + height = sizeY; + depth = sizeZ; + + setCoordBaseMode(EnumFacing.Plane.HORIZONTAL.random(rand)); + + if (getCoordBaseMode().getAxis() == EnumFacing.Axis.Z) { + boundingBox = new StructureBoundingBox(x, y, z, x + sizeX - 1, y + sizeY - 1, z + sizeZ - 1); + } else { + boundingBox = new StructureBoundingBox(x, y, z, x + sizeZ - 1, y + sizeY - 1, z + sizeX - 1); + } + } + + @Override + protected void writeStructureToNBT(NBTTagCompound tagCompound) { + tagCompound.setInteger("Width", width); + tagCompound.setInteger("Height", height); + tagCompound.setInteger("Depth", depth); + tagCompound.setInteger("HPos", horizontalPos); + } + + @Override + protected void readStructureFromNBT(NBTTagCompound tagCompound, TemplateManager templater) { + width = tagCompound.getInteger("Width"); + height = tagCompound.getInteger("Height"); + depth = tagCompound.getInteger("Depth"); + horizontalPos = tagCompound.getInteger("HPos"); + } + + protected int getAverageStructureAltitude() { + return 64; + } + + protected boolean offsetToAverageGroundLevel(World worldIn, StructureBoundingBox structurebb, int yOffset) { + if (horizontalPos >= 0) { + return true; + } + + int xOff = 0; + int offsetIncrements = 0; + + int targetY = getAverageStructureAltitude(); + + MutableBlockPos pos = new MutableBlockPos(); + + for (int z = boundingBox.minZ; z <= boundingBox.maxZ; ++z) { + for (int x = boundingBox.minX; x <= boundingBox.maxX; ++x) { + pos.setPos(x, targetY, z); + + if (structurebb.isVecInside(pos)) { + xOff += Math.max(worldIn.getTopSolidOrLiquidBlock(pos).getY(), worldIn.provider.getAverageGroundLevel()); + offsetIncrements++; + } + } + } + + if (offsetIncrements == 0) { + return false; + } + + horizontalPos = xOff / offsetIncrements; + boundingBox.offset(0, horizontalPos - boundingBox.minY + yOffset, 0); + return true; + } + + public abstract static class Start extends StructureStart { + public Start() { + + } + + public Start(World world, Random rand, int x, int z) { + this(world, rand, x, z, world.getBiome(new BlockPos(x * 16 + 8, 0, z * 16 + 8))); + } + + public Start(World world, Random rand, int x, int z, Biome biome) { + super(x, z); + addComponents(world, rand, x, z, biome); + updateBoundingBox(); + } + + protected abstract void addComponents(World world, Random ran, int x, int z, Biome biome); + } +} \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/structure/CloudDungeon.java b/src/main/java/com/minelittlepony/unicopia/structure/CloudDungeon.java new file mode 100644 index 00000000..59d7f7a8 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/structure/CloudDungeon.java @@ -0,0 +1,27 @@ +package com.minelittlepony.unicopia.structure; + +import java.util.Random; + +import com.minelittlepony.unicopia.Unicopia; + +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.template.PlacementSettings; +import net.minecraft.world.gen.structure.template.TemplateManager; + +public class CloudDungeon extends TemplateBasedFeature { + + private static final ResourceLocation STRUCTURE = new ResourceLocation(Unicopia.MODID, "cloud/dungeon_1"); + + public CloudDungeon(Random rand, int x, int z) { + super(rand, x, 120, z, 7, 5, 8); + } + + @Override + public boolean addComponentParts(World world, BlockPos startPos, TemplateManager templates, PlacementSettings placement) { + applyTemplate(world, startPos, templates, placement, STRUCTURE); + + return false; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/structure/TemplateBasedFeature.java b/src/main/java/com/minelittlepony/unicopia/structure/TemplateBasedFeature.java new file mode 100644 index 00000000..fd8f9ea1 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/structure/TemplateBasedFeature.java @@ -0,0 +1,91 @@ +package com.minelittlepony.unicopia.structure; + +import java.util.Map; +import java.util.Random; + +import javax.annotation.Nullable; + +import java.util.Map.Entry; + +import net.minecraft.init.Blocks; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityLockableLoot; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Rotation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.structure.StructureBoundingBox; +import net.minecraft.world.gen.structure.template.PlacementSettings; +import net.minecraft.world.gen.structure.template.Template; +import net.minecraft.world.gen.structure.template.TemplateManager; +import net.minecraft.world.storage.loot.LootTableList; + +public abstract class TemplateBasedFeature extends AbstractFeature { + + public TemplateBasedFeature() {} + + protected TemplateBasedFeature(Random rand, int x, int y, int z, int sizeX, int sizeY, int sizeZ) { + super(rand, x, y, z, sizeX, sizeY, sizeX); + } + + + @Override + public boolean addComponentParts(World world, Random rand, StructureBoundingBox bounds) { + + if (!offsetToAverageGroundLevel(world, bounds, -1)) { + return false; + } + + bounds = getBoundingBox(); + + BlockPos startPos = new BlockPos(bounds.minX, bounds.minY, bounds.minZ); + + Rotation[] orientations = Rotation.values(); + + TemplateManager templates = world.getSaveHandler().getStructureTemplateManager(); + + PlacementSettings placement = new PlacementSettings() + .setRotation(orientations[rand.nextInt(orientations.length)]) + .setReplacedBlock(Blocks.STRUCTURE_VOID) + .setBoundingBox(bounds); + + return addComponentParts(world, startPos, templates, placement); + } + + protected void applyTemplate(World world, BlockPos startPos, TemplateManager templates, PlacementSettings placement, ResourceLocation templateId) { + Template template = templates.get(world.getMinecraftServer(), templateId); + + template.addBlocksToWorldChunk(world, startPos, placement); + + Map map = template.getDataBlocks(startPos, placement); + + for (Entry entry : map.entrySet()) { + applyLootTables(world, entry.getKey(), entry.getValue()); + } + } + + protected void applyLootTables(World world, BlockPos pos, String blockId) { + ResourceLocation lootTable = getLootTable(blockId); + + if (lootTable != null) { + + world.setBlockState(pos, Blocks.AIR.getDefaultState(), 3); + TileEntity tileentity = world.getTileEntity(pos.down()); + + if (tileentity instanceof TileEntityLockableLoot) { + ((TileEntityLockableLoot)tileentity).setLootTable(lootTable, world.rand.nextLong()); + } + } + } + + @Nullable + protected ResourceLocation getLootTable(String blockId) { + if ("chest".equals(blockId)) { + return LootTableList.CHESTS_STRONGHOLD_LIBRARY; + } + + return null; + } + + public abstract boolean addComponentParts(World world, BlockPos startPos, TemplateManager templates, PlacementSettings placement); +} diff --git a/src/main/java/com/minelittlepony/unicopia/world/CloudGen.java b/src/main/java/com/minelittlepony/unicopia/world/CloudGen.java new file mode 100644 index 00000000..3b8826d1 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/world/CloudGen.java @@ -0,0 +1,47 @@ +package com.minelittlepony.unicopia.world; + +import java.util.Random; + +import com.minelittlepony.unicopia.structure.AbstractFeature; +import com.minelittlepony.unicopia.structure.CloudDungeon; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.structure.MapGenScatteredFeature; +import net.minecraft.world.gen.structure.StructureStart; + +public class CloudGen extends MapGenScatteredFeature { + + @Override + public String getStructureName() { + return "unicopia:clouds"; + } + + @Override + public boolean isSwampHut(BlockPos pos) { + return false; + } + + @Override + protected StructureStart getStructureStart(int chunkX, int chunkZ) { + return new Start(world, rand, chunkX, chunkZ); + } + + public static class Start extends AbstractFeature.Start { + public Start() { } + + public Start(World world, Random rand, int x, int z) { + super(world, rand, x, z); + } + + public Start(World world, Random rand, int x, int z, Biome biome) { + super(world, rand, x, z, biome); + } + + @Override + protected void addComponents(World world, Random rand, int x, int z, Biome biome) { + components.add(new CloudDungeon(rand, x * 16, z * 16)); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/world/UWorld.java b/src/main/java/com/minelittlepony/unicopia/world/UWorld.java index 05efc0f9..2b0d5823 100644 --- a/src/main/java/com/minelittlepony/unicopia/world/UWorld.java +++ b/src/main/java/com/minelittlepony/unicopia/world/UWorld.java @@ -6,10 +6,19 @@ import com.google.common.collect.Queues; import com.minelittlepony.jumpingcastle.Exceptions; import com.minelittlepony.unicopia.Unicopia; +import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; +import net.minecraft.world.gen.ChunkGeneratorOverworld; +import net.minecraft.world.gen.IChunkGenerator; public class UWorld { + private static final UWorld instance = new UWorld(); + + public static UWorld instance() { + return instance; + } + private static final Queue tickTasks = Queues.newArrayDeque(); private static final Object locker = new Object(); @@ -28,4 +37,16 @@ public class UWorld { tickTasks.add(task); } } + + private CloudGen cloudStructureGen = new CloudGen(); + + public void generateStructures(World world, int chunkX, int chunkZ, IChunkGenerator gen) { + if (gen instanceof ChunkGeneratorOverworld) { + if (world.getWorldInfo().isMapFeaturesEnabled()) { + ChunkPos pos = new ChunkPos(chunkX, chunkZ); + + cloudStructureGen.generateStructure(world, world.rand, pos); + } + } + } }