package joshie.harvest.buildings.render;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import joshie.harvest.buildings.BuildingHelper;
import joshie.harvest.api.buildings.Building;
import joshie.harvest.buildings.HFBuildings;
import joshie.harvest.core.helpers.MCClientHelper;
import joshie.harvest.core.util.annotations.HFEvents;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@HFEvents(Side.CLIENT)
public class PreviewEvent {
//Cache Values
public static final Cache<BuildingKey, BuildingRenderer> CACHE = CacheBuilder.newBuilder().expireAfterWrite(5L, TimeUnit.MINUTES).maximumSize(64).build();
private final BuildingVertexUploader vertexUploader = new BuildingVertexUploader();
private static final float offset = 0.00390625F;
private ItemStack held; //Cache the held itemstack
private Building building; //Cache the building value
private BuildingRenderer getRenderer(World world, EntityPlayerSP player) throws ExecutionException {
if (player == null) return null;
ItemStack stack = player.getHeldItemMainhand();
if (isInvalidStack(stack)) {
stack = player.getHeldItemOffhand();
}
if (isInvalidStack(stack)) return null;
else {
if (stack != held) {
if (stack.getItem() == HFBuildings.BLUEPRINTS) building = HFBuildings.BLUEPRINTS.getObjectFromStack(stack);
else building = HFBuildings.STRUCTURES.getObjectFromStack(stack);
held = stack; //Cache the held item
}
//Attempt the raytrace
RayTraceResult raytrace = BuildingHelper.rayTrace(player, 128, 0F);
if (raytrace == null || raytrace.getBlockPos() == null) return null;
else {
BuildingKey key = BuildingHelper.getPositioning(stack, world, raytrace, building, player, false);
if (key != null) {
return CACHE.get(key, () -> new BuildingRenderer(new BuildingAccess(building, key.getRotation()), key)).setPosition(key.getPos());
}
}
}
//All else fails return null
return null;
}
private boolean isBuildingItem(ItemStack stack) {
return stack.getItem() == HFBuildings.BLUEPRINTS || stack.getItem() == HFBuildings.STRUCTURES;
}
private boolean isInvalidStack(ItemStack stack) {
return stack == null || stack.getItem() == null || !isBuildingItem(stack);
}
private void renderRenderer(EntityPlayerSP player, BuildingRenderer renderer, float partialTick) {
BlockPos pos = renderer.getPos();
GlStateManager.pushMatrix();
double posX = player.prevPosX + (player.posX - player.prevPosX) * partialTick;
double posY = player.prevPosY + (player.posY - player.prevPosY) * partialTick;
double posZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTick;
GlStateManager.translate(-posX + offset, -posY + offset, -posZ + offset);
GlStateManager.translate(pos.getX(), pos.getY(), pos.getZ());
renderer.draw(vertexUploader);
GlStateManager.translate(-pos.getX(), -pos.getY(), -pos.getZ());
GlStateManager.translate(posX, posY, posZ);
GlStateManager.popMatrix();
}
/** Borrowed from SettlerCraft by @InfinityRaider **/
@SubscribeEvent
public void renderBuildingPreview(RenderWorldLastEvent event) throws ExecutionException {
EntityPlayerSP player = MCClientHelper.getPlayer();
BuildingRenderer renderer = getRenderer(player.worldObj, player);
if (renderer != null) {
renderRenderer(player, renderer, event.getPartialTicks());
}
}
}