package com.xcompwiz.lookingglass.client.proxyworld; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.particle.EffectRenderer; import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.util.ChunkCoordinates; import net.minecraft.util.MathHelper; import com.xcompwiz.lookingglass.api.animator.ICameraAnimator; import com.xcompwiz.lookingglass.api.view.IViewCamera; import com.xcompwiz.lookingglass.api.view.IWorldView; import com.xcompwiz.lookingglass.client.render.FrameBufferContainer; import com.xcompwiz.lookingglass.entity.EntityCamera; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @SideOnly(Side.CLIENT) public class WorldView implements IWorldView { private WorldClient worldObj; public final ChunkCoordinates coords; public final EntityCamera camera; public final IViewCamera camerawrapper; public final int width; public final int height; private boolean update; private boolean ready; private boolean hasChunks; private long last_render_time = -1; private RenderGlobal renderGlobal; private EffectRenderer effectRenderer; private FrameBufferContainer fbo; public WorldView(WorldClient worldObj, ChunkCoordinates coords, int width, int height) { this.width = width; this.height = height; this.worldObj = worldObj; this.coords = coords; this.camera = new EntityCamera(worldObj, coords); this.camerawrapper = new ViewCameraImpl(camera); this.renderGlobal = new RenderGlobal(Minecraft.getMinecraft()); this.effectRenderer = new EffectRenderer(worldObj, Minecraft.getMinecraft().getTextureManager()); // Technically speaking, this is poor practice as it leaks a reference to the view before it's done constructing. this.fbo = FrameBufferContainer.createNewFramebuffer(this, width, height); } /** * Explicitly shuts down the view. Informs the frame buffer manager that we don't want our framebuffer anymore (so it can be cleaned up for certain on the * next cleanup pass) and kills our fbo reference. The view is no longer usable after this is called. */ public void cleanup() { this.fbo = null; FrameBufferContainer.removeWorldView(this); } @Override public boolean isReady() { return fbo == null ? false : ready; } public boolean hasChunks() { return fbo == null ? false : hasChunks; } @Override public void markDirty() { update = true; } public boolean markClean() { if (fbo == null) return false; ready = true; boolean temp = update; update = false; return temp; } public int getFramebuffer() { return fbo == null ? 0 : fbo.getFramebuffer(); } public RenderGlobal getRenderGlobal() { return this.renderGlobal; } public EffectRenderer getEffectRenderer() { return this.effectRenderer; } @Override public int getTexture() { return fbo == null ? 0 : fbo.getTexture(); } @Override public void grab() {} @Override public boolean release() { return false; } public void onChunkReceived(int cx, int cz) { this.hasChunks = true; int cam_cx = MathHelper.floor_double(this.camera.posX) >> 4; int cam_cz = MathHelper.floor_double(this.camera.posZ) >> 4; if (cam_cx >= cx - 1 && cam_cx <= cx + 1 && cam_cz > cz - 1 && cam_cz < cz + 1) this.camera.refreshAnimator(); } public void updateWorldSpawn(ChunkCoordinates cc) { this.camera.updateWorldSpawn(cc); } public void startRender(long renderT) { if (this.last_render_time > 0) this.camera.tick(renderT - this.last_render_time); this.last_render_time = renderT; } @Override public void setAnimator(ICameraAnimator animator) { this.camera.setAnimator(animator); } @Override public IViewCamera getCamera() { return camerawrapper; } /** * This is a really complex bit. As we want to reuse the current client world when rendering, if possible, we need to handle when that world changes. We * could simply destroy all the views pointing to the existing proxy world, but that would be annoying to mods using the API. Instead, we replace our proxy * world with the new client world. This should only be called by LookingGlass, and only from the handling of the client world change detection. * @param world The new world */ public void replaceWorldObject(WorldClient world) { this.worldObj = world; this.camera.worldObj = world; this.effectRenderer.clearEffects(world); this.renderGlobal.setWorldAndLoadRenderers(world); } public WorldClient getWorldObj() { return this.worldObj; } }