package zmaster587.advancedRocketry.event;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.lwjgl.opengl.GL11;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayer.EnumStatus;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraft.world.WorldProvider;
import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.event.entity.living.LivingFallEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
import net.minecraftforge.event.entity.player.PlayerOpenContainerEvent;
import net.minecraftforge.event.terraingen.OreGenEvent;
import net.minecraftforge.event.terraingen.PopulateChunkEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import zmaster587.advancedRocketry.achievements.ARAchivements;
import zmaster587.advancedRocketry.api.AdvancedRocketryBiomes;
import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks;
import zmaster587.advancedRocketry.api.AdvancedRocketryItems;
import zmaster587.advancedRocketry.api.Configuration;
import zmaster587.advancedRocketry.api.IPlanetaryProvider;
import zmaster587.advancedRocketry.api.stations.ISpaceObject;
import zmaster587.advancedRocketry.atmosphere.AtmosphereHandler;
import zmaster587.advancedRocketry.atmosphere.AtmosphereType;
import zmaster587.advancedRocketry.dimension.DimensionManager;
import zmaster587.advancedRocketry.dimension.DimensionProperties;
import zmaster587.advancedRocketry.network.PacketDimInfo;
import zmaster587.advancedRocketry.network.PacketSpaceStationInfo;
import zmaster587.advancedRocketry.network.PacketStellarInfo;
import zmaster587.advancedRocketry.stations.SpaceObjectManager;
import zmaster587.advancedRocketry.util.BiomeHandler;
import zmaster587.advancedRocketry.util.TransitionEntity;
import zmaster587.advancedRocketry.world.provider.WorldProviderPlanet;
import zmaster587.advancedRocketry.world.util.TeleporterNoPortal;
import zmaster587.libVulpes.LibVulpes;
import zmaster587.libVulpes.api.IModularArmor;
import zmaster587.libVulpes.api.LibVulpesItems;
import zmaster587.libVulpes.network.PacketHandler;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.eventhandler.Event.Result;
import cpw.mods.fml.common.gameevent.PlayerEvent;
import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerRespawnEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import cpw.mods.fml.common.network.FMLNetworkEvent;
import cpw.mods.fml.common.network.FMLNetworkEvent.ClientDisconnectionFromServerEvent;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class PlanetEventHandler {
public static long time = 0;
private static long endTime, duration;
private static Map<Long,TransitionEntity> transitionMap = new HashMap<Long,TransitionEntity>();
public static void addDelayedTransition(long tick, TransitionEntity entity) {
transitionMap.put(tick, entity);
}
@SubscribeEvent
public void sleepEvent(PlayerSleepInBedEvent event) {
if(event.entity.worldObj.provider instanceof WorldProviderPlanet &&
AtmosphereHandler.hasAtmosphereHandler(event.entity.worldObj.provider.dimensionId) && !AtmosphereHandler.getOxygenHandler(event.entity.worldObj.provider.dimensionId).getAtmosphereType(event.x, event.y, event.z).isBreathable()) {
event.result = EnumStatus.OTHER_PROBLEM;
}
}
@SubscribeEvent
public void onCrafting(PlayerEvent.ItemCraftedEvent event) {
if(event.crafting != null) {
Item item = event.crafting.getItem();
if(item == LibVulpesItems.itemHoloProjector)
event.player.triggerAchievement(ARAchivements.holographic);
else if(item == Item.getItemFromBlock(AdvancedRocketryBlocks.blockRollingMachine))
event.player.triggerAchievement(ARAchivements.rollin);
else if(item == Item.getItemFromBlock(AdvancedRocketryBlocks.blockCrystallizer))
event.player.triggerAchievement(ARAchivements.crystalline);
else if(item == Item.getItemFromBlock(AdvancedRocketryBlocks.blockLathe))
event.player.triggerAchievement(ARAchivements.spinDoctor);
else if(item ==Item.getItemFromBlock(AdvancedRocketryBlocks.blockElectrolyser))
event.player.triggerAchievement(ARAchivements.electrifying);
else if(item == Item.getItemFromBlock(AdvancedRocketryBlocks.blockArcFurnace))
event.player.triggerAchievement(ARAchivements.feelTheHeat);
else if(item == Item.getItemFromBlock(AdvancedRocketryBlocks.blockWarpCore))
event.player.triggerAchievement(ARAchivements.warp);
else if(item == Item.getItemFromBlock(AdvancedRocketryBlocks.blockPlatePress))
event.player.triggerAchievement(ARAchivements.blockPresser);
}
}
@SubscribeEvent
public void onWorldGen(OreGenEvent.GenerateMinable event) {
if(event.world.provider instanceof WorldProviderPlanet &&
DimensionManager.getInstance().getDimensionProperties(event.world.provider.dimensionId).getOreGenProperties(event.world) != null) {
switch(event.type) {
case COAL:
case DIAMOND:
case GOLD:
case IRON:
case LAPIS:
case QUARTZ:
case REDSTONE:
case CUSTOM:
event.setResult(Result.DENY);
break;
default:
event.setResult(Result.DEFAULT);
}
}
}
@SubscribeEvent
public void onPickup(PlayerEvent.ItemPickupEvent event) {
if(event.pickedUp != null) {
Item item = event.pickedUp.getEntityItem().getItem();
zmaster587.libVulpes.api.material.Material mat = LibVulpes.materialRegistry.getMaterialFromItemStack( event.pickedUp.getEntityItem());
if(mat != null && mat.getUnlocalizedName().contains("Dilithium"))
event.player.triggerAchievement(ARAchivements.dilithiumCrystals);
}
}
//Handle gravity
@SubscribeEvent
public void playerTick(LivingUpdateEvent event) {
if(event.entity.worldObj.isRemote && event.entity.posY > 260 && event.entity.posY < 270 && event.entity.motionY < -.1) {
RocketEventHandler.destroyOrbitalTextures(event.entity.worldObj);
}
if(event.entity.isInWater()) {
if(AtmosphereType.LOWOXYGEN.isImmune(event.entityLiving))
event.entity.setAir(300);
}
if(!event.entity.worldObj.isRemote && event.entity.worldObj.getTotalWorldTime() % 20 ==0 && event.entity instanceof EntityPlayer) {
if(DimensionManager.getInstance().getDimensionProperties(event.entity.worldObj.provider.dimensionId).getName().equals("Luna") &&
event.entity.getDistanceSq(67, 80, 2347) < 512 ) {
((EntityPlayer)event.entity).triggerAchievement(ARAchivements.weReallyWentToTheMoon);
}
}
}
@SubscribeEvent
public void blockPlaceEvent(PlayerInteractEvent event) {
ForgeDirection direction = ForgeDirection.getOrientation(event.face);
if(!event.world.isRemote && Action.RIGHT_CLICK_BLOCK == event.action && event.entityPlayer != null && AtmosphereHandler.getOxygenHandler(event.world.provider.dimensionId) != null &&
!AtmosphereHandler.getOxygenHandler(event.world.provider.dimensionId).getAtmosphereType(event.x + direction.offsetX, event.y + direction.offsetY, event.z + direction.offsetZ).allowsCombustion()) {
if(event.entityPlayer.getCurrentEquippedItem() != null) {
if(event.entityPlayer.getCurrentEquippedItem().getItem() == Item.getItemFromBlock(Blocks.torch) &&
event.world.getBlock(event.x, event.y, event.z).isSideSolid(event.world, event.x, event.y, event.z, direction)) {
event.setCanceled(true);
event.world.setBlock(event.x + direction.offsetX, event.y + direction.offsetY, event.z + direction.offsetZ, AdvancedRocketryBlocks.blockUnlitTorch);
}
else if(zmaster587.advancedRocketry.api.Configuration.torchBlocks.contains(Block.getBlockFromItem(event.entityPlayer.getCurrentEquippedItem().getItem())) )
event.setCanceled(true);
else if(event.entityPlayer.getCurrentEquippedItem().getItem() == Items.flint_and_steel || event.entityPlayer.getCurrentEquippedItem().getItem() == Items.fire_charge || event.entityPlayer.getCurrentEquippedItem().getItem() == Items.blaze_powder || event.entityPlayer.getCurrentEquippedItem().getItem() == Items.blaze_rod || event.entityPlayer.getCurrentEquippedItem().getItem() == Items.lava_bucket)
event.setCanceled(true);
}
}
if(!event.world.isRemote && event.entityPlayer != null && event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK && event.entityPlayer.getCurrentEquippedItem() != null && event.entityPlayer.getCurrentEquippedItem().getItem() == Items.bed && event.world.provider instanceof WorldProviderPlanet) {
AdvancedRocketryItems.itemAstroBed.onItemUse( event.entityPlayer.getCurrentEquippedItem(), event.entityPlayer, event.entityPlayer.worldObj, event.x, event.y, event.z, event.face, 0, 0, 0);
event.setCanceled(true);
}
if(!event.world.isRemote && event.entityPlayer != null && event.entityPlayer.getCurrentEquippedItem() != null && event.entityPlayer.getCurrentEquippedItem().getItem() == Item.getItemFromBlock(AdvancedRocketryBlocks.blockGenericSeat) && event.world.getBlock(event.x, event.y, event.z) == Blocks.tnt) {
event.entityPlayer.triggerAchievement(ARAchivements.beerOnTheSun);
}
}
@EventHandler
public void disconnected(ClientDisconnectionFromServerEvent event) {
zmaster587.advancedRocketry.dimension.DimensionManager.getInstance().unregisterAllDimensions();
}
/*@SubscribeEvent
public void entityRegister(EntityConstructing event) {
if(event.entity instanceof EntityPlayer) {
event.entity.registerExtendedProperties(PlayerDataHandler.IDENTIFIER, new PlayerDataHandler());
}
}*/
//TODO move
//Has weak refs so if the player gets killed/logsout etc the entry doesnt stay trapped in RAM
private static HashSet<WeakReference<EntityPlayer>> inventoryCheckPlayerBypassMap = new HashSet<WeakReference<EntityPlayer>>();
public static void addPlayerToInventoryBypass(EntityPlayer player) {
inventoryCheckPlayerBypassMap.add(new WeakReference<>(player));
}
public static void removePlayerFromInventoryBypass(EntityPlayer player) {
Iterator<WeakReference<EntityPlayer>> iter = inventoryCheckPlayerBypassMap.iterator();
while(iter.hasNext()) {
WeakReference<EntityPlayer> player2 = iter.next();
if(player2.get() == player || player2.get() == null)
iter.remove();
}
}
public static boolean canPlayerBypassInvChecks(EntityPlayer player) {
Iterator<WeakReference<EntityPlayer>> iter = inventoryCheckPlayerBypassMap.iterator();
while(iter.hasNext()) {
WeakReference<EntityPlayer> player2 = iter.next();
if(player2.get() == player)
return true;
}
return false;
}
@SubscribeEvent
public void containerOpen(PlayerOpenContainerEvent event) {
//event.entityPlayer.openContainer
if(canPlayerBypassInvChecks(event.entityPlayer))
if(event.entityPlayer.openContainer.windowId == 0)
removePlayerFromInventoryBypass(event.entityPlayer);
else
event.setResult(Result.ALLOW);
}
//Tick dimensions, needed for satellites, and guis
@SubscribeEvent
public void tick(TickEvent.ServerTickEvent event) {
//Tick satellites
if(event.phase == event.phase.END) {
DimensionManager.getInstance().tickDimensions();
time++;
if(!transitionMap.isEmpty()) {
Iterator<Entry<Long, TransitionEntity>> itr = transitionMap.entrySet().iterator();
while(itr.hasNext()) {
Entry<Long, TransitionEntity> entry = itr.next();
TransitionEntity ent = entry.getValue();
if(ent.entity.worldObj.getTotalWorldTime() >= entry.getKey()) {
ent.entity.setLocationAndAngles(ent.location.x, ent.location.y, ent.location.z, ent.entity.rotationYaw, ent.entity.rotationPitch);
MinecraftServer.getServer().getConfigurationManager().transferPlayerToDimension((EntityPlayerMP)ent.entity, ent.dimId, new TeleporterNoPortal(MinecraftServer.getServer().worldServerForDimension(ent.dimId)));
ent.entity.mountEntity(ent.entity2);
itr.remove();
}
}
}
}
}
@SubscribeEvent
public void tickClient(TickEvent.ClientTickEvent event) {
if(event.phase == event.phase.END)
DimensionManager.getInstance().tickDimensionsClient();
}
//Make sure the player receives data about the dimensions
@SubscribeEvent
public void playerLoggedInEvent(FMLNetworkEvent.ServerConnectionFromClientEvent event) {
//Make sure stars are sent first
for(int i : DimensionManager.getInstance().getStarIds()) {
PacketHandler.sendToDispatcher(new PacketStellarInfo(i, DimensionManager.getInstance().getStar(i)), event.manager);
}
for(int i : DimensionManager.getInstance().getRegisteredDimensions()) {
PacketHandler.sendToDispatcher(new PacketDimInfo(i, DimensionManager.getInstance().getDimensionProperties(i)), event.manager);
}
for(ISpaceObject obj : SpaceObjectManager.getSpaceManager().getSpaceObjects()) {
PacketHandler.sendToDispatcher(new PacketSpaceStationInfo(obj.getId(), obj), event.manager);
}
PacketHandler.sendToDispatcher(new PacketDimInfo(0, DimensionManager.getInstance().getDimensionProperties(0)), event.manager);
}
// Used to save extra biome data
/*@SubscribeEvent
public void worldLoadEvent(WorldEvent.Load event) {
if(event.world.provider instanceof ProviderPlanet && DimensionManager.getInstance().getDimensionProperties(event.world.provider.dimensionId).biomeProperties == null) {
DimensionManager.getInstance().getDimensionProperties(event.world.provider.dimensionId).biomeProperties = new ExtendedBiomeProperties(event.world);
}
}
// Used to load extra biome data
@SubscribeEvent
public void saveExtraData(ChunkDataEvent.Save event) {
if(event.world.provider instanceof ProviderPlanet) {
NBTTagCompound nbt = event.getData();
int xPos = event.getChunk().xPosition;//nbt.getInteger("xPos");
int zPos = event.getChunk().zPosition;//nbt.getInteger("zPos");
ChunkProperties properties = DimensionManager.getInstance().getDimensionProperties(event.world.provider.dimensionId).biomeProperties.getChunkPropertiesFromChunkCoords(xPos, zPos);
nbt.setIntArray("ExtendedBiomeArray", properties.getBlockBiomeArray());
}
}
@SubscribeEvent
public void loadExtraData(ChunkDataEvent.Load event) {
if(event.world.provider instanceof ProviderPlanet) {
NBTTagCompound nbt = event.getData();
int xPos = event.getChunk().xPosition;//nbt.getInteger("xPos");
int zPos = event.getChunk().zPosition;//nbt.getInteger("zPos");
ChunkProperties properties = DimensionManager.getInstance().getDimensionProperties(event.world.provider.dimensionId).biomeProperties.getChunkPropertiesFromChunkCoords(xPos, zPos);
properties.setBlockBiomeArray(event.getData().getIntArray("ExtendedBiomeArray"));
}
}
*/
@SubscribeEvent
public void worldLoadEvent(WorldEvent.Load event) {
if(!event.world.isRemote)
AtmosphereHandler.registerWorld(event.world.provider.dimensionId);
}
@SubscribeEvent
public void worldUnloadEvent(WorldEvent.Unload event) {
if(!event.world.isRemote)
AtmosphereHandler.unregisterWorld(event.world.provider.dimensionId);
}
/**
* Starts a burst, used for move to warp effect
* @param endTime
* @param duration
*/
@SideOnly(Side.CLIENT)
public static void runBurst(long endTime, long duration) {
PlanetEventHandler.endTime = endTime;
PlanetEventHandler.duration = duration;
}
//Handle fog density and color
@SubscribeEvent
@SideOnly(Side.CLIENT)
public void fogColor(net.minecraftforge.client.event.EntityViewRenderEvent.FogColors event) {
Block block = ActiveRenderInfo.getBlockAtEntityViewpoint(event.entity.worldObj, event.entity, (float)event.renderPartialTicks);
if(block.getMaterial() == Material.water)
return;
DimensionProperties properties = DimensionManager.getInstance().getDimensionProperties(event.entity.dimension);
if(properties != null) {
float fog = properties.getAtmosphereDensityAtHeight(event.entity.posY);
if(event.entity.worldObj.provider instanceof IPlanetaryProvider) {
Vec3 color = event.entity.worldObj.provider.getSkyColor(event.entity, 0f);
event.red = (float) Math.min(color.xCoord*1.4f,1f);
event.green = (float) Math.min(color.yCoord*1.4f, 1f);
event.blue = (float) Math.min(color.zCoord*1.4f, 1f);
}
if(endTime > 0) {
double amt = (endTime - Minecraft.getMinecraft().theWorld.getTotalWorldTime()) / (double)duration;
if(amt < 0) {
endTime = 0;
}
else
event.green = event.blue = event.red = (float)amt;
} else {
event.red *= fog;
event.green *= fog;
event.blue *= fog;
}
}
}
@SubscribeEvent
public void serverTickEvent(TickEvent.WorldTickEvent event) {
if(zmaster587.advancedRocketry.api.Configuration.allowTerraforming && event.world.provider.getClass() == WorldProviderPlanet.class) {
if(DimensionManager.getInstance().getDimensionProperties(event.world.provider.dimensionId).isTerraformed()) {
List<Chunk> list = ((WorldServer)event.world).theChunkProviderServer.loadedChunks;
if(list.size() > 0) {
for(int i = 0; i < Configuration.terraformingBlockSpeed; i++) {
Chunk chunk = list.get(event.world.rand.nextInt(list.size()));
int coord = event.world.rand.nextInt(256);
int x = (coord & 0xF) + chunk.xPosition*16;
int z = (coord >> 4) + chunk.zPosition*16;
BiomeHandler.changeBiome(event.world, ((WorldProviderPlanet)event.world.provider).chunkMgrTerraformed.getBiomeGenAt(x,z).biomeID, x, z);
}
}
}
}
}
@SubscribeEvent
public void chunkLoadEvent(PopulateChunkEvent.Post event) {
if(zmaster587.advancedRocketry.api.Configuration.allowTerraforming && event.world.provider.getClass() == WorldProviderPlanet.class) {
if(DimensionManager.getInstance().getDimensionProperties(event.world.provider.dimensionId).isTerraformed()) {
Chunk chunk = event.world.getChunkFromChunkCoords(event.chunkX, event.chunkZ);
modifyChunk(event.world, (WorldProviderPlanet) event.world.provider, chunk);
}
}
}
@SubscribeEvent
public void chunkLoadEvent(ChunkEvent.Load event) {
}
public static void modifyChunk(World world ,WorldProviderPlanet provider, Chunk chunk) {
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
BiomeHandler.changeBiome(world, provider.chunkMgrTerraformed.getBiomeGenAt(x + chunk.xPosition*16,z + chunk.zPosition*16).biomeID, chunk, x + chunk.xPosition* 16, z + chunk.zPosition*16);
}
}
}
static final ItemStack component = new ItemStack(AdvancedRocketryItems.itemUpgrade, 1, 4);
@SubscribeEvent
@SideOnly(Side.CLIENT)
public void fogColor(net.minecraftforge.client.event.EntityViewRenderEvent.RenderFogEvent event) {
if(false || event.fogMode == -1) {
return;
}
DimensionProperties properties = DimensionManager.getInstance().getDimensionProperties(event.entity.dimension);
if(properties != null && event.block != Blocks.water && event.block != Blocks.lava) {//& properties.atmosphereDensity > 125) {
float fog = properties.getAtmosphereDensityAtHeight(event.entity.posY);
//GL11.glFogi(GL11.GL_FOG_MODE, GL11.GL_EXP);
GL11.glFogi(GL11.GL_FOG_MODE, GL11.GL_LINEAR);
float f1 = event.farPlaneDistance;
float near;
float far;
int atmosphere = properties.getAtmosphereDensity();
ItemStack armor = Minecraft.getMinecraft().thePlayer.getCurrentArmor(3);
if(armor != null && armor.getItem() instanceof IModularArmor) {
for(ItemStack i : ((IModularArmor)armor.getItem()).getComponents(armor)) {
if(i.isItemEqual(component)) {
atmosphere = Math.min(atmosphere, 100);
break;
}
}
}
//Check environment
if(AtmosphereHandler.currentPressure != -1) {
atmosphere = AtmosphereHandler.currentPressure;
}
if(atmosphere > 100) {
near = 0.75f*f1*(2.00f - atmosphere*atmosphere/10000f);
far = f1;
}
else {
near = 0.75f*f1*(2.00f -atmosphere/100f);
far = f1*(2.002f - atmosphere/100f);
}
GL11.glFogf(GL11.GL_FOG_START, near);
GL11.glFogf(GL11.GL_FOG_END, far);
GL11.glFogf(GL11.GL_FOG_DENSITY, 0);
//event.setCanceled(false);
}
}
//Saves NBT data
@SubscribeEvent
public void worldSaveEvent(WorldEvent.Save event) {
//TODO: save only the one dimension
if(event.world.provider.dimensionId == 0)
//DimensionManager.getInstance().getDimensionProperties(event.world.provider.dimensionId).
DimensionManager.getInstance().saveDimensions(DimensionManager.filePath);
}
//Make sure the player doesnt die on low gravity worlds
@SubscribeEvent
public void fallEvent(LivingFallEvent event) {
if(event.entity.worldObj.provider instanceof IPlanetaryProvider) {
IPlanetaryProvider planet = (IPlanetaryProvider)event.entity.worldObj.provider;
event.distance *= planet.getGravitationalMultiplier((int)event.entity.posX, (int)event.entity.posZ);
}
}
}