package StevenDimDoors.mod_pocketDim; import cpw.mods.fml.common.eventhandler.Event; import cpw.mods.fml.common.eventhandler.EventPriority; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.ISound; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.audio.SoundManager; import net.minecraft.client.audio.SoundPoolEntry; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.DamageSource; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraft.world.WorldProvider; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.client.event.sound.PlayBackgroundMusicEvent; import net.minecraftforge.client.event.sound.PlaySoundEvent17; import net.minecraftforge.client.event.sound.SoundLoadEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; import net.minecraftforge.event.entity.living.LivingFallEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; import net.minecraftforge.event.terraingen.InitMapGenEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; import StevenDimDoors.mod_pocketDim.config.DDProperties; import StevenDimDoors.mod_pocketDim.config.DDWorldProperties; import StevenDimDoors.mod_pocketDim.core.DDTeleporter; import StevenDimDoors.mod_pocketDim.core.DimLink; import StevenDimDoors.mod_pocketDim.core.DimensionType; import StevenDimDoors.mod_pocketDim.core.NewDimData; import StevenDimDoors.mod_pocketDim.core.PocketManager; import StevenDimDoors.mod_pocketDim.items.BaseItemDoor; import StevenDimDoors.mod_pocketDim.items.ItemWarpDoor; import StevenDimDoors.mod_pocketDim.ticking.RiftRegenerator; import StevenDimDoors.mod_pocketDim.util.Point4D; import StevenDimDoors.mod_pocketDim.world.LimboProvider; import StevenDimDoors.mod_pocketDim.world.PocketProvider; import cpw.mods.fml.client.FMLClientHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public class EventHookContainer { private static final int MAX_FOOD_LEVEL = 20; private final DDProperties properties; private DDWorldProperties worldProperties; private RiftRegenerator regenerator; public EventHookContainer(DDProperties properties) { this.properties = properties; } public void setSessionFields(DDWorldProperties worldProperties, RiftRegenerator regenerator) { // SenseiKiwi: // Why have a setter rather than accessing mod_pocketDim directly? // I want to make this dependency explicit in our code. this.worldProperties = worldProperties; this.regenerator = regenerator; } @SubscribeEvent(priority = EventPriority.LOW) public void onInitMapGen(InitMapGenEvent event) { // Replace the Nether fortress generator with our own only if any // gateways would ever generate. This allows admins to disable our // fortress overriding without disabling all gateways. /* * if (properties.FortressGatewayGenerationChance > 0 && * properties.WorldRiftGenerationEnabled && event.type == * InitMapGenEvent.EventType.NETHER_BRIDGE) { event.newGen = new * DDNetherFortressGenerator(); } */ } @SubscribeEvent public void onPlayerEvent(PlayerInteractEvent event) { // Handle all door placement here if (event.action == Action.LEFT_CLICK_BLOCK) { return; } World world = event.entity.worldObj; ItemStack stack = event.entityPlayer.inventory.getCurrentItem(); if (stack != null) { if(stack.getItem() instanceof ItemWarpDoor) { NewDimData data = PocketManager.getDimensionData(world); if(data.type() == DimensionType.PERSONAL) { mod_pocketDim.sendChat(event.entityPlayer,("Something prevents the Warp Door from tunneling out here")); event.setCanceled(true); return; } } if (BaseItemDoor.tryToPlaceDoor(stack, event.entityPlayer, world, event.x, event.y, event.z, event.face)) { // Cancel the event so that we don't get two doors from vanilla doors event.setCanceled(true); } } } @SubscribeEvent public void onWorldLoad(WorldEvent.Load event) { // We need to initialize PocketManager here because onServerAboutToStart // fires before we can use DimensionManager and onServerStarting fires // after the game tries to generate terrain. If a gateway tries to // generate before PocketManager has initialized, we get a crash. if (!event.world.isRemote && !PocketManager.isLoaded()) { PocketManager.load(); } } @SubscribeEvent public void onPlayerFall(LivingFallEvent event) { event.setCanceled(event.entity.worldObj.provider.dimensionId == properties.LimboDimensionID); } @SubscribeEvent(priority = EventPriority.HIGHEST) public boolean onDeathWithHighPriority(LivingDeathEvent event) { // Teleport the entity to Limbo if it's a player in a pocket dimension // and if Limbo preserves player inventories. We'll check again in a // low-priority event handler to give other mods a chance to save the // player if Limbo does _not_ preserve inventories. Entity entity = event.entity; if (properties.LimboEnabled && properties.LimboReturnsInventoryEnabled && entity instanceof EntityPlayer && isValidSourceForLimbo(entity.worldObj.provider)) { if(entity.worldObj.provider instanceof PocketProvider) { EntityPlayer player = (EntityPlayer) entity; mod_pocketDim.deathTracker.addUsername(player.getGameProfile().getName()); revivePlayerInLimbo(player); event.setCanceled(true); return false; } else if(entity.worldObj.provider instanceof LimboProvider && event.source == DamageSource.outOfWorld) { EntityPlayer player = (EntityPlayer) entity; revivePlayerInLimbo(player); mod_pocketDim.sendChat(player, "Search for the dark red pools which accumulate in the lower reaches of Limbo"); event.setCanceled(true); return false; } } return true; } @SubscribeEvent(priority = EventPriority.LOWEST) public boolean onDeathWithLowPriority(LivingDeathEvent event) { // This low-priority handler gives mods a chance to save a player from // death before we apply teleporting them to Limbo _without_ preserving // their inventory. We also check if the player died in a pocket // dimension and record it, regardless of whether the player will be // sent to Limbo. Entity entity = event.entity; if (entity instanceof EntityPlayer && isValidSourceForLimbo(entity.worldObj.provider)) { EntityPlayer player = (EntityPlayer) entity; mod_pocketDim.deathTracker.addUsername(player.getGameProfile().getName()); if (properties.LimboEnabled && !properties.LimboReturnsInventoryEnabled) { player.inventory.clearInventory(null, -1); revivePlayerInLimbo(player); event.setCanceled(true); } return false; } return true; } private boolean isValidSourceForLimbo(WorldProvider provider) { // Returns whether a given world is a valid place for sending a player // to Limbo. We can send someone to Limbo from a certain dimension if // Universal Limbo is enabled and the source dimension is not Limbo, or // if the source dimension is a pocket dimension. return (worldProperties.UniversalLimboEnabled && provider.dimensionId != properties.LimboDimensionID) || (provider instanceof PocketProvider); } private void revivePlayerInLimbo(EntityPlayer player) { player.extinguish(); player.clearActivePotions(); player.setHealth(player.getMaxHealth()); player.getFoodStats().addStats(MAX_FOOD_LEVEL, 0); Point4D destination = LimboProvider.getLimboSkySpawn(player, properties); DDTeleporter.teleportEntity(player, destination, false); } @SubscribeEvent public void onWorldSave(WorldEvent.Save event) { if (event.world.provider.dimensionId == 0) { PocketManager.save(true); if (mod_pocketDim.deathTracker != null && mod_pocketDim.deathTracker.isModified()) { mod_pocketDim.deathTracker.writeToFile(); } } } @SubscribeEvent public void onChunkLoad(ChunkEvent.Load event) { // Schedule rift regeneration for any links located in this chunk. // This event runs on both the client and server. Allow server only. // Also, check that PocketManager is loaded, because onChunkLoad() can // fire while chunks are being initialized in a new world, before // onWorldLoad() fires. Chunk chunk = event.getChunk(); if (!chunk.worldObj.isRemote && PocketManager.isLoaded()) { NewDimData dimension = PocketManager.createDimensionData(chunk.worldObj); for (DimLink link : dimension.getChunkLinks(chunk.xPosition, chunk.zPosition)) { regenerator.scheduleSlowRegeneration(link); } } } }