Merge pull request #136 from SenseiKiwi/nether

Implemented Nether Gateways
This commit is contained in:
StevenRS11 2014-01-28 09:05:33 -08:00
commit bc6b323b57
5 changed files with 369 additions and 10 deletions

View file

@ -1,9 +1,7 @@
package StevenDimDoors.mod_pocketDim; package StevenDimDoors.mod_pocketDim;
import paulscode.sound.SoundSystem;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.client.audio.SoundManager; import net.minecraft.client.audio.SoundManager;
import net.minecraft.client.audio.SoundPool;
import net.minecraft.client.audio.SoundPoolEntry; import net.minecraft.client.audio.SoundPoolEntry;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@ -14,15 +12,13 @@ import net.minecraft.util.ChunkCoordinates;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.client.event.sound.PlayBackgroundMusicEvent; import net.minecraftforge.client.event.sound.PlayBackgroundMusicEvent;
import net.minecraftforge.client.event.sound.SoundLoadEvent; import net.minecraftforge.client.event.sound.SoundLoadEvent;
import net.minecraftforge.event.Event;
import net.minecraftforge.event.EventPriority; import net.minecraftforge.event.EventPriority;
import net.minecraftforge.event.ForgeSubscribe; import net.minecraftforge.event.ForgeSubscribe;
import net.minecraftforge.event.entity.living.LivingDeathEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent;
import net.minecraftforge.event.entity.living.LivingFallEvent; import net.minecraftforge.event.entity.living.LivingFallEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.terraingen.InitMapGenEvent;
import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.event.world.WorldEvent;
import StevenDimDoors.mod_pocketDim.blocks.IDimDoor;
import StevenDimDoors.mod_pocketDim.core.DDTeleporter; import StevenDimDoors.mod_pocketDim.core.DDTeleporter;
import StevenDimDoors.mod_pocketDim.core.PocketManager; import StevenDimDoors.mod_pocketDim.core.PocketManager;
import StevenDimDoors.mod_pocketDim.items.BaseItemDoor; import StevenDimDoors.mod_pocketDim.items.BaseItemDoor;
@ -30,6 +26,7 @@ import StevenDimDoors.mod_pocketDim.ticking.RiftRegenerator;
import StevenDimDoors.mod_pocketDim.util.Point4D; import StevenDimDoors.mod_pocketDim.util.Point4D;
import StevenDimDoors.mod_pocketDim.world.LimboProvider; import StevenDimDoors.mod_pocketDim.world.LimboProvider;
import StevenDimDoors.mod_pocketDim.world.PocketProvider; import StevenDimDoors.mod_pocketDim.world.PocketProvider;
import StevenDimDoors.mod_pocketDim.world.fortresses.DDNetherFortressGenerator;
import cpw.mods.fml.client.FMLClientHandler; import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.relauncher.SideOnly;
@ -43,6 +40,15 @@ public class EventHookContainer
this.properties = properties; this.properties = properties;
} }
@ForgeSubscribe(priority = EventPriority.LOW)
public void onMapGen(InitMapGenEvent event)
{
if (event.type == InitMapGenEvent.EventType.NETHER_BRIDGE)
{
event.newGen = new DDNetherFortressGenerator();
}
}
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
@ForgeSubscribe @ForgeSubscribe
public void onSoundLoad(SoundLoadEvent event) public void onSoundLoad(SoundLoadEvent event)
@ -56,8 +62,8 @@ public class EventHookContainer
event.manager.addSound(mod_pocketDim.modid+":riftClose.ogg"); event.manager.addSound(mod_pocketDim.modid+":riftClose.ogg");
event.manager.addSound(mod_pocketDim.modid+":riftDoor.ogg"); event.manager.addSound(mod_pocketDim.modid+":riftDoor.ogg");
event.manager.addSound(mod_pocketDim.modid+":creepy.ogg"); event.manager.addSound(mod_pocketDim.modid+":creepy.ogg");
} }
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
@ForgeSubscribe @ForgeSubscribe
public void onSoundEffectResult(PlayBackgroundMusicEvent event) public void onSoundEffectResult(PlayBackgroundMusicEvent event)
@ -68,7 +74,6 @@ public class EventHookContainer
} }
} }
@ForgeSubscribe @ForgeSubscribe
public void onPlayerEvent(PlayerInteractEvent event) public void onPlayerEvent(PlayerInteractEvent event)
{ {
@ -113,6 +118,7 @@ public class EventHookContainer
} }
} }
} }
@ForgeSubscribe @ForgeSubscribe
public void onWorldLoad(WorldEvent.Load event) public void onWorldLoad(WorldEvent.Load event)
{ {
@ -129,7 +135,7 @@ public class EventHookContainer
RiftRegenerator.regenerateRiftsInAllWorlds(); RiftRegenerator.regenerateRiftsInAllWorlds();
} }
if(event.world!=null) if (event.world != null)
{ {
this.playMusicForDim(event.world); this.playMusicForDim(event.world);
} }
@ -140,7 +146,8 @@ public class EventHookContainer
{ {
event.setCanceled(event.entity.worldObj.provider.dimensionId == properties.LimboDimensionID); event.setCanceled(event.entity.worldObj.provider.dimensionId == properties.LimboDimensionID);
} }
@ForgeSubscribe(priority=EventPriority.HIGHEST)
@ForgeSubscribe(priority = EventPriority.HIGHEST)
public boolean LivingDeathEvent(LivingDeathEvent event) public boolean LivingDeathEvent(LivingDeathEvent event)
{ {
Entity entity = event.entity; Entity entity = event.entity;

View file

@ -174,7 +174,9 @@ public class mod_pocketDim
properties = DDProperties.initialize(new File(path)); properties = DDProperties.initialize(new File(path));
//Now do other stuff //Now do other stuff
MinecraftForge.EVENT_BUS.register(new EventHookContainer(properties)); EventHookContainer hooks = new EventHookContainer(properties);
MinecraftForge.EVENT_BUS.register(hooks);
MinecraftForge.TERRAIN_GEN_BUS.register(hooks);
gatewayGenerator = new GatewayGenerator(properties); gatewayGenerator = new GatewayGenerator(properties);
} }

View file

@ -0,0 +1,181 @@
package StevenDimDoors.mod_pocketDim.world.fortresses;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraft.world.gen.structure.StructureComponent;
import StevenDimDoors.mod_pocketDim.mod_pocketDim;
import StevenDimDoors.mod_pocketDim.core.DimLink;
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
import StevenDimDoors.mod_pocketDim.core.NewDimData;
import StevenDimDoors.mod_pocketDim.core.PocketManager;
import StevenDimDoors.mod_pocketDim.items.BaseItemDoor;
public class ComponentNetherGateway extends StructureComponent
{
// Note: In this case, it doesn't really matter which class we extend, since this class will
// never be passed to Minecraft. We just need an instance to have access to structure-building methods.
// If Forge supports adding custom fortress structures in the future, then we might have to change
// our class to extend ComponentNetherBridgeCrossing or something along those lines. ~SenseiKiwi
public ComponentNetherGateway(int componentType, Random random, StructureBoundingBox bounds, int coordBaseMode)
{
super(componentType);
this.boundingBox = bounds;
this.coordBaseMode = coordBaseMode;
}
/**
* Creates and returns a new component piece. Or null if it could not find enough room to place it.
*/
public static ComponentNetherGateway createValidComponent(List components, Random random, int minX, int minY, int minZ, int coordBaseMode, int componentType)
{
StructureBoundingBox bounds = StructureBoundingBox.getComponentToAddBoundingBox(minX, minY, minZ, -2, 0, 0, 7, 9, 7, coordBaseMode);
return isAboveGround(bounds) && StructureComponent.findIntersecting(components, bounds) == null ? new ComponentNetherGateway(componentType, random, bounds, coordBaseMode) : null;
}
public static ComponentNetherGateway createFromComponent(StructureComponent component, Random random)
{
// Create an instance of our gateway component using the same data as another component,
// likely a component that we intend to replace during generation
return new ComponentNetherGateway( component.getComponentType(), random,
component.getBoundingBox(), getCoordBaseMode(component));
}
private static int getCoordBaseMode(StructureComponent component)
{
// This is a hack to get the value of a component's coordBaseMode field.
// It's essentially the orientation of the component... with a weird name.
return component.func_143010_b().getInteger("O");
}
/**
* Checks if the bounding box's minY is > 10
*/
protected static boolean isAboveGround(StructureBoundingBox par0StructureBoundingBox)
{
return par0StructureBoundingBox != null && par0StructureBoundingBox.minY > 10;
}
/**
* second Part of Structure generating, this for example places Spiderwebs, Mob Spawners, it closes Mineshafts at
* the end, it adds Fences...
*/
public boolean addComponentParts(World world, Random random, StructureBoundingBox bounds)
{
int NETHER_SLAB_METADATA = 6;
// Set all the blocks in the area of the room to air
this.fillWithBlocks(world, bounds, 0, 2, 0, 6, 6, 6, 0, 0, false);
// Set up the platform under the gateway
this.fillWithBlocks(world, bounds, 0, 0, 0, 6, 1, 6, Block.netherBrick.blockID, Block.netherBrick.blockID, false);
// Build the fence at the back of the room
this.fillWithBlocks(world, bounds, 1, 2, 6, 5, 2, 6, Block.netherBrick.blockID, Block.netherBrick.blockID, false);
this.fillWithBlocks(world, bounds, 1, 3, 6, 5, 3, 6, Block.netherFence.blockID, Block.netherFence.blockID, false);
// Build the fences at the sides of the room
this.fillWithBlocks(world, bounds, 0, 2, 0, 0, 2, 6, Block.netherBrick.blockID, Block.netherBrick.blockID, false);
this.fillWithBlocks(world, bounds, 0, 3, 0, 0, 3, 6, Block.netherFence.blockID, Block.netherFence.blockID, false);
this.fillWithBlocks(world, bounds, 6, 2, 0, 6, 2, 6, Block.netherBrick.blockID, Block.netherBrick.blockID, false);
this.fillWithBlocks(world, bounds, 6, 3, 0, 6, 3, 6, Block.netherFence.blockID, Block.netherFence.blockID, false);
// Build the fence portions closest to the entrance
this.placeBlockAtCurrentPosition(world, Block.netherBrick.blockID, 0, 1, 2, 0, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherFence.blockID, 0, 1, 3, 0, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherBrick.blockID, 0, 5, 2, 0, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherFence.blockID, 0, 5, 3, 0, bounds);
// Build the first layer of the gateway
this.fillWithBlocks(world, bounds, 1, 2, 2, 5, 2, 5, Block.netherBrick.blockID, Block.netherBrick.blockID, false);
this.fillWithMetadataBlocks(world, bounds, 1, 2, 1, 5, 2, 1, Block.stoneSingleSlab.blockID, NETHER_SLAB_METADATA, Block.stoneSingleSlab.blockID, NETHER_SLAB_METADATA, false);
this.placeBlockAtCurrentPosition(world, Block.stoneSingleSlab.blockID, NETHER_SLAB_METADATA, 1, 2, 2, bounds);
this.placeBlockAtCurrentPosition(world, Block.stoneSingleSlab.blockID, NETHER_SLAB_METADATA, 5, 2, 2, bounds);
// Build the second layer of the gateway
int orientation = this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 2);
this.fillWithBlocks(world, bounds, 2, 3, 3, 2, 3, 4, Block.netherBrick.blockID, Block.netherBrick.blockID, false);
this.fillWithBlocks(world, bounds, 4, 3, 3, 4, 3, 4, Block.netherBrick.blockID, Block.netherBrick.blockID, false);
this.placeBlockAtCurrentPosition(world, Block.netherBrick.blockID, 0, 3, 3, 4, bounds);
this.placeBlockAtCurrentPosition(world, Block.stairsNetherBrick.blockID, orientation, 3, 3, 5, bounds);
// Build the third layer of the gateway
// We add 4 to get the rotated metadata for upside-down stairs
// because Minecraft only supports metadata rotations for normal stairs -_-
this.fillWithMetadataBlocks(world, bounds, 2, 4, 4, 4, 4, 4, Block.stairsNetherBrick.blockID, orientation, Block.stairsNetherBrick.blockID, orientation, false);
this.placeBlockAtCurrentPosition(world, Block.stairsNetherBrick.blockID, this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 0) + 4, 2, 4, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.stairsNetherBrick.blockID, this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 1) + 4, 4, 4, 3, bounds);
// Build the fourth layer of the gateway
this.placeBlockAtCurrentPosition(world, Block.netherBrick.blockID, 0, 3, 5, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherrack.blockID, 0, 2, 5, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.stairsNetherBrick.blockID, this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 0) + 4, 1, 5, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.stairsNetherBrick.blockID, this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 3) + 4, 2, 5, 2, bounds);
this.placeBlockAtCurrentPosition(world, Block.stairsNetherBrick.blockID, this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 2) + 4, 2, 5, 4, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherrack.blockID, 0, 4, 5, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.stairsNetherBrick.blockID, this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 1) + 4, 5, 5, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.stairsNetherBrick.blockID, this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 3) + 4, 4, 5, 2, bounds);
this.placeBlockAtCurrentPosition(world, Block.stairsNetherBrick.blockID, this.getMetadataWithOffset(Block.stairsNetherBrick.blockID, 2) + 4, 4, 5, 4, bounds);
// Build the top layer of the gateway
this.placeBlockAtCurrentPosition(world, Block.netherFence.blockID, 0, 3, 6, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.fire.blockID, 0, 2, 6, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherFence.blockID, 0, 1, 6, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherFence.blockID, 0, 2, 6, 2, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherFence.blockID, 0, 2, 6, 4, bounds);
this.placeBlockAtCurrentPosition(world, Block.fire.blockID, 0, 4, 6, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherFence.blockID, 0, 5, 6, 3, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherFence.blockID, 0, 4, 6, 2, bounds);
this.placeBlockAtCurrentPosition(world, Block.netherFence.blockID, 0, 4, 6, 4, bounds);
// Place the transient door
int y = this.getYWithOffset(3);
int x = this.getXWithOffset(3, 3);
int z = this.getZWithOffset(3, 3);
DimLink link;
NewDimData dimension;
// This function might run multiple times for a single component
// due to the way Minecraft handles structure generation!
if (bounds.isVecInside(x, y, z) && bounds.isVecInside(x, y + 1, z))
{
orientation = this.getMetadataWithOffset(Block.doorWood.blockID, 1);
dimension = PocketManager.getDimensionData(world);
link = dimension.getLink(x, y + 1, z);
if (link == null)
{
link = dimension.createLink(x, y + 1, z, LinkTypes.DUNGEON, orientation);
}
BaseItemDoor.placeDoorBlock(world, x, y, z, orientation, mod_pocketDim.transientDoor);
}
for (x = 0; x <= 6; ++x)
{
for (z = 0; z <= 6; ++z)
{
this.fillCurrentPositionBlocksDownwards(world, Block.netherBrick.blockID, 0, x, -1, z, bounds);
}
}
return true;
}
@Override
protected void func_143012_a(NBTTagCompound tag) { }
@Override
protected void func_143011_b(NBTTagCompound tag) { }
}

View file

@ -0,0 +1,24 @@
package StevenDimDoors.mod_pocketDim.world.fortresses;
import net.minecraft.world.gen.structure.MapGenNetherBridge;
import net.minecraft.world.gen.structure.MapGenStructureIO;
import net.minecraft.world.gen.structure.StructureStart;
public class DDNetherFortressGenerator extends MapGenNetherBridge
{
public DDNetherFortressGenerator()
{
super();
// Register our custom StructureStart class with MapGenStructureIO
// If we don't do this, Minecraft will crash when a fortress tries to generate.
// Moreover, use Fortress as our structure identifier so that if DD is removed,
// fortresses will generate properly using Vanilla code.
MapGenStructureIO.func_143034_b(DDStructureNetherBridgeStart.class, "Fortress");
}
protected StructureStart getStructureStart(int chunkX, int chunkZ)
{
return new DDStructureNetherBridgeStart(this.worldObj, this.rand, chunkX, chunkZ);
}
}

View file

@ -0,0 +1,145 @@
package StevenDimDoors.mod_pocketDim.world.fortresses;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.ComponentNetherBridgeCrossing;
import net.minecraft.world.gen.structure.ComponentNetherBridgeThrone;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraft.world.gen.structure.StructureComponent;
import net.minecraft.world.gen.structure.StructureNetherBridgeStart;
public class DDStructureNetherBridgeStart extends StructureNetherBridgeStart
{
private static int GATEWAY_GENERATION_CHANCE = 1;
private static int MAX_GATEWAY_GENERATION_CHANCE = 3;
private boolean hasGateway;
private int minX;
private int minY;
private int minZ;
public DDStructureNetherBridgeStart() { }
public DDStructureNetherBridgeStart(World world, Random random, int chunkX, int chunkZ)
{
// StructureNetherBridgeStart handles designing the fortress for us
super(world, random, chunkX, chunkZ);
Iterator componentIterator;
StructureComponent component;
StructureBoundingBox bounds;
ArrayList<ComponentNetherBridgeThrone> spawnerRooms;
hasGateway = false;
// Randomly decide whether to build a gateway in this fortress
if (random.nextInt(MAX_GATEWAY_GENERATION_CHANCE) < GATEWAY_GENERATION_CHANCE)
{
// Search for all the blaze spawners in a fortress
spawnerRooms = new ArrayList<ComponentNetherBridgeThrone>();
componentIterator = this.components.iterator();
while (componentIterator.hasNext())
{
component = (StructureComponent) componentIterator.next();
if (component instanceof ComponentNetherBridgeThrone)
{
spawnerRooms.add((ComponentNetherBridgeThrone) component);
}
}
// If any spawner rooms were found, choose one to randomly replace
if (!spawnerRooms.isEmpty())
{
hasGateway = true;
component = spawnerRooms.get(random.nextInt(spawnerRooms.size()));
// Store enough data to identify the room when it's going to be built later
bounds = component.getBoundingBox();
minX = bounds.minX;
minY = bounds.minY;
minZ = bounds.minZ;
}
}
}
@Override
public NBTTagCompound func_143021_a(int chunkX, int chunkZ)
{
// We override the function for writing NBT data to add our own gateway data
NBTTagCompound fortressTag = super.func_143021_a(chunkX, chunkZ);
// Add a compound tag with our data
NBTTagCompound dimensionalTag = new NBTTagCompound();
dimensionalTag.setBoolean("HasGateway", this.hasGateway);
if (hasGateway)
{
dimensionalTag.setInteger("GatewayMinX", this.minX);
dimensionalTag.setInteger("GatewayMinY", this.minY);
dimensionalTag.setInteger("GatewayMinZ", this.minZ);
}
fortressTag.setCompoundTag("DimensionalDoors", dimensionalTag);
return fortressTag;
}
@Override
public void func_143020_a(World world, NBTTagCompound fortressTag)
{
// We override the function for reading NBT data to load gateway data
super.func_143020_a(world, fortressTag);
NBTTagCompound dimensionalTag = fortressTag.getCompoundTag("DimensionalDoors");
if (dimensionalTag != null)
{
this.hasGateway = dimensionalTag.getBoolean("HasGateway");
if (hasGateway)
{
minX = dimensionalTag.getInteger("GatewayMinX");
minY = dimensionalTag.getInteger("GatewayMinY");
minZ = dimensionalTag.getInteger("GatewayMinZ");
}
}
}
/**
* Keeps iterating Structure Pieces and spawning them until the checks tell it to stop
*/
public void generateStructure(World world, Random random, StructureBoundingBox generationBounds)
{
if (hasGateway)
{
// Use a modified version of Vanilla's fortress generation code
// Try to detect the room that we intend to replace with our gateway
Iterator iterator = this.components.iterator();
while (iterator.hasNext())
{
StructureComponent component = (StructureComponent)iterator.next();
StructureBoundingBox bounds = component.getBoundingBox();
if (bounds.intersectsWith(generationBounds))
{
// Check if this is our replacement target
// Checking the location is enough because structures aren't allowed to have
// intersecting bounding boxes - nothing else can have these min coordinates.
if (bounds.minX == this.minX && bounds.minY == this.minY && bounds.minZ == this.minZ)
{
component = ComponentNetherGateway.createFromComponent(component, random);
}
// Now for the last bit of Vanilla's generation code
if (!component.addComponentParts(world, random, generationBounds))
{
iterator.remove();
}
}
}
}
else
{
// Just run the usual structure generation
super.generateStructure(world, random, generationBounds);
}
}
}