package micdoodle8.mods.galacticraft.core;
import micdoodle8.mods.galacticraft.api.entity.IAntiGrav;
import micdoodle8.mods.galacticraft.api.entity.ICameraZoomEntity;
import micdoodle8.mods.galacticraft.api.item.IArmorGravity;
import micdoodle8.mods.galacticraft.api.prefab.entity.EntitySpaceshipBase;
import micdoodle8.mods.galacticraft.api.world.IGalacticraftWorldProvider;
import micdoodle8.mods.galacticraft.api.world.IOrbitDimension;
import micdoodle8.mods.galacticraft.api.world.IZeroGDimension;
import micdoodle8.mods.galacticraft.core.client.FootprintRenderer;
import micdoodle8.mods.galacticraft.core.client.SkyProviderOverworld;
import micdoodle8.mods.galacticraft.core.dimension.WorldProviderMoon;
import micdoodle8.mods.galacticraft.core.dimension.WorldProviderSpaceStation;
import micdoodle8.mods.galacticraft.core.entities.player.EnumGravity;
import micdoodle8.mods.galacticraft.core.entities.player.GCPlayerStatsClient;
import micdoodle8.mods.galacticraft.core.proxy.ClientProxyCore;
import micdoodle8.mods.galacticraft.core.util.*;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.passive.EntityChicken;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.IWorldGenerator;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.opengl.GL11;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import static micdoodle8.mods.galacticraft.core.proxy.ClientProxyCore.PLAYER_Y_OFFSET;
import static micdoodle8.mods.galacticraft.core.proxy.ClientProxyCore.submergedTextures;
/**
* These methods are called from vanilla minecraft through bytecode injection done in MicdoodleCore
*
* See https://github.com/micdoodle8/MicdoodleCore
*/
public class TransformerHooks
{
private static IWorldGenerator generatorGCGreg = null;
private static IWorldGenerator generatorCoFH = null;
private static IWorldGenerator generatorDenseOres = null;
private static IWorldGenerator generatorTCAuraNodes = null;
private static IWorldGenerator generatorAE2meteors = null;
private static Method generateTCAuraNodes = null;
private static boolean generatorsInitialised = false;
public static double getGravityForEntity(Entity entity)
{
if (entity.worldObj.provider instanceof IGalacticraftWorldProvider)
{
if (entity instanceof EntityChicken && !OxygenUtil.isAABBInBreathableAirBlock(entity.worldObj, entity.getEntityBoundingBox()))
{
return 0.08D;
}
final IGalacticraftWorldProvider customProvider = (IGalacticraftWorldProvider) entity.worldObj.provider;
if (entity instanceof EntityPlayer)
{
EntityPlayer player = (EntityPlayer) entity;
if (player.inventory != null)
{
int armorModLowGrav = 100;
int armorModHighGrav = 100;
for (int i = 0; i < 4; i++)
{
ItemStack armorPiece = player.getCurrentArmor(i);
if (armorPiece != null && armorPiece.getItem() instanceof IArmorGravity)
{
armorModLowGrav -= ((IArmorGravity) armorPiece.getItem()).gravityOverrideIfLow(player);
armorModHighGrav -= ((IArmorGravity) armorPiece.getItem()).gravityOverrideIfHigh(player);
}
}
if (armorModLowGrav > 100)
{
armorModLowGrav = 100;
}
if (armorModHighGrav > 100)
{
armorModHighGrav = 100;
}
if (armorModLowGrav < 0)
{
armorModLowGrav = 0;
}
if (armorModHighGrav < 0)
{
armorModHighGrav = 0;
}
if (customProvider.getGravity() > 0)
{
return 0.08D - (customProvider.getGravity() * armorModLowGrav) / 100;
}
return 0.08D - (customProvider.getGravity() * armorModHighGrav) / 100;
}
}
return 0.08D - customProvider.getGravity();
}
else if (entity instanceof IAntiGrav)
{
return 0;
}
else
{
return 0.08D;
}
}
public static double getItemGravity(EntityItem e)
{
if (e.worldObj.provider instanceof IGalacticraftWorldProvider)
{
final IGalacticraftWorldProvider customProvider = (IGalacticraftWorldProvider) e.worldObj.provider;
return Math.max(0.002D, 0.03999999910593033D - (customProvider instanceof IOrbitDimension ? 0.05999999910593033D : customProvider.getGravity()) / 1.75D);
}
else
{
return 0.03999999910593033D;
}
}
public static float getArrowGravity(EntityArrow e)
{
if (e.worldObj.provider instanceof IGalacticraftWorldProvider)
{
return ((IGalacticraftWorldProvider)e.worldObj.provider).getArrowGravity();
}
else
{
return 0.05F;
}
}
public static float getRainStrength(World world, float partialTicks)
{
if (world.isRemote)
{
if (world.provider.getSkyRenderer() instanceof SkyProviderOverworld)
{
return 0.0F;
}
}
return world.prevRainingStrength + (world.rainingStrength - world.prevRainingStrength) * partialTicks;
}
public static boolean otherModPreventGenerate(int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
{
if (!(world.provider instanceof IGalacticraftWorldProvider))
{
return false;
}
if (world.provider instanceof WorldProviderSpaceStation)
{
return true;
}
if (ConfigManagerCore.enableOtherModsFeatures)
{
return false;
}
if (!generatorsInitialised)
{
generatorsInitialised = true;
try
{
Class GCGreg = Class.forName("bloodasp.galacticgreg.GT_Worldgenerator_Space");
if (GCGreg != null)
{
final Field regField = GameRegistry.class.getDeclaredField("worldGenerators");
regField.setAccessible(true);
Set<IWorldGenerator> registeredGenerators = (Set<IWorldGenerator>) regField.get(null);
for (IWorldGenerator gen : registeredGenerators)
{
if (GCGreg.isInstance(gen))
{
generatorGCGreg = gen;
break;
}
}
}
}
catch (Exception e)
{
}
try
{
Class cofh = Class.forName("cofh.core.world.WorldHandler");
if (cofh != null && ConfigManagerCore.whitelistCoFHCoreGen)
{
final Field regField = GameRegistry.class.getDeclaredField("worldGenerators");
regField.setAccessible(true);
Set<IWorldGenerator> registeredGenerators = (Set<IWorldGenerator>) regField.get(null);
for (IWorldGenerator gen : registeredGenerators)
{
if (cofh.isInstance(gen))
{
generatorCoFH = gen;
break;
}
}
}
}
catch (Exception e)
{
}
try
{
Class denseOres = Class.forName("com.rwtema.denseores.WorldGenOres");
if (denseOres != null)
{
final Field regField = GameRegistry.class.getDeclaredField("worldGenerators");
regField.setAccessible(true);
Set<IWorldGenerator> registeredGenerators = (Set<IWorldGenerator>) regField.get(null);
for (IWorldGenerator gen : registeredGenerators)
{
if (denseOres.isInstance(gen))
{
generatorDenseOres = gen;
break;
}
}
}
}
catch (Exception e)
{
}
try
{
Class ae2meteorPlace = null;
try
{
ae2meteorPlace = Class.forName("appeng.hooks.MeteoriteWorldGen");
}
catch (ClassNotFoundException e)
{
}
if (ae2meteorPlace == null)
{
try
{
ae2meteorPlace = Class.forName("appeng.worldgen.MeteoriteWorldGen");
}
catch (ClassNotFoundException e)
{
}
}
if (ae2meteorPlace != null)
{
final Field regField = GameRegistry.class.getDeclaredField("worldGenerators");
regField.setAccessible(true);
Set<IWorldGenerator> registeredGenerators = (Set<IWorldGenerator>) regField.get(null);
for (IWorldGenerator gen : registeredGenerators)
{
if (ae2meteorPlace.isInstance(gen))
{
generatorAE2meteors = gen;
break;
}
}
}
}
catch (Exception e)
{
}
try
{
Class genThaumCraft = Class.forName("thaumcraft.common.lib.world.ThaumcraftWorldGenerator");
if (genThaumCraft != null)
{
final Field regField = GameRegistry.class.getDeclaredField("worldGenerators");
regField.setAccessible(true);
Set<IWorldGenerator> registeredGenerators = (Set<IWorldGenerator>) regField.get(null);
for (IWorldGenerator gen : registeredGenerators)
{
if (genThaumCraft.isInstance(gen))
{
generatorTCAuraNodes = gen;
break;
}
}
if (generatorTCAuraNodes != null && ConfigManagerCore.enableThaumCraftNodes)
{
generateTCAuraNodes = genThaumCraft.getDeclaredMethod("generateWildNodes", World.class, Random.class, int.class, int.class, boolean.class, boolean.class);
generateTCAuraNodes.setAccessible(true);
}
}
}
catch (Exception e)
{
}
if (generatorGCGreg != null)
{
GCLog.info("Whitelisting GalacticGreg oregen on planets.");
}
if (generatorCoFH != null)
{
GCLog.info("Whitelisting CoFHCore custom oregen on planets.");
}
if (generatorDenseOres != null)
{
GCLog.info("Whitelisting Dense Ores oregen on planets.");
}
if (generatorAE2meteors != null)
{
GCLog.info("Whitelisting AE2 meteorites worldgen on planets.");
}
if (generatorTCAuraNodes != null && generateTCAuraNodes != null)
{
GCLog.info("Whitelisting ThaumCraft aura node generation on planets.");
}
}
if (generatorGCGreg != null || generatorCoFH != null || generatorDenseOres != null || generatorTCAuraNodes != null || generatorAE2meteors != null)
{
try
{
long worldSeed = world.getSeed();
Random fmlRandom = new Random(worldSeed);
long xSeed = fmlRandom.nextLong() >> 2 + 1L;
long zSeed = fmlRandom.nextLong() >> 2 + 1L;
long chunkSeed = (xSeed * chunkX + zSeed * chunkZ) ^ worldSeed;
fmlRandom.setSeed(chunkSeed);
if (generatorCoFH != null)
{
generatorCoFH.generate(fmlRandom, chunkX, chunkZ, world, chunkGenerator, chunkProvider);
}
if (generatorDenseOres != null)
{
generatorDenseOres.generate(fmlRandom, chunkX, chunkZ, world, chunkGenerator, chunkProvider);
}
if (generatorGCGreg != null)
{
generatorGCGreg.generate(fmlRandom, chunkX, chunkZ, world, chunkGenerator, chunkProvider);
}
if (generatorAE2meteors != null)
{
generatorAE2meteors.generate(fmlRandom, chunkX, chunkZ, world, chunkGenerator, chunkProvider);
}
if (generateTCAuraNodes != null)
{
generateTCAuraNodes.invoke(generatorTCAuraNodes, world, fmlRandom, chunkX, chunkZ, false, true);
}
}
catch (Exception e)
{
GCLog.severe("Error in another mod's worldgen. This is NOT a Galacticraft bug.");
e.printStackTrace();
}
}
return true;
}
@SideOnly(Side.CLIENT)
public static float getWorldBrightness(WorldClient world)
{
if (world.provider instanceof WorldProviderMoon)
{
float f1 = world.getCelestialAngle(1.0F);
float f2 = 1.0F - (MathHelper.cos(f1 * Constants.twoPI) * 2.0F + 0.2F);
if (f2 < 0.0F)
{
f2 = 0.0F;
}
if (f2 > 1.0F)
{
f2 = 1.0F;
}
f2 = 1.0F - f2;
return f2 * 0.8F;
}
return world.getSunBrightness(1.0F);
}
@SideOnly(Side.CLIENT)
public static float getColorRed(World world)
{
return (float) WorldUtil.getWorldColor(world).x;
}
@SideOnly(Side.CLIENT)
public static float getColorGreen(World world)
{
return (float) WorldUtil.getWorldColor(world).y;
}
@SideOnly(Side.CLIENT)
public static float getColorBlue(World world)
{
return (float) WorldUtil.getWorldColor(world).z;
}
@SideOnly(Side.CLIENT)
public static Vec3 getFogColorHook(World world)
{
EntityPlayerSP player = FMLClientHandler.instance().getClient().thePlayer;
if (world.provider.getSkyRenderer() instanceof SkyProviderOverworld)
{
float var20 = ((float) (player.posY) - Constants.OVERWORLD_SKYPROVIDER_STARTHEIGHT) / 1000.0F;
var20 = MathHelper.sqrt_float(var20);
final float var21 = Math.max(1.0F - var20 * 40.0F, 0.0F);
Vec3 vec = world.getFogColor(1.0F);
return new Vec3(vec.xCoord * Math.max(1.0F - var20 * 1.29F, 0.0F), vec.yCoord * Math.max(1.0F - var20 * 1.29F, 0.0F), vec.zCoord * Math.max(1.0F - var20 * 1.29F, 0.0F));
}
return world.getFogColor(1.0F);
}
@SideOnly(Side.CLIENT)
public static Vec3 getSkyColorHook(World world)
{
EntityPlayerSP player = FMLClientHandler.instance().getClient().thePlayer;
if (world.provider.getSkyRenderer() instanceof SkyProviderOverworld || (player != null && player.posY > Constants.OVERWORLD_CLOUD_HEIGHT && player.ridingEntity instanceof EntitySpaceshipBase))
{
float f1 = world.getCelestialAngle(1.0F);
float f2 = MathHelper.cos(f1 * Constants.twoPI) * 2.0F + 0.5F;
if (f2 < 0.0F)
{
f2 = 0.0F;
}
if (f2 > 1.0F)
{
f2 = 1.0F;
}
int i = MathHelper.floor_double(player.posX);
int j = MathHelper.floor_double(player.posY);
int k = MathHelper.floor_double(player.posZ);
BlockPos pos = new BlockPos(i, j, k);
int l = ForgeHooksClient.getSkyBlendColour(world, pos);
float f4 = (float) (l >> 16 & 255) / 255.0F;
float f5 = (float) (l >> 8 & 255) / 255.0F;
float f6 = (float) (l & 255) / 255.0F;
f4 *= f2;
f5 *= f2;
f6 *= f2;
if (player.posY <= Constants.OVERWORLD_SKYPROVIDER_STARTHEIGHT)
{
Vec3 vec = world.getSkyColor(FMLClientHandler.instance().getClient().getRenderViewEntity(), 1.0F);
double blend = (player.posY - Constants.OVERWORLD_CLOUD_HEIGHT) / (Constants.OVERWORLD_SKYPROVIDER_STARTHEIGHT - Constants.OVERWORLD_CLOUD_HEIGHT);
double ablend = 1 - blend;
return new Vec3(f4 * blend + vec.xCoord * ablend, f5 * blend + vec.yCoord * ablend, f6 * blend + vec.zCoord * ablend);
}
else
{
double blend = Math.min(1.0D, (player.posY - Constants.OVERWORLD_SKYPROVIDER_STARTHEIGHT) / 300.0D);
double ablend = 1.0D - blend;
blend /= 255.0D;
return new Vec3(f4 * ablend + blend * 31.0D, f5 * ablend + blend * 8.0D, f6 * ablend + blend * 99.0D);
}
}
return world.getSkyColor(FMLClientHandler.instance().getClient().getRenderViewEntity(), 1.0F);
}
@SideOnly(Side.CLIENT)
public static double getRenderPosY(Entity viewEntity, double regular)
{
if (viewEntity.posY >= 256)
{
return 255.0F;
}
else
{
return regular + viewEntity.getEyeHeight();
}
}
@SideOnly(Side.CLIENT)
public static boolean shouldRenderFire(Entity entity)
{
if (entity.worldObj == null || !(entity.worldObj.provider instanceof IGalacticraftWorldProvider))
{
return entity.isBurning();
}
if (!(entity instanceof EntityLivingBase) && !(entity instanceof EntityArrow))
{
return entity.isBurning();
}
if (entity.isBurning())
{
if (OxygenUtil.noAtmosphericCombustion(entity.worldObj.provider))
{
return OxygenUtil.isAABBInBreathableAirBlock(entity.worldObj, entity.getEntityBoundingBox());
}
else
{
return true;
}
//Disable fire on Galacticraft worlds with no oxygen
}
return false;
}
@SideOnly(Side.CLIENT)
public static void orientCamera(float partialTicks)
{
EntityPlayerSP player = ClientProxyCore.mc.thePlayer;
GCPlayerStatsClient stats = GCPlayerStatsClient.get(player);
Entity viewEntity = ClientProxyCore.mc.getRenderViewEntity();
if (player.ridingEntity instanceof ICameraZoomEntity && ClientProxyCore.mc.gameSettings.thirdPersonView == 0)
{
Entity entity = player.ridingEntity;
float offset = ((ICameraZoomEntity)entity).getRotateOffset();
if (offset > -10F)
{
offset += PLAYER_Y_OFFSET;
GL11.glTranslatef(0, -offset, 0);
float anglePitch = entity.prevRotationPitch + (entity.rotationPitch - entity.prevRotationPitch) * partialTicks;
float angleYaw = entity.prevRotationYaw + (entity.rotationYaw - entity.prevRotationYaw) * partialTicks;
GL11.glRotatef(-anglePitch, 0.0F, 0.0F, 1.0F);
GL11.glRotatef(angleYaw, 0.0F, 1.0F, 0.0F);
GL11.glTranslatef(0, offset, 0);
}
}
if (viewEntity instanceof EntityLivingBase && viewEntity.worldObj.provider instanceof IZeroGDimension && !((EntityLivingBase)viewEntity).isPlayerSleeping())
{
float pitch = viewEntity.prevRotationPitch + (viewEntity.rotationPitch - viewEntity.prevRotationPitch) * partialTicks;
float yaw = viewEntity.prevRotationYaw + (viewEntity.rotationYaw - viewEntity.prevRotationYaw) * partialTicks + 180.0F;
float eyeHeightChange = viewEntity.width / 2.0F;
// GL11.glTranslatef(0.0F, -f1, 0.0F);
GL11.glRotatef(-yaw, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(-pitch, 1.0F, 0.0F, 0.0F);
GL11.glTranslatef(0.0F, 0.0F, 0.1F);
EnumGravity gDir = stats.getGdir();
GL11.glRotatef(180.0F * gDir.getThetaX(), 1.0F, 0.0F, 0.0F);
GL11.glRotatef(180.0F * gDir.getThetaZ(), 0.0F, 0.0F, 1.0F);
GL11.glRotatef(pitch * gDir.getPitchGravityX(), 1.0F, 0.0F, 0.0F);
GL11.glRotatef(pitch * gDir.getPitchGravityY(), 0.0F, 1.0F, 0.0F);
GL11.glRotatef(yaw * gDir.getYawGravityX(), 1.0F, 0.0F, 0.0F);
GL11.glRotatef(yaw * gDir.getYawGravityY(), 0.0F, 1.0F, 0.0F);
GL11.glRotatef(yaw * gDir.getYawGravityZ(), 0.0F, 0.0F, 1.0F);
// GL11.glTranslatef(sneakY * gDir.getSneakVecX(), sneakY * gDir.getSneakVecY(), sneakY * gDir.getSneakVecZ());
GL11.glTranslatef(eyeHeightChange * gDir.getEyeVecX(), eyeHeightChange * gDir.getEyeVecY(), eyeHeightChange * gDir.getEyeVecZ());
if (stats.getGravityTurnRate() < 1.0F)
{
GL11.glRotatef(90.0F * (stats.getGravityTurnRatePrev() + (stats.getGravityTurnRate() - stats.getGravityTurnRatePrev()) * partialTicks), stats.getGravityTurnVecX(), stats.getGravityTurnVecY(), stats.getGravityTurnVecZ());
}
}
//omit this for interesting 3P views
// GL11.glTranslatef(0.0F, 0.0F, -0.1F);
// GL11.glRotatef(pitch, 1.0F, 0.0F, 0.0F);
// GL11.glRotatef(yaw, 0.0F, 1.0F, 0.0F);
// GL11.glTranslatef(0.0F, f1, 0.0F);
}
@SideOnly(Side.CLIENT)
public static void renderLiquidOverlays(float partialTicks)
{
boolean within = false;
for (Map.Entry<Fluid, ResourceLocation> entry : submergedTextures.entrySet())
{
if (FluidUtil.isInsideOfFluid(ClientProxyCore.mc.thePlayer, entry.getKey()))
{
within = true;
ClientProxyCore.mc.getTextureManager().bindTexture(entry.getValue());
break;
}
}
if (!within)
{
return;
}
Tessellator tessellator = Tessellator.getInstance();
float f1 = ClientProxyCore.mc.thePlayer.getBrightness(partialTicks) / 3.0F;
GL11.glColor4f(f1, f1, f1, 1.0F);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glPushMatrix();
float f2 = 4.0F;
float f3 = -1.1F;
float f4 = 1.1F;
float f5 = -1.1F;
float f6 = 1.1F;
float f7 = -0.25F;
float f8 = -ClientProxyCore.mc.thePlayer.rotationYaw / 64.0F;
float f9 = ClientProxyCore.mc.thePlayer.rotationPitch / 64.0F;
WorldRenderer worldRenderer = tessellator.getWorldRenderer();
worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
worldRenderer.pos(f3, f5, f7).tex(f2 + f8, f2 + f9).endVertex();
worldRenderer.pos(f4, f5, f7).tex(0.0F + f8, f2 + f9).endVertex();
worldRenderer.pos(f4, f6, f7).tex(0.0F + f8, 0.0F + f9).endVertex();
worldRenderer.pos(f3, f6, f7).tex(f2 + f8, 0.0F + f9).endVertex();
tessellator.draw();
GL11.glPopMatrix();
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glDisable(GL11.GL_BLEND);
}
@SideOnly(Side.CLIENT)
public static void renderFootprints(float partialTicks)
{
FootprintRenderer.renderFootprints(ClientProxyCore.mc.thePlayer, partialTicks);
MinecraftForge.EVENT_BUS.post(new ClientProxyCore.EventSpecialRender(partialTicks));
}
}