package com.xcompwiz.lookingglass.proxyworld;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.WorldClient;
import com.xcompwiz.lookingglass.client.proxyworld.ProxyWorldManager;
import com.xcompwiz.lookingglass.log.LoggerUtils;
import com.xcompwiz.lookingglass.render.PerspectiveRenderManager;
import com.xcompwiz.lookingglass.render.WorldViewRenderManager;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import cpw.mods.fml.common.network.FMLNetworkEvent.ClientDisconnectionFromServerEvent;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
/**
* This class handles the FML events. Primarily it is used to listen for tick events.
*/
public class LookingGlassEventHandler {
/** An output stream we can use for proxy world logging */
private final PrintStream printstream;
/** The client world as we last saw it. We use this to check if the client has changed worlds */
@SideOnly(Side.CLIENT)
private WorldClient previousWorld;
/** A simple accumulator to handle triggering freeing world views and such */
@SideOnly(Side.CLIENT)
private int tickcounter;
public LookingGlassEventHandler(File logfile) {
PrintStream stream = null;
try {
stream = new PrintStream(logfile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
printstream = stream;
}
if (printstream == null) throw new RuntimeException("Could not set up debug exception logger file for Proxy World system");
}
@SideOnly(Side.CLIENT)
@SubscribeEvent
public void onClientTick(TickEvent.ClientTickEvent event) {
Minecraft mc = Minecraft.getMinecraft();
// If no client world we're not playing. Abort.
if (mc.theWorld == null) return;
// We don't want to tick twice per tick loop. Just once. We chose to tick at the start of the tick loop.
if (event.phase != TickEvent.Phase.START) return;
// Every now and then we want to check to see if there are frame buffers we could free
if (++this.tickcounter % 200 == 0) ProxyWorldManager.detectFreedWorldViews();
// Handle whenever the client world has changed since we last looked
if (mc.theWorld != previousWorld) {
// We need to handle the removal of the old world. Particularly, the player will still be visible in it.
// We may consider replacing the old client world with a new proxy world.
if (previousWorld != null) previousWorld.removeAllEntities(); //TODO: This is hardly an ideal solution (It also doesn't seem to work well)
previousWorld = mc.theWorld; // At this point we can safely assert that the client world has changed
// We let our local world manager know that the client world changed.
ProxyWorldManager.handleWorldChange(mc.theWorld);
}
// Tick loop for our own worlds.
WorldClient worldBackup = mc.theWorld;
for (WorldClient proxyworld : ProxyWorldManager.getProxyworlds()) {
if (proxyworld.lastLightningBolt > 0) --proxyworld.lastLightningBolt;
if (worldBackup == proxyworld) continue; // This prevents us from double ticking the client world.
try {
mc.theWorld = proxyworld;
//TODO: relays for views (renderGlobal and effectRenderer) (See ProxyWorld.makeFireworks ln23)
proxyworld.tick();
} catch (Exception e) {
LoggerUtils.error("Client Proxy Dim had error while ticking: %s", e.getLocalizedMessage());
e.printStackTrace(printstream);
}
}
mc.theWorld = worldBackup;
}
@SideOnly(Side.CLIENT)
@SubscribeEvent
public void onRenderTick(TickEvent.RenderTickEvent event) {
// If no client world we're not playing. Abort.
if (Minecraft.getMinecraft().theWorld == null) return;
if (event.phase == TickEvent.Phase.START) {
// Anything we need to render for the current frame should happen either during or before the main world render
// Here we call the renderer for "live portal" renders.
PerspectiveRenderManager.onRenderTick(printstream);
return;
}
if (event.phase == TickEvent.Phase.END) {
// We render the world views at the end of the render tick.
WorldViewRenderManager.onRenderTick(printstream);
return;
}
}
@SubscribeEvent
public void onServerTick(TickEvent.ServerTickEvent event) {
if (event.phase != TickEvent.Phase.END) return;
// On server ticks we try to send clients who need chunk data some of that data they need
ChunkFinderManager.instance.tick();
}
@SubscribeEvent
public void onClientDisconnect(ClientDisconnectionFromServerEvent event) {
// Abandon ship!
ProxyWorldManager.clearProxyworlds();
}
}