Moved Key Events to KeyInputHandler

Added Spectator Menu and Mode to Replay
This commit is contained in:
Marius Metzger
2015-02-01 15:44:55 +01:00
parent 521bf52e79
commit 101a0359d3
13 changed files with 450 additions and 115 deletions

View File

@@ -12,6 +12,7 @@ import java.util.UUID;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.entity.Entity;
import net.minecraft.network.EnumPacketDirection;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.INetHandlerPlayClient;
@@ -26,6 +27,7 @@ import eu.crushedpixel.replaymod.holders.KeyframeComparator;
import eu.crushedpixel.replaymod.holders.Position;
import eu.crushedpixel.replaymod.holders.PositionKeyframe;
import eu.crushedpixel.replaymod.holders.TimeKeyframe;
import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry;
public class ReplayHandler {
@@ -35,7 +37,7 @@ public class ReplayHandler {
private static OpenEmbeddedChannel channel;
private static int realTimelinePosition = 0;
private static Keyframe selectedKeyframe;
private static boolean isReplaying = false;
@@ -49,15 +51,39 @@ public class ReplayHandler {
public static long lastExit = 0;
private static float gamma = 0f;
private static Entity currentEntity = null;
public static void spectateEntity(Entity e) {
currentEntity = e;
mc.setRenderViewEntity(currentEntity);
}
public static Entity getSpectatedEntity() {
return currentEntity;
}
public static void spectateCamera() {
if(currentEntity != null) {
Position prev = new Position(currentEntity);
cameraEntity.movePath(prev);
}
currentEntity = cameraEntity;
mc.setRenderViewEntity(cameraEntity);
}
public static boolean isCamera() {
return currentEntity == cameraEntity;
}
public static void setInitialGamma(float initial) {
gamma = initial;
}
public static float getInitialGamma() {
return gamma;
}
public static void setReplaying(boolean replaying) {
isReplaying = replaying;
}
@@ -73,11 +99,11 @@ public class ReplayHandler {
public static boolean isReplaying() {
return isReplaying;
}
public static void setCameraEntity(CameraEntity entity) {
if(entity == null) return;
cameraEntity = entity;
mc.setRenderViewEntity(cameraEntity);
spectateCamera();
}
public static CameraEntity getCameraEntity() {
@@ -135,7 +161,7 @@ public class ReplayHandler {
}
return size;
}
public static int getTimeKeyframeCount() {
int size = 0;
for(Keyframe kf : keyframes) {
@@ -240,7 +266,7 @@ public class ReplayHandler {
public static void resetKeyframes() {
keyframes = new ArrayList<Keyframe>();
selectKeyframe(null);
}
@@ -249,7 +275,7 @@ public class ReplayHandler {
replaySender.jumpToTime(pos);
}
}
public static boolean isHurrying() {
if(replaySender != null) {
return replaySender.isHurrying();
@@ -299,7 +325,7 @@ public class ReplayHandler {
}
public static void startReplay(File file) throws NoSuchMethodException, SecurityException, NoSuchFieldException {
ChatMessageRequests.initialize();
mc.ingameGUI.getChatGUI().clearChatMessages();
resetKeyframes();
@@ -372,11 +398,11 @@ public class ReplayHandler {
public static Keyframe getSelected() {
return selectedKeyframe;
}
public static int getRealTimelineCursor() {
return realTimelinePosition;
}
public static void setRealTimelineCursor(int pos) {
realTimelinePosition = pos;
}
@@ -385,7 +411,7 @@ public class ReplayHandler {
public static void setLastPosition(Position position) {
lastPosition = position;
}
public static Position getLastPosition() {
return lastPosition;
}

View File

@@ -8,8 +8,8 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
@@ -332,7 +332,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
hasRestarted = false;
}
} catch(EOFException eof) {
} catch(IOException eof) {
setReplaySpeed(0);
}
}

View File

@@ -0,0 +1,233 @@
package eu.crushedpixel.replaymod.replay.screenshot;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.IntBuffer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import javax.imageio.ImageIO;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.shader.Framebuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import eu.crushedpixel.replaymod.chat.ChatMessageRequests;
import eu.crushedpixel.replaymod.chat.ChatMessageRequests.ChatMessageType;
import eu.crushedpixel.replaymod.gui.GuiReplaySaving;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
import eu.crushedpixel.replaymod.utils.ImageUtils;
public class ReplayScreenshot {
private static Minecraft mc = Minecraft.getMinecraft();
private static IntBuffer pixelBuffer;
private static int[] pixelValues;
private static final byte[] uniqueBytes = new byte[]{0,1,1,2,3,5,8};
private static long last_finish = -1;
private static boolean before;
private static double beforeSpeed;
private static GuiScreen beforeScreen;
public static void prepareScreenshot() {
before = mc.gameSettings.hideGUI;
beforeSpeed = ReplayHandler.getSpeed();
beforeScreen = mc.currentScreen;
}
public static void saveScreenshot(Framebuffer buffer) {
try {
GuiReplaySaving.replaySaving = true;
mc.gameSettings.hideGUI = true;
mc.currentScreen = null;
mc.entityRenderer.updateCameraAndRender(0);
ReplayHandler.setSpeed(0);
int width = mc.displayWidth;
int height = mc.displayHeight;
if (OpenGlHelper.isFramebufferEnabled())
{
width = buffer.framebufferTextureWidth;
height = buffer.framebufferTextureHeight;
}
int k = width * height;
if (pixelBuffer == null || pixelBuffer.capacity() < k)
{
pixelBuffer = BufferUtils.createIntBuffer(k);
pixelValues = new int[k];
}
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
pixelBuffer.clear();
if (OpenGlHelper.isFramebufferEnabled()) {
GlStateManager.bindTexture(buffer.framebufferTexture);
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, pixelBuffer);
}
else {
GL11.glReadPixels(0, 0, width, height, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, pixelBuffer);
}
pixelBuffer.get(pixelValues);
TextureUtil.processPixelValues(pixelValues, width, height);
BufferedImage bufferedimage = null;
if (OpenGlHelper.isFramebufferEnabled())
{
bufferedimage = new BufferedImage(buffer.framebufferWidth, buffer.framebufferHeight, 1);
int l = buffer.framebufferTextureHeight - buffer.framebufferHeight;
for (int i1 = l; i1 < buffer.framebufferTextureHeight; ++i1)
{
for (int j1 = 0; j1 < buffer.framebufferWidth; ++j1)
{
bufferedimage.setRGB(j1, i1 - l, pixelValues[i1 * buffer.framebufferTextureWidth + j1]);
}
}
}
else {
bufferedimage = new BufferedImage(width, height, 1);
bufferedimage.setRGB(0, 0, width, height, pixelValues, 0, width);
}
final BufferedImage fbi = bufferedimage;
mc.gameSettings.hideGUI = before;
mc.currentScreen = beforeScreen;
ReplayHandler.setSpeed(beforeSpeed);
//The actual cropping and saving should be executed in a separate thread
Thread ioThread = new Thread(new Runnable() {
@Override
public void run() {
try {
float aspect = 1280f/720f;
Rectangle rect;
if((float)fbi.getWidth()/(float)fbi.getHeight() <= aspect) {
int h = Math.round(fbi.getWidth()/aspect);
int y = (fbi.getHeight()/2) - (h/2);
System.out.println(h+" | "+y);
rect = new Rectangle(0, y, fbi.getWidth(), h);
} else {
int w = Math.round(fbi.getHeight()*aspect);
int x = (fbi.getWidth()/2) - (w/2);
rect = new Rectangle(x, 0, w, fbi.getHeight());
}
final BufferedImage nbi = ImageUtils.cropImage(fbi, rect);
File replayFile = ReplayHandler.getReplayFile();
File folder = new File("./replay_recordings/");
folder.mkdirs();
File temp = File.createTempFile("thumb", null);
int h = 720;
int w = 1280;
//int w = width*(h/height);
BufferedImage img = ImageUtils.scaleImage(nbi, new Dimension(w, h));
ImageIO.write(img, "jpg", temp);
File tempFile = File.createTempFile(replayFile.getName(), null);
tempFile.delete(); tempFile.deleteOnExit();
replayFile.renameTo(tempFile);
replayFile.delete();
replayFile.createNewFile();
byte[] buf = new byte[1024];
ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(replayFile));
FileInputStream fis = new FileInputStream(temp);
ZipEntry entry = zin.getNextEntry();
while (entry != null) {
String name = entry.getName();
if(!name.contains("thumb")) {
// Add ZIP entry to output stream.
zout.putNextEntry(new ZipEntry(name));
// Transfer bytes from the ZIP file to the output file
int len;
while ((len = zin.read(buf)) > 0) {
zout.write(buf, 0, len);
}
}
entry = zin.getNextEntry();
}
zout.putNextEntry(new ZipEntry("thumb"));
int len;
//Add unique bytes to the end of the file
zout.write(uniqueBytes);
while ((len = fis.read(buf)) > 0) {
zout.write(buf, 0, len);
}
// Close the streams
fis.close();
zin.close();
// Compress the files
// Complete the ZIP file
zout.close();
tempFile.delete();
temp.delete();
ChatMessageRequests.addChatMessage("Thumbnail has been successfully saved", ChatMessageType.INFORMATION);
} catch(Exception e) {}
finally {
GuiReplaySaving.replaySaving = false;
}
}
});
ioThread.start();
}
catch (Exception exception) {
mc.gameSettings.hideGUI = before;
mc.currentScreen = beforeScreen;
ReplayHandler.setSpeed(beforeSpeed);
exception.printStackTrace();
ChatMessageRequests.addChatMessage("Thumbnail could not be saved", ChatMessageType.WARNING);
}
last_finish = System.currentTimeMillis();
}
}

View File

@@ -0,0 +1,34 @@
package eu.crushedpixel.replaymod.replay.spectate;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import com.google.common.base.Predicate;
import eu.crushedpixel.replaymod.entities.CameraEntity;
import eu.crushedpixel.replaymod.gui.GuiSpectateSelection;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
public class SpectateHandler {
private static Minecraft mc = Minecraft.getMinecraft();
private static Predicate<EntityPlayer> playerPredicate = new Predicate<EntityPlayer>() {
@Override
public boolean apply(EntityPlayer input) {
if(input instanceof CameraEntity || input == mc.thePlayer) return false;
return true;
}
};
public static void openSpectateSelection() {
if(!ReplayHandler.replayActive()) {
return;
}
List<EntityPlayer> players = mc.theWorld.getEntities(EntityPlayer.class, playerPredicate);
mc.displayGuiScreen(new GuiSpectateSelection(players));
}
}